Skip to content

feat(deploy): add OpenShift/K8s deployment manifests#5880

Merged
singlerider merged 2 commits intozeroclaw-labs:masterfrom
pavelanni:feature/k8s-deployment
Apr 20, 2026
Merged

feat(deploy): add OpenShift/K8s deployment manifests#5880
singlerider merged 2 commits intozeroclaw-labs:masterfrom
pavelanni:feature/k8s-deployment

Conversation

@pavelanni
Copy link
Copy Markdown
Contributor

@pavelanni pavelanni commented Apr 18, 2026

Summary

  • Base branch: master (all contributions)
  • What changed and why:
    • For running multiple agents on a production Kubernetes/OpenShift cluster we heed a set of Kubernetes YAML manifests that can configure and deploy ZeroClaw at scale. This PR adds all necessary YAML manifests and a README file explaining how to use them.
    • Includes Namespace, Secret, ConfigMap, Deployment, Service, and OpenShift Route with edge TLS
    • Adds ZeroClaw configuration for an external LLM provider (Anthropic, OpenAI, or compatible)
    • Adds hardened SecurityContext: runAsNonRoot, drop all capabilities, read-only root filesystem, seccomp RuntimeDefault
  • Scope boundary: No changes in the source code; all changes are collected in a single new directory deploy-k8s
  • Blast radius: minimal
  • Linked issue(s): N/A

Security & Privacy Impact (required)

Yes/No for each. Answer any Yes with a 1–2 sentence explanation.

  • New permissions, capabilities, or file system access scope? No
  • New external network calls? No
  • Secrets / tokens / credentials handling changed? No
  • PII, real identities, or personal data in diff, tests, fixtures, or docs? No
  • If any Yes, describe the risk and mitigation:

Compatibility (required)

  • Backward compatible? Yes
  • Config / env / CLI surface changed? No

Label Snapshot

  • labels shoud be: risk: low and size: S but I don't have permissions to change them. Please, @theonlyhennygod and @singlerider update the labels.

Change Metadata

  • Change type: feature

Privace and Data Hygiene

  • N/A

i18n Follow-Through

  • N/A

Side Effects / Blast Radius

  • affected subsystems: deploy-k8s/ subtree only, no runtime changes

Rollback Plan

— git revert removes the subtree, no side effects

Validation Evidence (required)

NOTE: the clippy error is a pre-existing upstream issue not introduced by this PR, and that CI on this branch passes.

❯ cargo fmt --all -- --check
cargo clippy --all-targets -- -D warnings
cargo test
    Checking zeroclaw-config v0.7.1 (/Users/panni/work/experiments/forks/zeroclaw/crates/zeroclaw-config)
error: this `if` can be collapsed into the outer `match`
   --> crates/zeroclaw-config/src/policy.rs:552:25
    |
552 | /                         if chars.next_if_eq(&'&').is_none() {
553 | |                             return true;
554 | |                         }
    | |_________________________^
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.95.0/index.html#collapsible_match
    = note: `-D clippy::collapsible-match` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::collapsible_match)]`
help: collapse nested if block
    |
551 ~                     '&'
552 ~                         if chars.next_if_eq(&'&').is_none() => {
553 |                             return true;
554 ~                         }
    |

error: could not compile `zeroclaw-config` (lib) due to 1 previous error
    Finished [`test` profile [unoptimized + debuginfo]](https://doc.rust-lang.org/cargo/reference/profiles.html#default-profiles) target(s) in 0.65s
     Running unittests src/lib.rs (target/debug/deps/zeroclaw-1ec7c000838db0bf)

running 230 tests
test approval::tests::auto_approve_tools_skip_prompt ... ok
test approval::tests::full_autonomy_never_prompts ... ok
test approval::tests::always_ask_tools_always_prompt ... ok
test approval::tests::interactive_manager_reports_interactive ... ok
test approval::tests::non_interactive_allows_default_auto_approve_tools ... ok
test approval::tests::always_ask_overrides_auto_approve ... ok
test approval::tests::non_interactive_always_ask_tools_need_approval ... ok
test approval::tests::non_interactive_auto_approve_tools_skip_approval ... ok
test approval::tests::non_interactive_denies_unknown_tools ... ok
test approval::tests::non_interactive_full_autonomy_never_needs_approval ... ok
test approval::tests::non_interactive_manager_reports_non_interactive ... ok
test approval::tests::approval_response_serde_roundtrip ... ok
test approval::tests::non_interactive_readonly_never_needs_approval ... ok
test approval::tests::approval_request_serde ... ok
test approval::tests::non_interactive_shell_skips_outer_approval_by_default ... ok
test approval::tests::non_interactive_unknown_tools_need_approval_in_supervised ... ok
test approval::tests::non_interactive_weather_is_auto_approved ... ok
test approval::tests::readonly_never_prompts ... ok
test approval::tests::summarize_args_non_object ... ok
test approval::tests::summarize_args_object ... ok
test approval::tests::summarize_args_truncates_long_values ... ok
test approval::tests::always_response_adds_to_session_allowlist ... ok
test approval::tests::non_interactive_always_ask_overrides_session_allowlist ... ok
test approval::tests::audit_log_contains_timestamp_and_channel ... ok
test approval::tests::unknown_tool_needs_approval_in_supervised ... ok
test approval::tests::yes_response_does_not_add_to_allowlist ... ok
test approval::tests::always_ask_overrides_session_allowlist ... ok
test approval::tests::non_interactive_session_allowlist_still_works ... ok
test approval::tests::summarize_args_unicode_safe_truncation ... ok
test approval::tests::audit_log_records_decisions ... ok
test commands::update::tests::detect_arch_too_short ... ok
test commands::update::tests::current_target_triple_is_not_empty ... ok
test commands::update::tests::detect_arch_elf_x86_64 ... ok
test commands::update::tests::detect_arch_macho_aarch64 ... ok
test commands::update::tests::detect_arch_elf_aarch64 ... ok
test commands::update::tests::detect_arch_macho_x86_64 ... ok
test commands::update::tests::detect_arch_unknown_format ... ok
test commands::update::tests::host_architecture_is_known ... ok
test commands::update::tests::find_asset_url_returns_none_for_empty_assets ... ok
test commands::update::tests::find_asset_url_returns_none_for_missing_assets ... ok
test config::tests::reexported_channel_configs_are_constructible ... ok
test commands::update::tests::find_asset_url_picks_correct_gnu_over_android ... ok
test hands::tests::load_hands_nonexistent_dir ... ok
test commands::update::tests::test_version_comparison ... ok
test config::tests::reexported_config_default_is_constructible ... ok
test hands::types::tests::context_caps_history_at_max ... ok
test hands::types::tests::context_deduplicates_learned_facts ... ok
test hands::types::tests::context_new_is_empty ... ok
test hands::types::tests::context_record_failed_run_does_not_increment_total ... ok
test hands::types::tests::context_record_run_increments_counters ... ok
test hands::tests::load_hands_empty_dir ... ok
test hands::tests::load_context_returns_fresh_when_missing ... ok
test hands::types::tests::context_json_roundtrip ... ok
test hands::tests::load_hands_ignores_non_toml_files ... ok
test hands::types::tests::hand_deserializes_full_toml ... ok
test hands::types::tests::hand_roundtrip_json ... ok
test hands::types::tests::hand_deserializes_from_toml ... ok
test hands::tests::context_roundtrip_through_filesystem ... ok
test hands::types::tests::hand_run_status_serde_roundtrip ... ok
test hands::types::tests::most_recent_run_is_first_in_history ... ok
test commands::update::tests::extract_tar_gz_errors_on_missing_binary ... ok
test hands::tests::save_context_creates_directory ... ok
test health::tests::mark_component_ok_initializes_component_state ... ok
test health::tests::bump_component_restart_increments_counter ... ok
test health::tests::mark_component_error_then_ok_clears_last_error ... ok
test health::tests::snapshot_json_contains_registered_component_fields ... ok
test hands::tests::load_hands_skips_malformed_files ... ok
test hands::tests::load_hands_parses_valid_files ... ok
test commands::update::tests::extract_tar_gz_finds_binary ... ok
test heartbeat::tests::heartbeat_engine_is_constructible_via_module_export ... ok
test memory::battle_tests::tests::conflict_detection_skips_non_core ... ok
test memory::battle_tests::tests::conflict_detection_skips_already_superseded ... ok
test memory::battle_tests::tests::conflict_detection_identical_content_not_flagged ... ok
test hands::tests::save_then_load_preserves_multiple_runs ... ok
test memory::battle_tests::tests::importance_empty_content ... ok
test memory::battle_tests::tests::importance_core_higher_than_daily ... ok
test memory::battle_tests::tests::deterministic_tiebreaker_in_hybrid_merge ... ok
test memory::battle_tests::tests::importance_keywords_increase_score ... ok
test memory::battle_tests::tests::importance_score_stays_in_bounds ... ok
test memory::battle_tests::tests::jaccard_similarity_case_sensitive ... ok
test memory::battle_tests::tests::jaccard_similarity_identical ... ok
test memory::battle_tests::tests::jaccard_similarity_no_overlap ... ok
test memory::battle_tests::tests::memory_entry_deserialize_without_new_fields_uses_defaults ... ok
test memory::battle_tests::tests::memory_entry_serde_roundtrip_with_new_fields ... ok
test heartbeat::tests::ensure_heartbeat_file_creates_expected_file ... ok
test memory::battle_tests::tests::audit_with_namespaced_operations ... ok
test memory::battle_tests::tests::audit_logs_all_operation_types ... ok
test memory::battle_tests::tests::audit_concurrent_operations ... ok
test memory::battle_tests::tests::empty_namespace_recall_returns_nothing ... ok
test memory::battle_tests::tests::importance_persists_in_sqlite ... ok
test memory::battle_tests::tests::namespace_default_assignment ... ok
test memory::battle_tests::tests::policy_custom_category_retention ... ok
test memory::battle_tests::tests::policy_quota_boundary_conditions ... ok
test memory::battle_tests::tests::policy_read_only_multiple_namespaces ... ok
test memory::battle_tests::tests::policy_validate_store_rejects_read_only ... ok
test memory::battle_tests::tests::policy_zero_quota_means_unlimited ... ok
test memory::battle_tests::tests::forget_cleans_up_namespaced_entry ... ok
test memory::battle_tests::tests::namespace_empty_string_works ... ok
test memory::battle_tests::tests::full_lifecycle_store_recall_supersede ... ok
test memory::battle_tests::tests::importance_survives_upsert ... ok
test memory::battle_tests::tests::namespace_isolation_with_session_id_cross_filter ... ok
test memory::battle_tests::tests::namespace_survives_upsert ... ok
test memory::battle_tests::tests::audit_wrapping_sqlite_backend ... ok
test memory::battle_tests::tests::namespace_isolation_between_agents ... ok
test memory::battle_tests::tests::weighted_final_score_all_ones ... ok
test memory::battle_tests::tests::weighted_final_score_all_zeros ... ok
test memory::battle_tests::tests::weighted_final_score_hybrid_dominant ... ok
test memory::cli::tests::parse_category_custom_fallback ... ok
test memory::cli::tests::parse_category_known_variants ... ok
test memory::cli::tests::truncate_content_empty_string ... ok
test memory::cli::tests::truncate_content_long_text_truncated ... ok
test memory::cli::tests::truncate_content_multiline_uses_first_line ... ok
test memory::cli::tests::truncate_content_short_text_unchanged ... ok
test memory::traits::tests::memory_category_custom_roundtrip ... ok
test memory::traits::tests::memory_category_display_outputs_expected_values ... ok
test memory::traits::tests::memory_category_serde_uses_snake_case ... ok
test memory::traits::tests::memory_entry_roundtrip_preserves_optional_fields ... ok
test observability::tests::factory_empty_string_falls_back_to_noop ... ok
test observability::tests::factory_garbage_falls_back_to_noop ... ok
test observability::tests::factory_log_returns_log ... ok
test observability::tests::factory_none_returns_noop ... ok
test observability::tests::factory_noop_returns_noop ... ok
test observability::tests::factory_opentelemetry_alias ... ok
test observability::tests::factory_otel_returns_otel ... ok
test observability::tests::factory_otlp_alias ... ok
test observability::tests::factory_prometheus_returns_prometheus ... ok
test observability::tests::factory_unknown_falls_back_to_noop ... ok
test observability::tests::factory_verbose_returns_verbose ... ok
test onboard::tests::wizard_functions_are_reexported ... ok
test platform::tests::factory_cloudflare_errors ... ok
test platform::tests::factory_docker ... ok
test platform::tests::factory_empty_errors ... ok
test platform::tests::factory_native ... ok
test platform::tests::factory_unknown_errors ... ok
test providers::traits::tests::build_tool_instructions_text_empty ... ok
test providers::traits::tests::build_tool_instructions_text_format ... ok
test providers::traits::tests::chat_message_constructors ... ok
test providers::traits::tests::chat_response_helpers ... ok
test providers::traits::tests::chat_response_with_usage ... ok
test providers::traits::tests::conversation_message_variants ... ok
test providers::traits::tests::provider_capabilities_default ... ok
test providers::traits::tests::provider_capabilities_equality ... ok
test providers::traits::tests::provider_chat_prompt_guided_fallback ... ok
test providers::traits::tests::provider_chat_prompt_guided_preserves_existing_system_not_first ... ok
test providers::traits::tests::provider_chat_prompt_guided_rejects_non_prompt_payload ... ok
test providers::traits::tests::provider_chat_prompt_guided_uses_convert_tools_override ... ok
test providers::traits::tests::provider_chat_without_tools ... ok
test providers::traits::tests::provider_convert_tools_default ... ok
test providers::traits::tests::provider_stream_chat_default_maps_legacy_chunks_to_events ... ok
test providers::traits::tests::supports_native_tools_reflects_capabilities_default_mapping ... ok
test providers::traits::tests::supports_vision_reflects_capabilities_default_mapping ... ok
test providers::traits::tests::token_usage_default_is_none ... ok
test providers::traits::tests::tool_call_serialization ... ok
test providers::traits::tests::tools_payload_variants ... ok
test rag::tests::hardware_rag_load_and_retrieve ... ok
test rag::tests::hardware_rag_load_empty_dir ... ok
test rag::tests::infer_board_from_path_nucleo ... ok
test rag::tests::infer_board_generic_none ... ok
test rag::tests::parse_pin_aliases_empty ... ok
test rag::tests::parse_pin_aliases_key_value ... ok
test rag::tests::parse_pin_aliases_table ... ok
test security::tests::redact_handles_multibyte_utf8_without_panic ... ok
test security::tests::redact_hides_most_of_value ... ok
test security::tests::reexported_policy_and_pairing_types_are_usable ... ok
test security::tests::reexported_secret_store_encrypt_decrypt_roundtrip ... ok
test sop::tests::deterministic_flag_overrides_execution_mode ... ok
test sop::tests::extract_bold_title_no_separator ... ok
test sop::tests::extract_bold_title_none ... ok
test sop::tests::extract_bold_title_with_dash ... ok
test sop::tests::load_sop_from_directory ... ok
test sop::tests::load_sop_toml_only_no_md ... ok
test sop::tests::load_sop_uses_config_default_execution_mode_when_omitted ... ok
test sop::tests::load_sops_empty_dir ... ok
test sop::tests::load_sops_nonexistent_dir ... ok
test sop::tests::parse_all_trigger_types ... ok
test sop::tests::parse_steps_basic ... ok
test sop::tests::parse_steps_empty_md ... ok
test sop::tests::parse_steps_multiline_body ... ok
test sop::tests::parse_steps_no_bold_title ... ok
test sop::tests::parse_steps_with_checkpoint_kind ... ok
test sop::tests::resolve_sops_dir_default ... ok
test sop::tests::resolve_sops_dir_override ... ok
test sop::tests::validate_sop_clean ... ok
test sop::tests::validate_sop_warnings ... ok
test tunnel::tests::cloudflare_health_false_before_start ... ok
test tunnel::tests::cloudflare_tunnel_name ... ok
test tunnel::tests::custom_health_false_before_start_without_health_url ... ok
test tunnel::tests::custom_tunnel_name ... ok
test tunnel::tests::factory_cloudflare_missing_config_errors ... ok
test tunnel::tests::factory_cloudflare_with_config_ok ... ok
test tunnel::tests::factory_custom_missing_config_errors ... ok
test tunnel::tests::factory_custom_with_config_ok ... ok
test tunnel::tests::factory_empty_string_returns_none ... ok
test tunnel::tests::factory_ngrok_missing_config_errors ... ok
test tunnel::tests::factory_ngrok_with_config_ok ... ok
test tunnel::tests::factory_none_returns_none ... ok
test tunnel::tests::factory_openvpn_missing_config_errors ... ok
test tunnel::tests::factory_openvpn_with_config_ok ... ok
test tunnel::tests::factory_pinggy_missing_config_errors ... ok
test tunnel::tests::factory_pinggy_with_config_ok ... ok
test tunnel::tests::factory_tailscale_defaults_ok ... ok
test tunnel::tests::factory_unknown_provider_errors ... ok
test tunnel::tests::kill_shared_no_process_is_ok ... ok
test memory::battle_tests::tests::many_namespaces_sequential_writes ... ok
test tunnel::tests::ngrok_health_false_before_start ... ok
test tunnel::tests::ngrok_tunnel_name ... ok
test tunnel::tests::ngrok_with_domain ... ok
test tunnel::tests::none_tunnel_health_always_true ... ok
test tunnel::tests::none_tunnel_name ... ok
test tunnel::tests::none_tunnel_public_url_is_none ... ok
test tunnel::tests::none_tunnel_start_returns_local ... ok
test tunnel::tests::openvpn_health_false_before_start ... ok
test tunnel::tests::openvpn_tunnel_name ... ok
test tunnel::tests::pinggy_health_false_before_start ... ok
test tunnel::tests::pinggy_tunnel_name ... ok
test tunnel::tests::pinggy_without_token ... ok
test tunnel::tests::tailscale_funnel_mode ... ok
test tunnel::tests::tailscale_health_false_before_start ... ok
test tunnel::tests::tailscale_tunnel_name ... ok
test memory::battle_tests::tests::namespace_with_special_characters ... ok
test tunnel::tests::kill_shared_terminates_and_clears_child ... ok
test memory::battle_tests::tests::retrieval_pipeline_empty_query_works ... ok
test memory::battle_tests::tests::retrieval_pipeline_invalidation_forces_fresh_results ... ok
test memory::battle_tests::tests::retrieval_pipeline_caches_sqlite_results ... ok
test memory::battle_tests::tests::retrieval_pipeline_with_namespace_filter ... ok
test memory::battle_tests::tests::superseded_entry_still_accessible_via_get ... ok
test memory::battle_tests::tests::pipeline_with_audited_sqlite ... ok
test memory::battle_tests::tests::superseded_entries_hidden_from_recall ... ok
test memory::battle_tests::tests::schema_migration_idempotent_with_new_columns ... ok
test memory::battle_tests::tests::retrieval_pipeline_respects_limit ... ok

test result: ok. 230 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.08s

     Running unittests src/main.rs (target/debug/deps/zeroclaw-99dff520d97e2bfd)

running 222 tests
test approval::tests::interactive_manager_reports_interactive ... ok
test approval::tests::auto_approve_tools_skip_prompt ... ok
test approval::tests::always_ask_overrides_auto_approve ... ok
test approval::tests::full_autonomy_never_prompts ... ok
test approval::tests::non_interactive_allows_default_auto_approve_tools ... ok
test approval::tests::always_ask_tools_always_prompt ... ok
test approval::tests::non_interactive_always_ask_tools_need_approval ... ok
test approval::tests::non_interactive_auto_approve_tools_skip_approval ... ok
test approval::tests::approval_request_serde ... ok
test approval::tests::non_interactive_denies_unknown_tools ... ok
test approval::tests::non_interactive_full_autonomy_never_needs_approval ... ok
test approval::tests::approval_response_serde_roundtrip ... ok
test approval::tests::non_interactive_manager_reports_non_interactive ... ok
test approval::tests::non_interactive_readonly_never_needs_approval ... ok
test approval::tests::non_interactive_shell_skips_outer_approval_by_default ... ok
test approval::tests::non_interactive_unknown_tools_need_approval_in_supervised ... ok
test approval::tests::readonly_never_prompts ... ok
test approval::tests::non_interactive_weather_is_auto_approved ... ok
test approval::tests::summarize_args_non_object ... ok
test approval::tests::always_ask_overrides_session_allowlist ... ok
test approval::tests::non_interactive_always_ask_overrides_session_allowlist ... ok
test approval::tests::non_interactive_session_allowlist_still_works ... ok
test approval::tests::summarize_args_object ... ok
test approval::tests::audit_log_contains_timestamp_and_channel ... ok
test approval::tests::always_response_adds_to_session_allowlist ... ok
test approval::tests::summarize_args_truncates_long_values ... ok
test approval::tests::summarize_args_unicode_safe_truncation ... ok
test approval::tests::yes_response_does_not_add_to_allowlist ... ok
test approval::tests::unknown_tool_needs_approval_in_supervised ... ok
test approval::tests::audit_log_records_decisions ... ok
test commands::update::tests::detect_arch_too_short ... ok
test commands::update::tests::detect_arch_unknown_format ... ok
test commands::update::tests::detect_arch_macho_aarch64 ... ok
test commands::update::tests::detect_arch_elf_aarch64 ... ok
test commands::update::tests::detect_arch_macho_x86_64 ... ok
test commands::update::tests::detect_arch_elf_x86_64 ... ok
test commands::update::tests::current_target_triple_is_not_empty ... ok
test commands::update::tests::find_asset_url_returns_none_for_missing_assets ... ok
test commands::update::tests::host_architecture_is_known ... ok
test commands::update::tests::find_asset_url_returns_none_for_empty_assets ... ok
test config::tests::reexported_channel_configs_are_constructible ... ok
test commands::update::tests::find_asset_url_picks_correct_gnu_over_android ... ok
test health::tests::mark_component_error_then_ok_clears_last_error ... ok
test health::tests::mark_component_ok_initializes_component_state ... ok
test health::tests::bump_component_restart_increments_counter ... ok
test commands::update::tests::test_version_comparison ... ok
test health::tests::snapshot_json_contains_registered_component_fields ... ok
test heartbeat::tests::heartbeat_engine_is_constructible_via_module_export ... ok
test config::tests::reexported_config_default_is_constructible ... ok
test memory::battle_tests::tests::conflict_detection_skips_non_core ... ok
test memory::battle_tests::tests::conflict_detection_skips_already_superseded ... ok
test memory::battle_tests::tests::conflict_detection_identical_content_not_flagged ... ok
test commands::update::tests::extract_tar_gz_errors_on_missing_binary ... ok
test memory::battle_tests::tests::deterministic_tiebreaker_in_hybrid_merge ... ok
test memory::battle_tests::tests::importance_empty_content ... ok
test memory::battle_tests::tests::importance_keywords_increase_score ... ok
test memory::battle_tests::tests::importance_core_higher_than_daily ... ok
test memory::battle_tests::tests::importance_score_stays_in_bounds ... ok
test commands::update::tests::extract_tar_gz_finds_binary ... ok
test memory::battle_tests::tests::jaccard_similarity_case_sensitive ... ok
test heartbeat::tests::ensure_heartbeat_file_creates_expected_file ... ok
test memory::battle_tests::tests::jaccard_similarity_identical ... ok
test memory::battle_tests::tests::jaccard_similarity_no_overlap ... ok
test memory::battle_tests::tests::memory_entry_deserialize_without_new_fields_uses_defaults ... ok
test memory::battle_tests::tests::memory_entry_serde_roundtrip_with_new_fields ... ok
test memory::battle_tests::tests::audit_with_namespaced_operations ... ok
test memory::battle_tests::tests::audit_logs_all_operation_types ... ok
test memory::battle_tests::tests::audit_concurrent_operations ... ok
test memory::battle_tests::tests::forget_cleans_up_namespaced_entry ... ok
test memory::battle_tests::tests::namespace_empty_string_works ... ok
test memory::battle_tests::tests::namespace_default_assignment ... ok
test memory::battle_tests::tests::policy_custom_category_retention ... ok
test memory::battle_tests::tests::policy_quota_boundary_conditions ... ok
test memory::battle_tests::tests::policy_read_only_multiple_namespaces ... ok
test memory::battle_tests::tests::importance_persists_in_sqlite ... ok
test memory::battle_tests::tests::policy_validate_store_rejects_read_only ... ok
test memory::battle_tests::tests::policy_zero_quota_means_unlimited ... ok
test memory::battle_tests::tests::empty_namespace_recall_returns_nothing ... ok
test memory::battle_tests::tests::importance_survives_upsert ... ok
test memory::battle_tests::tests::full_lifecycle_store_recall_supersede ... ok
test memory::battle_tests::tests::audit_wrapping_sqlite_backend ... ok
test memory::battle_tests::tests::namespace_survives_upsert ... ok
test memory::battle_tests::tests::namespace_isolation_with_session_id_cross_filter ... ok
test memory::battle_tests::tests::namespace_isolation_between_agents ... ok
test memory::battle_tests::tests::weighted_final_score_all_ones ... ok
test memory::battle_tests::tests::weighted_final_score_all_zeros ... ok
test memory::battle_tests::tests::weighted_final_score_hybrid_dominant ... ok
test memory::cli::tests::parse_category_custom_fallback ... ok
test memory::cli::tests::parse_category_known_variants ... ok
test memory::cli::tests::truncate_content_empty_string ... ok
test memory::cli::tests::truncate_content_long_text_truncated ... ok
test memory::cli::tests::truncate_content_multiline_uses_first_line ... ok
test memory::cli::tests::truncate_content_short_text_unchanged ... ok
test memory::traits::tests::memory_category_custom_roundtrip ... ok
test memory::traits::tests::memory_category_display_outputs_expected_values ... ok
test memory::traits::tests::memory_category_serde_uses_snake_case ... ok
test memory::traits::tests::memory_entry_roundtrip_preserves_optional_fields ... ok
test observability::tests::factory_empty_string_falls_back_to_noop ... ok
test observability::tests::factory_garbage_falls_back_to_noop ... ok
test observability::tests::factory_log_returns_log ... ok
test observability::tests::factory_none_returns_noop ... ok
test observability::tests::factory_noop_returns_noop ... ok
test observability::tests::factory_opentelemetry_alias ... ok
test observability::tests::factory_otel_returns_otel ... ok
test observability::tests::factory_otlp_alias ... ok
test observability::tests::factory_prometheus_returns_prometheus ... ok
test observability::tests::factory_unknown_falls_back_to_noop ... ok
test observability::tests::factory_verbose_returns_verbose ... ok
test onboard::tests::wizard_functions_are_reexported ... ok
test platform::tests::factory_cloudflare_errors ... ok
test platform::tests::factory_docker ... ok
test platform::tests::factory_empty_errors ... ok
test platform::tests::factory_native ... ok
test platform::tests::factory_unknown_errors ... ok
test providers::traits::tests::build_tool_instructions_text_empty ... ok
test providers::traits::tests::build_tool_instructions_text_format ... ok
test providers::traits::tests::chat_message_constructors ... ok
test providers::traits::tests::chat_response_helpers ... ok
test providers::traits::tests::chat_response_with_usage ... ok
test providers::traits::tests::conversation_message_variants ... ok
test providers::traits::tests::provider_capabilities_default ... ok
test providers::traits::tests::provider_capabilities_equality ... ok
test providers::traits::tests::provider_chat_prompt_guided_fallback ... ok
test providers::traits::tests::provider_chat_prompt_guided_preserves_existing_system_not_first ... ok
test providers::traits::tests::provider_chat_prompt_guided_rejects_non_prompt_payload ... ok
test providers::traits::tests::provider_chat_prompt_guided_uses_convert_tools_override ... ok
test providers::traits::tests::provider_chat_without_tools ... ok
test providers::traits::tests::provider_convert_tools_default ... ok
test providers::traits::tests::provider_stream_chat_default_maps_legacy_chunks_to_events ... ok
test providers::traits::tests::supports_native_tools_reflects_capabilities_default_mapping ... ok
test providers::traits::tests::supports_vision_reflects_capabilities_default_mapping ... ok
test providers::traits::tests::token_usage_default_is_none ... ok
test providers::traits::tests::tool_call_serialization ... ok
test providers::traits::tests::tools_payload_variants ... ok
test security::tests::redact_handles_multibyte_utf8_without_panic ... ok
test security::tests::redact_hides_most_of_value ... ok
test security::tests::reexported_policy_and_pairing_types_are_usable ... ok
test security::tests::reexported_secret_store_encrypt_decrypt_roundtrip ... ok
test skillforge::tests::default_config_values ... ok
test skillforge::tests::disabled_forge_returns_empty_report ... ok
test sop::tests::deterministic_flag_overrides_execution_mode ... ok
test sop::tests::extract_bold_title_no_separator ... ok
test sop::tests::extract_bold_title_none ... ok
test sop::tests::extract_bold_title_with_dash ... ok
test sop::tests::load_sop_from_directory ... ok
test sop::tests::load_sop_toml_only_no_md ... ok
test sop::tests::load_sop_uses_config_default_execution_mode_when_omitted ... ok
test sop::tests::load_sops_empty_dir ... ok
test sop::tests::load_sops_nonexistent_dir ... ok
test sop::tests::parse_all_trigger_types ... ok
test sop::tests::parse_steps_basic ... ok
test sop::tests::parse_steps_empty_md ... ok
test sop::tests::parse_steps_multiline_body ... ok
test sop::tests::parse_steps_no_bold_title ... ok
test sop::tests::parse_steps_with_checkpoint_kind ... ok
test sop::tests::resolve_sops_dir_default ... ok
test sop::tests::resolve_sops_dir_override ... ok
test sop::tests::validate_sop_clean ... ok
test sop::tests::validate_sop_warnings ... ok
test tests::agent_command_parses_session_state_file ... ok
test tests::agent_command_parses_with_temperature ... ok
test tests::agent_command_parses_without_temperature ... ok
test tests::agent_fallback_uses_config_default_temperature ... ok
test tests::agent_fallback_uses_hardcoded_when_config_uses_default ... ok
test tests::cli_definition_has_no_flag_conflicts ... ok
test tests::cli_parses_estop_default_engage ... ok
test tests::cli_parses_estop_resume_domain ... ok
test memory::battle_tests::tests::many_namespaces_sequential_writes ... ok
test tests::completions_cli_parses_supported_shells ... ok
test tests::onboard_cli_accepts_force_flag ... ok
test tests::onboard_cli_accepts_model_provider_and_api_key_in_quick_mode ... ok
test tests::onboard_cli_bare_parses ... ok
test memory::battle_tests::tests::namespace_with_special_characters ... ok
test tests::completion_generation_mentions_binary_name ... ok
test tests::onboard_cli_quick_and_channels_only_conflict ... ok
test tests::onboard_cli_parses_quick_flag ... ok
test tunnel::tests::cloudflare_health_false_before_start ... ok
test tunnel::tests::cloudflare_tunnel_name ... ok
test tests::onboard_help_includes_model_flag ... ok
test tunnel::tests::custom_health_false_before_start_without_health_url ... ok
test tunnel::tests::custom_tunnel_name ... ok
test tests::onboard_cli_rejects_removed_interactive_flag ... ok
test tunnel::tests::factory_cloudflare_with_config_ok ... ok
test tunnel::tests::factory_cloudflare_missing_config_errors ... ok
test tunnel::tests::factory_custom_missing_config_errors ... ok
test tunnel::tests::factory_custom_with_config_ok ... ok
test tunnel::tests::factory_empty_string_returns_none ... ok
test tunnel::tests::factory_ngrok_missing_config_errors ... ok
test tunnel::tests::factory_ngrok_with_config_ok ... ok
test tunnel::tests::factory_none_returns_none ... ok
test tunnel::tests::factory_openvpn_missing_config_errors ... ok
test tunnel::tests::factory_pinggy_with_config_ok ... ok
test tunnel::tests::factory_pinggy_missing_config_errors ... ok
test tunnel::tests::factory_openvpn_with_config_ok ... ok
test tunnel::tests::factory_tailscale_defaults_ok ... ok
test tunnel::tests::factory_unknown_provider_errors ... ok
test tunnel::tests::kill_shared_no_process_is_ok ... ok
test tunnel::tests::ngrok_tunnel_name ... ok
test tunnel::tests::ngrok_health_false_before_start ... ok
test memory::battle_tests::tests::retrieval_pipeline_empty_query_works ... ok
test tunnel::tests::none_tunnel_health_always_true ... ok
test tunnel::tests::ngrok_with_domain ... ok
test tunnel::tests::none_tunnel_name ... ok
test tunnel::tests::none_tunnel_start_returns_local ... ok
test tunnel::tests::none_tunnel_public_url_is_none ... ok
test tunnel::tests::openvpn_tunnel_name ... ok
test tunnel::tests::openvpn_health_false_before_start ... ok
test tunnel::tests::pinggy_health_false_before_start ... ok
test tunnel::tests::pinggy_tunnel_name ... ok
test tunnel::tests::pinggy_without_token ... ok
test tunnel::tests::tailscale_funnel_mode ... ok
test tunnel::tests::tailscale_health_false_before_start ... ok
test tunnel::tests::tailscale_tunnel_name ... ok
test memory::battle_tests::tests::retrieval_pipeline_invalidation_forces_fresh_results ... ok
test memory::battle_tests::tests::retrieval_pipeline_caches_sqlite_results ... ok
test memory::battle_tests::tests::retrieval_pipeline_with_namespace_filter ... ok
test tunnel::tests::kill_shared_terminates_and_clears_child ... ok
test memory::battle_tests::tests::superseded_entry_still_accessible_via_get ... ok
test memory::battle_tests::tests::pipeline_with_audited_sqlite ... ok
test memory::battle_tests::tests::superseded_entries_hidden_from_recall ... ok
test memory::battle_tests::tests::schema_migration_idempotent_with_new_columns ... ok
test memory::battle_tests::tests::retrieval_pipeline_respects_limit ... ok

test result: ok. 222 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.09s

     Running tests/test_component.rs (target/debug/deps/component-5c3f5e30b36b1607)

running 205 tests
test component::config_migration::model_provider_alias_works ... ok
test component::config_migration::resolved_cache_populated_for_v2_config ... ok
test component::config_migration::no_default_provider_uses_fallback_name_default ... ok
test component::config_migration::empty_config_produces_valid_v2 ... ok
test component::config_migration::room_id_deduped_with_existing_allowed_rooms ... ok
test component::config_migration::profile_values_take_precedence_over_top_level ... ok
test component::config_migration::already_v2_config_unchanged ... ok
test component::config_migration::migrate_file_returns_none_when_current ... ok
test component::config_persistence::agent_config_default_compact_context_on ... ok
test component::config_migration::top_level_fields_merge_with_existing_model_providers_entry ... ok
test component::config_persistence::agent_config_default_max_history_messages ... ok
test component::config_persistence::agent_config_default_max_tool_iterations ... ok
test component::config_persistence::agent_config_default_tool_dispatcher ... ok
test component::config_persistence::config_default_has_expected_provider ... ok
test component::config_persistence::config_default_has_expected_model ... ok
test component::config_persistence::config_default_temperature_positive ... ok
test component::config_persistence::memory_config_default_backend ... ok
test component::config_persistence::memory_config_default_embedding_provider ... ok
test component::config_persistence::memory_config_default_vector_keyword_weights_sum_to_one ... ok
test component::config_persistence::config_file_with_missing_optional_fields_uses_defaults ... ok
test component::config_schema::autonomy_config_default_is_supervised ... ok
test component::config_schema::autonomy_config_default_max_actions_per_hour ... ok
test component::config_persistence::config_file_with_custom_agent_section ... ok
test component::config_schema::autonomy_config_default_workspace_only ... ok
test component::config_schema::config_channels_all_optional_channels_none_by_default ... ok
test component::config_persistence::workspace_dir_creation_in_tempdir ... ok
test component::config_schema::config_channels_default_cli_enabled ... ok
test component::config_persistence::nested_workspace_dir_creation ... ok
test component::config_schema::config_channels_explicit_cli_true_with_whatsapp ... ok
test component::config_schema::config_empty_parses_with_all_defaults ... ok
test component::config_schema::config_channels_without_cli_field ... ok
test component::config_schema::config_empty_toml_uses_default_temperature ... ok
test component::config_schema::config_extra_unknown_keys_ignored ... ok
test component::config_schema::config_memory_defaults_when_section_absent ... ok
test component::config_schema::config_minimal_toml_with_temperature_uses_defaults ... ok
test component::config_schema::config_multiple_channels_coexist ... ok
test component::config_schema::config_negative_temperature_fails ... ok
test component::config_schema::config_nested_optional_sections_default_when_absent ... ok
test component::config_schema::config_negative_port_fails ... ok
test component::config_migration::exhaustive_walk_no_props_lost ... ok
test component::config_schema::config_only_temperature_parses ... ok
test component::config_schema::config_only_whatsapp_channel_parses ... ok
test component::config_schema::config_out_of_range_temperature_fails ... ok
test component::config_schema::config_overflow_port_fails ... ok
test component::config_schema::config_toplevel_cli_section_with_whatsapp_parses ... ok
test component::config_schema::config_unknown_keys_parse_without_error ... ok
test component::config_schema::config_wrong_type_for_port_fails ... ok
test component::config_schema::config_wrong_type_for_temperature_fails ... ok
test component::config_schema::gateway_config_defaults_are_secure ... ok
test component::config_schema::gateway_config_idempotency_defaults ... ok
test component::config_schema::gateway_config_missing_section_uses_defaults ... ok
test component::config_schema::gateway_config_partial_section_fills_defaults ... ok
test component::config_schema::gateway_config_rate_limit_defaults ... ok
test component::config_persistence::config_toml_roundtrip_preserves_agent_config ... ok
test component::config_persistence::config_file_write_read_roundtrip ... ok
test component::config_schema::gateway_config_toml_roundtrip ... ok
test component::config_schema::gateway_path_prefix_accepts_none ... ok
test component::config_schema::gateway_path_prefix_accepts_valid_prefixes ... ok
test component::config_schema::gateway_path_prefix_rejects_bare_slash ... ok
test component::config_schema::gateway_path_prefix_rejects_missing_leading_slash ... ok
test component::config_schema::gateway_path_prefix_rejects_trailing_slash ... ok
test component::config_schema::security_config_defaults ... ok
test component::config_schema::autonomy_config_toml_roundtrip ... ok
test component::config_schema::gateway_path_prefix_rejects_unsafe_characters ... ok
test component::config_schema::security_config_toml_roundtrip ... ok
test component::config_persistence::config_toml_roundtrip_preserves_memory_config ... ok
test component::config_persistence::config_toml_roundtrip_preserves_provider ... ok
test component::dockerignore_test::dockerignore_excludes_ci_configs ... ok
test component::dockerignore_test::dockerignore_excludes_env_files ... ok
test component::dockerignore_test::dockerignore_does_not_exclude_build_essentials ... ok
test component::dockerignore_test::dockerignore_excludes_image_files ... ok
test component::dockerignore_test::dockerignore_excludes_markdown_files ... ok
test component::dockerignore_test::dockerignore_excludes_database_files ... ok
test component::dockerignore_test::dockerignore_excludes_git_directory ... ok
test component::dockerignore_test::dockerignore_file_exists ... ok
test component::gateway::gateway_body_limit_is_reasonable ... ok
test component::gateway::gateway_rate_limit_window_is_60s ... ok
test component::gateway::gateway_timeout_is_reasonable ... ok
test component::dockerignore_test::dockerignore_pattern_matching_edge_cases ... ok
test component::dockerignore_test::dockerignore_excludes_security_critical_paths ... ok
test component::gateway::gateway_whatsapp_empty_signature_rejected ... ok
test component::gateway::gateway_whatsapp_missing_prefix_rejected ... ok
test component::gateway::gateway_whatsapp_different_secrets_differ ... ok
test component::gateway::gateway_whatsapp_wrong_signature_rejected ... ok
test component::gateway::gateway_whatsapp_tampered_body_rejected ... ok
test component::gateway::gateway_whatsapp_valid_signature_accepted ... ok
test component::dockerignore_test::dockerignore_has_valid_syntax ... ok
test component::dockerignore_test::dockerignore_excludes_target_directory ... ok
test component::otel_dependency_feature_regression::opentelemetry_otlp_uses_blocking_reqwest_client ... ok
test component::provider_resolution::compatible_provider_bearer_auth_style ... ok
test component::provider_resolution::compatible_provider_base_url_trailing_slash_normalized ... ok
test component::config_schema::config_valid_keys_not_flagged_as_unknown ... ok
test component::provider_resolution::compatible_provider_custom_auth_header ... ok
test component::provider_resolution::compatible_provider_no_credential ... ok
test component::provider_resolution::compatible_provider_xapikey_auth_style ... ok
test component::provider_resolution::factory_aws_bedrock_alias_resolves_to_bedrock ... ok
test component::provider_resolution::convenience_factory_ollama_no_key ... ok
test component::provider_resolution::convenience_factory_resolves_major_providers ... ok
test component::provider_resolution::factory_cloudflare_ai_alias_resolves_to_cloudflare ... ok
test component::provider_resolution::factory_custom_empty_url_rejected ... ok
test component::provider_resolution::factory_build_nvidia_com_alias_resolves_to_nvidia ... ok
test component::config_migration::migrate_file_preserves_comments ... ok
test component::provider_resolution::factory_anthropic_custom_endpoint_resolves ... ok
test component::provider_resolution::factory_custom_http_url_resolves ... ok
test component::provider_resolution::factory_custom_ftp_url_rejected ... ok
test component::provider_resolution::factory_custom_https_url_resolves ... ok
test component::provider_resolution::factory_grok_alias_resolves_to_xai ... ok
test component::provider_resolution::factory_kimi_alias_resolves_to_moonshot ... ok
test component::provider_resolution::factory_llama_cpp_alias_resolves_to_llamacpp ... ok
test component::provider_resolution::factory_lm_studio_alias_resolves_to_lmstudio ... ok
test component::provider_resolution::factory_nvidia_nim_alias_resolves_to_nvidia ... ok
test component::provider_resolution::factory_ollama_with_custom_api_url ... ok
test component::provider_resolution::factory_opencode_zen_alias_resolves_to_opencode ... ok
test component::provider_resolution::factory_openai_with_custom_api_url ... ok
test component::provider_resolution::factory_ovh_alias_resolves_to_ovhcloud ... ok
test component::provider_resolution::factory_resolves_anthropic_provider ... ok
test component::provider_resolution::factory_resolves_astrai_provider ... ok
test component::provider_resolution::factory_github_copilot_alias_resolves_to_copilot ... ok
test component::provider_resolution::factory_resolves_cloudflare_provider ... ok
test component::provider_resolution::factory_resolves_bedrock_provider ... ok
test component::provider_resolution::factory_google_alias_resolves_to_gemini ... ok
test component::provider_resolution::factory_google_gemini_alias_resolves_to_gemini ... ok
test component::gemini_capabilities::gemini_reports_no_native_tool_calling ... ok
test component::gemini_capabilities::gemini_supports_native_tools_returns_false ... ok
test component::gemini_capabilities::gemini_supports_vision_returns_true ... ok
test component::provider_resolution::factory_resolves_cohere_provider ... ok
test component::provider_resolution::factory_resolves_deepseek_provider ... ok
test component::gemini_capabilities::gemini_reports_vision_support ... ok
test component::provider_resolution::factory_resolves_copilot_provider ... ok
test component::provider_resolution::factory_resolves_doubao_provider ... ok
test component::provider_resolution::factory_resolves_fireworks_provider ... ok
test component::gemini_capabilities::gemini_convert_tools_returns_prompt_guided ... ok
test component::provider_resolution::factory_resolves_glm_provider ... ok
test component::provider_resolution::factory_resolves_groq_provider ... ok
test component::provider_resolution::factory_resolves_kimi_code_provider ... ok
test component::provider_resolution::factory_resolves_lmstudio_provider ... ok
test component::provider_resolution::factory_resolves_llamacpp_provider ... ok
test component::provider_resolution::factory_resolves_minimax_provider ... ok
test component::provider_resolution::factory_resolves_mistral_provider ... ok
test component::provider_resolution::factory_resolves_moonshot_provider ... ok
test component::provider_resolution::factory_resolves_nvidia_provider ... ok
test component::provider_resolution::factory_resolves_ollama_provider ... ok
test component::provider_resolution::factory_resolves_openai_provider ... ok
test component::provider_resolution::factory_resolves_opencode_provider ... ok
test component::provider_resolution::factory_resolves_opencode_go_provider ... ok
test component::provider_resolution::factory_resolves_ovhcloud_provider ... ok
test component::provider_resolution::factory_resolves_perplexity_provider ... ok
test component::provider_resolution::factory_resolves_openrouter_provider ... ok
test component::provider_resolution::factory_resolves_qianfan_provider ... ok
test component::provider_resolution::factory_resolves_gemini_provider ... ok
test component::provider_resolution::factory_resolves_qwen_provider ... ok
test component::provider_resolution::factory_resolves_synthetic_provider ... ok
test component::provider_resolution::factory_resolves_together_provider ... ok
test component::provider_resolution::factory_resolves_venice_provider ... ok
test component::provider_resolution::factory_resolves_vercel_provider ... ok
test component::provider_resolution::factory_resolves_vllm_provider ... ok
test component::provider_resolution::factory_resolves_xai_provider ... ok
test component::provider_resolution::factory_resolves_openai_codex_provider ... ok
test component::provider_resolution::factory_resolves_zai_provider ... ok
test component::provider_resolution::factory_unknown_provider_rejected ... ok
test component::provider_resolution::factory_vercel_ai_alias_resolves_to_vercel ... ok
test component::provider_schema::auth_style_bearer_is_constructible ... ok
test component::provider_resolution::factory_zhipu_alias_resolves_to_glm ... ok
test component::provider_schema::auth_style_custom_header ... ok
test component::provider_schema::auth_style_xapikey_is_constructible ... ok
test component::provider_schema::chat_message_assistant_role_correct ... ok
test component::provider_schema::chat_message_system_role_correct ... ok
test component::provider_schema::chat_message_json_roundtrip ... ok
test component::provider_schema::chat_message_tool_role_correct ... ok
test component::provider_schema::chat_message_serializes_to_json_with_required_fields ... ok
test component::provider_schema::chat_message_user_role_correct ... ok
test component::provider_schema::chat_messages_maintain_role_sequence ... ok
test component::provider_schema::chat_messages_with_tool_calls_maintain_sequence ... ok
test component::provider_schema::chat_response_multiple_tool_calls ... ok
test component::provider_schema::chat_response_text_only ... ok
test component::provider_schema::chat_response_text_or_empty_handles_none ... ok
test component::provider_schema::chat_response_with_tool_calls ... ok
test component::provider_schema::provider_construction_with_different_auth_styles ... ok
test component::provider_schema::provider_construction_with_different_names ... ok
test component::provider_schema::tool_call_arguments_contain_valid_json ... ok
test component::provider_schema::tool_call_has_required_fields ... ok
test component::provider_schema::tool_response_message_can_embed_tool_call_id ... ok
test component::provider_schema::tool_call_id_preserved_in_serialization ... ok
test component::security::security_default_autonomy_is_supervised ... ok
test component::security::security_default_block_high_risk_commands ... ok
test component::security::security_default_max_actions_per_hour ... ok
test component::security::security_default_require_approval_for_medium_risk ... ok
test component::security::security_default_workspace_only ... ok
test component::security::security_full_config_has_autonomy ... ok
test component::security::security_config_debug_does_not_leak_api_key ... ok
test component::security::security_full_autonomy_parses ... ok
test component::security::security_secrets_encryption_default ... ok
test component::whatsapp_webhook_security::whatsapp_signature_rejects_empty_signature ... ok
test component::whatsapp_webhook_security::whatsapp_signature_accepts_valid_signature ... ok
test component::whatsapp_webhook_security::whatsapp_signature_rejects_invalid_hex ... ok
test component::security::security_autonomy_config_toml_roundtrip ... ok
test component::whatsapp_webhook_security::whatsapp_signature_rejects_missing_sha256_prefix ... ok
test component::security::security_readonly_autonomy_parses ... ok
test component::whatsapp_webhook_security::whatsapp_signature_different_secrets_produce_different_sigs ... ok
test component::whatsapp_webhook_security::whatsapp_signature_rejects_tampered_body ... ok
test component::whatsapp_webhook_security::whatsapp_signature_rejects_wrong_signature ... ok
test component::whatsapp_webhook_security::whatsapp_signature_rejects_wrong_secret ... ok
test component::config_migration::realistic_v1_config_migrates_and_validates ... ok
test component::config_migration::migrate_file_round_trips ... ok
test component::reply_target_field_regression::source_does_not_use_legacy_reply_to_field ... ok

test result: ok. 205 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.03s

     Running tests/test_integration.rs (target/debug/deps/integration-c7b238e4e9620591)

running 159 tests
test integration::agent::e2e_multi_turn_conversation ... ok
test integration::agent_robustness::agent_handles_empty_provider_response ... ok
test integration::agent::e2e_multi_turn_with_memory_enrichment ... ok
test integration::agent::e2e_memory_enrichment_injects_context ... ok
test integration::agent::e2e_simple_text_response ... ok
test integration::agent::e2e_multi_turn_history_fidelity ... ok
test integration::agent::e2e_empty_memory_context_passthrough ... ok
test integration::agent::e2e_parallel_tool_dispatch ... ok
test integration::agent::e2e_multi_step_tool_chain ... ok
test integration::agent::e2e_unknown_tool_recovery ... ok
test integration::agent::e2e_single_tool_call_cycle ... ok
test integration::agent::e2e_xml_dispatcher_tool_call ... ok
test integration::agent_robustness::agent_handles_nested_json_tool_arguments ... ok
test integration::agent_robustness::agent_handles_whitespace_only_response ... ok
test integration::agent_robustness::agent_recovers_from_text_with_xml_residue ... ok
test integration::agent_robustness::agent_handles_sequential_tool_then_text ... ok
test integration::agent_robustness::agent_handles_unicode_tool_arguments ... ok
test integration::agent_robustness::agent_handles_tool_call_with_empty_arguments ... ok
test integration::agent_robustness::agent_handles_failing_tool ... ok
test integration::agent_robustness::agent_handles_mixed_tool_success_and_failure ... ok
test integration::agent_robustness::agent_handles_none_text_response ... ok
test integration::channel_matrix::all_platforms_channel_field_matches_platform_name ... ok
test integration::agent_robustness::agent_handles_nonexistent_tool_gracefully ... ok
test integration::channel_matrix::all_platforms_have_non_empty_fields ... ok
test integration::agent_robustness::agent_respects_max_tool_iterations ... ok
test integration::channel_matrix::alternating_channels_preserve_isolation ... ok
test integration::channel_matrix::channel_message_max_timestamp ... ok
test integration::channel_matrix::capability_matrix_spec ... ok
test integration::channel_matrix::channel_message_none_thread_ts_preserved ... ok
test integration::channel_matrix::channel_message_thread_ts_preserved_on_clone ... ok
test integration::channel_matrix::channel_message_zero_timestamp ... ok
test integration::channel_matrix::channel_platforms_have_distinct_sender_and_reply_target ... ok
test integration::channel_matrix::dm_platforms_have_same_sender_and_reply_target ... ok
test integration::channel_matrix::draft_cancel_lifecycle ... ok
test integration::channel_matrix::concurrent_typing_events_all_recorded ... ok
test integration::channel_matrix::concurrent_reactions_all_recorded ... ok
test integration::channel_matrix::draft_channel_reports_support ... ok
test integration::channel_matrix::concurrent_sends_all_recorded ... ok
test integration::channel_matrix::draft_full_lifecycle_send_update_finalize ... ok
test integration::channel_matrix::draft_multiple_sequential_drafts_get_unique_ids ... ok
test integration::channel_matrix::draft_non_supporting_channel_returns_none ... ok
test integration::channel_matrix::dyn_channel_dispatch_works ... ok
test integration::channel_matrix::messages_routed_to_correct_channel ... ok
test integration::channel_matrix::minimal_channel_all_defaults_succeed ... ok
test integration::channel_matrix::non_draft_channel_reports_no_support ... ok
test integration::channel_matrix::full_conversation_lifecycle ... ok
test integration::channel_matrix::multi_channel_listen_produces_channel_tagged_messages ... ok
test integration::channel_matrix::pin_multiple_messages_in_same_channel ... ok
test integration::channel_matrix::pin_unpin_lifecycle ... ok
test integration::channel_matrix::reaction_across_different_channels_and_messages ... ok
test integration::channel_matrix::reaction_add_remove_lifecycle ... ok
test integration::channel_matrix::rapid_send_burst ... ok
test integration::channel_matrix::reaction_multiple_emojis_on_same_message ... ok
test integration::channel_matrix::reaction_unicode_emoji_preserved ... ok
test integration::channel_matrix::redact_message_lifecycle ... ok
test integration::channel_matrix::reply_uses_reply_target_not_sender ... ok
test integration::channel_matrix::send_content_with_newlines_and_special_chars ... ok
test integration::channel_matrix::send_message_empty_subject ... ok
test integration::channel_matrix::send_empty_content ... ok
test integration::channel_matrix::send_message_in_thread_builder ... ok
test integration::channel_matrix::send_message_in_thread_none_clears_thread ... ok
test integration::channel_matrix::send_message_subject_none_by_default ... ok
test integration::channel_matrix::send_message_with_subject_preserves_thread ... ok
test integration::channel_matrix::threaded_platforms_have_thread_ts ... ok
test integration::channel_matrix::send_unicode_content ... ok
test integration::channel_matrix::threaded_reply_preserves_thread_ts ... ok
test integration::channel_matrix::send_very_long_content ... ok
test integration::channel_matrix::trait_health_check_configurable ... ok
test integration::channel_matrix::trait_listen_produces_well_formed_message ... ok
test integration::channel_matrix::trait_name_returns_configured_name ... ok
test integration::channel_matrix::typing_empty_recipient_does_not_panic ... ok
test integration::channel_matrix::trait_send_records_content_and_recipient ... ok
test integration::channel_matrix::typing_multiple_recipients_interleaved ... ok
test integration::channel_matrix::typing_start_stop_cycle ... ok
test integration::channel_routing::channel_draft_defaults ... ok
test integration::channel_routing::channel_health_check_default_returns_true ... ok
test integration::channel_routing::channel_message_fields_not_swapped ... ok
test integration::channel_routing::channel_listen_produces_correct_identity_fields ... ok
test integration::channel_routing::channel_message_preserves_all_fields_on_clone ... ok
test integration::channel_routing::channel_message_reply_target_distinct_from_sender ... ok
test integration::channel_routing::channel_message_sender_field_holds_platform_user_id ... ok
test integration::channel_routing::channel_send_preserves_recipient ... ok
test integration::channel_routing::channel_multiple_sends_preserve_order_and_recipients ... ok
test integration::channel_routing::send_message_new_sets_content_and_recipient ... ok
test integration::channel_routing::channel_send_reply_uses_sender_from_listen ... ok
test integration::channel_routing::channel_typing_defaults_succeed ... ok
test integration::channel_routing::send_message_recipient_carries_platform_target ... ok
test integration::channel_routing::send_message_with_subject_sets_all_fields ... ok
test integration::email_attachments::send_message_attachments_default_empty ... ok
test integration::email_attachments::send_message_with_attachments_builder ... ok
test integration::email_attachments::extract_attachments_skips_text_parts ... ok
test integration::email_attachments::extract_attachments_from_multipart_email ... ok
test integration::email_attachments::extract_attachments_respects_size_limit ... ok
test integration::hooks::hook_runner_full_pipeline ... ok
test integration::backup_cron_scheduling::backup_cron_job_not_synced_when_schedule_none ... ok
test integration::backup_cron_scheduling::backup_cron_job_command_is_backup_create ... ok
test integration::backup_cron_scheduling::backup_cron_job_type_is_shell ... ok
test integration::backup_cron_scheduling::backup_cron_job_source_is_declarative ... ok
test integration::backup_cron_scheduling::backup_cron_job_synced_when_schedule_set ... ok
test integration::backup_cron_scheduling::backup_cron_job_removed_when_schedule_cleared ... ok
test integration::backup_cron_scheduling::backup_cron_job_id_is_stable ... ok
test integration::backup_cron_scheduling::backup_cron_job_schedule_updated ... ok
test integration::memory_comparison::compare_forget ... ok
test integration::memory_comparison::compare_category_filter ... ok
test integration::memory_comparison::compare_persistence ... ok
test integration::memory_comparison::compare_upsert ... ok
test integration::memory_loop_continuity::agent_completes_five_step_tool_chain ... ok
test integration::memory_comparison::compare_recall_quality ... ok
test integration::memory_loop_continuity::agent_handles_interleaved_tools_and_text ... ok
test integration::memory_loop_continuity::agent_handles_parallel_tool_calls ... ok
test integration::memory_loop_continuity::agent_maintains_history_across_turns ... ok
test integration::memory_loop_continuity::agent_auto_saves_and_recalls_memory ... ok
test integration::memory_loop_continuity::agent_multi_turn_with_tools_builds_context ... ok
test integration::memory_loop_continuity::compressor_with_memory_saves_summary ... ok
test integration::memory_loop_continuity::agent_survives_large_tool_output ... ok
test integration::memory_loop_continuity::session_backend_persists_messages ... ok
test integration::memory_loop_continuity::session_state_transitions ... ok
test integration::memory_loop_continuity::memory_recall_returns_relevant_entries ... ok
test integration::memory_loop_continuity::memory_persists_across_instances ... ok
test integration::memory_loop_continuity::consolidation_extracts_facts_to_memory ... ok
test integration::memory_restart::sqlite_memory_forget_nonexistent_returns_false ... ok
test integration::memory_loop_continuity::memory_survives_rapid_consolidation ... ok
test integration::memory_restart::sqlite_memory_forget_removes_entry ... ok
test integration::memory_restart::sqlite_memory_concurrent_stores_no_data_loss ... ok
test integration::memory_restart::sqlite_memory_global_recall_includes_all_sessions ... ok
test integration::memory_restart::sqlite_memory_health_check_returns_true ... ok
test integration::report_template_tool_test::default_language_is_en ... ok
test integration::report_template_tool_test::empty_variables_map_renders ... ok
test integration::report_template_tool_test::injection_protection_enforced ... ok
test integration::report_template_tool_test::invalid_language_code_fails ... ok
test integration::report_template_tool_test::invalid_template_name_fails ... ok
test integration::report_template_tool_test::missing_template_param_fails ... ok
test integration::report_template_tool_test::missing_variables_param_fails ... ok
test integration::report_template_tool_test::non_string_variable_values_coerced ... ok
test integration::report_template_tool_test::render_milestone_report_it ... ok
test integration::report_template_tool_test::render_risk_register_fr ... ok
test integration::report_template_tool_test::render_sprint_review_de ... ok
test integration::report_template_tool_test::render_weekly_status_en ... ok
test integration::memory_restart::sqlite_memory_recall_empty_query_returns_recent_entries ... ok
test integration::telegram_attachment_fallback::document_only_message_falls_back_to_text ... ok
test integration::memory_restart::sqlite_memory_list_by_category ... ok
test integration::telegram_attachment_fallback::document_url_failure_falls_back_to_text_link ... ok
test integration::memory_restart::sqlite_memory_persists_across_reinitialization ... ok
test integration::memory_restart::sqlite_memory_recall_returns_relevant_results ... ok
test integration::telegram_attachment_fallback::successful_attachment_no_fallback ... ok
test integration::memory_restart::sqlite_memory_store_different_keys_creates_separate_entries ... ok
test integration::telegram_finalize_draft::finalize_draft_plain_retry_treats_not_modified_as_success ... ok
test integration::telegram_attachment_fallback::text_portion_delivered_before_attachment_failure ... ok
test integration::memory_restart::sqlite_memory_recall_respects_limit ... ok
test integration::telegram_attachment_fallback::photo_url_failure_falls_back_to_text_link ... ok
test integration::telegram_finalize_draft::finalize_draft_treats_not_modified_as_success ... ok
test integration::memory_restart::sqlite_memory_store_same_key_deduplicates ... ok
test integration::telegram_attachment_fallback::multiple_attachments_independent_fallback ... ok
test integration::memory_restart::sqlite_memory_session_scoped_store_and_recall ... ok
test integration::telegram_finalize_draft::finalize_draft_sends_fresh_message_after_successful_delete ... ok
test integration::telegram_finalize_draft::finalize_draft_skips_send_message_when_delete_fails ... ok
test integration::memory_restart::sqlite_memory_restart_does_not_duplicate_on_rewrite ... ok
test integration::memory_comparison::compare_store_speed ... ok
test integration::memory_comparison::compare_recall_speed ... ok

test result: ok. 159 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.19s

     Running tests/test_live.rs (target/debug/deps/live-05da99df3a2fac94)

running 7 tests
test live::gemini_fallback_oauth_refresh::gemini_warmup_refreshes_expired_oauth_token ... ignored, requires live Gemini OAuth credentials with refresh_token
test live::gemini_fallback_oauth_refresh::gemini_warmup_with_valid_credentials ... ignored, requires live Gemini OAuth credentials
test live::openai_codex_vision_e2e::openai_codex_second_vision_support ... ignored, requires live OpenAI Codex OAuth credentials (second profile)
test live::openai_codex_vision_e2e::provider_vision_support ... ignored, requires live provider OAuth credentials
test live::providers::e2e_live_openai_codex_multi_turn ... ignored, requires live OpenAI Codex OAuth credentials
test live::zai_jwt_auth::live_zai_jwt_auth_chat ... ignored, requires live ZAI_API_KEY
test live::zai_jwt_auth::live_zai_jwt_auth_multi_turn ... ignored, requires live ZAI_API_KEY

test result: ok. 0 passed; 0 failed; 7 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_system.rs (target/debug/deps/system-2819923ca5382e34)

running 5 tests
test system::full_stack::system_tool_arguments_passed_correctly ... ok
test system::full_stack::system_multi_turn_conversation ... ok
test system::full_stack::system_parallel_tool_execution ... ok
test system::full_stack::system_tool_execution_flow ... ok
test system::full_stack::system_simple_text_response ... ok

test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.02s

   Doc-tests zeroclaw

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

Test plan

  • All manifests pass kubectl apply --dry-run=client validation
  • Deployed on OpenShift (NERC cluster) — pod starts, gateway healthy, web UI accessible
  • Runtime footprint: ~6Mi memory at idle with full agent runtime
  • Pairing auth (require_pairing = true) verified working via Route
  • Test on vanilla Kubernetes (without Route — users would substitute Ingress)

🤖 Generated with Claude Code

Sample manifests for deploying ZeroClaw on OpenShift/Kubernetes with
an external LLM provider. Includes Namespace, Secret, ConfigMap,
Deployment, Service, and Route with edge TLS.

Highlights:
- Distroless image, hardened SecurityContext (runAsNonRoot, drop ALL
  caps, read-only root filesystem, seccomp RuntimeDefault)
- Health probes on /health endpoint
- Pairing auth support via config
- Sample files with .gitignore pattern so users can customize
  without leaking secrets

Tested on OpenShift (NERC cluster): pod runs at ~6Mi memory idle
with full agent runtime, web UI, and gateway.

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Pavel Anni <panni@redhat.com>
@github-actions github-actions bot added the docs Auto scope: docs/markdown/template files changed. label Apr 18, 2026
Copy link
Copy Markdown
Collaborator

@WareWolf-MoonWall WareWolf-MoonWall left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Welcome, @pavelanni — and thank you for a real, live-cluster-validated contribution.
The security posture here is genuinely strong, and the test evidence is the kind that
makes a review faster and a merge more confident. Let me walk through what you got
right before I get to the items that need to change.


Intake checklist

A few process items to address before this can merge. These are not optional — they are
how we keep review quality consistent across contributors and track work intentionally per
FND-003.

  • Fill out the PR template. The description you wrote is clear and useful, but it
    does not follow .github/pull_request_template.md.
    For a deploy-k8s/ docs PR most sections are short or N/A — that is fine, but the
    reviewer needs to know each section was considered, not skipped. Specifically needed:
    Blast radius, Security & Privacy Impact (Yes/No answers are required even when
    all are No), Compatibility, Rollback, and i18n Follow-Through. See the
    template for exactly what each section asks.
  • Set risk: and size: labels via the sidebar. The CI auto-assigned docs
    correctly, but risk: low and size: S are also required per the label registry.
    This PR qualifies for risk: low (new subtree, no runtime changes).
  • Assign to the v0.7.2 milestone. Per FND-003 §3.5, PRs are assigned to the
    milestone they target before merge. This fits cleanly under v0.7.2 maintenance scope.
    If you do not have milestone access, leave a comment here and a maintainer will set it.

✅ Commendations

The security context is complete — not just present.
runAsNonRoot, allowPrivilegeEscalation: false, readOnlyRootFilesystem: true,
capabilities.drop: ALL, seccompProfile.type: RuntimeDefault — this is the full
hardened profile. Most sample manifests in open-source projects include two or three of
these and omit the rest. Having all five here sets a baseline that users will copy
forward into their own cluster configs without thinking about it. Shipping secure defaults
in the starting point is how security posture propagates without requiring every
downstream user to know what to ask for.

The .gitignore pattern is elegant.
*.yaml + !*-sample.yaml means user copies are gitignored by default before they ever
have to remember to add them. The pattern is scoped to deploy-k8s/ so it does not
affect the rest of the repository. This is the kind of design that prevents secret leaks
from contributors who are moving fast and not thinking about what just got staged. The
convention is also self-documenting — anyone who reads the .gitignore understands the
copy-and-customize workflow immediately.

Secret injection is done correctly throughout.
The API key flows through a Kubernetes Secret and arrives in the container via
secretKeyRef, not hardcoded in the ConfigMap or as a literal env value. Using
stringData (not base64 data) in secret-sample.yaml is the right ergonomic choice
for a human-authored template — it is readable, diff-friendly, and the placeholder value
is unambiguous. This whole pattern is exactly what we want contributors to replicate.

Both probes are differentiated with real intent.
Readiness fires at 5s initial / 10s cycle; liveness fires at 10s initial / 60s cycle.
This is not cargo-culted from a tutorial — it reflects that the pod should stop receiving
traffic quickly when it is not ready, but should only be restarted under genuine
sustained failure. The distinction matters especially for an agent runtime that may be
mid-tool-execution when a transient health blip occurs.

The test evidence is the kind that makes a reviewer confident.
Pod running on NERC, route accessible, gateway healthy, pairing auth exercised, memory
footprint measured at ~6Mi idle. That is a complete deployment story, not a "manifests
look plausible" assertion. The ~6Mi figure is also genuinely useful signal for anyone
planning cluster resource allocation. Keep bringing this level of validation to future
PRs — it is exactly what the template's "Beyond CI" field is asking for.


🔴 Blocking

require_pairing = false ships an unauthenticated gateway as the default.

configmap-sample.yaml line 23 sets require_pairing = false. The README quick-start
takes the user from copy → edit API key → oc apply -f deploy-k8s/ in six steps. Anyone
who follows that path ends up with a ZeroClaw gateway publicly reachable on their
OpenShift Route with no authentication required.

The PR description notes "Pairing auth (require_pairing = true) verified working via
Route" — but the sample ships the opposite. There is a mismatch between what was tested
and what becomes the default for every user who copies this.

Change require_pairing = false to require_pairing = true in configmap-sample.yaml.

Per FND-006, secure defaults
belong in the starting point. Users who intentionally want a public endpoint (e.g.,
deployed behind a corporate SSO proxy that handles authentication at the network layer)
can change one line. Users who do not realize this setting exists should not have to
actively choose security — it should be the default they inherit.

A short comment above the line is welcome but not required:

# Set to false only if authentication is handled at the network/proxy layer.
require_pairing = true

🟡 Conditional

api_key = "" in the config.toml block is a V1 legacy field that will emit a
migration warning on every pod startup.

I traced the credential resolution path in crates/zeroclaw-providers/src/lib.rs. The
API_KEY env var injected from the Secret does work — it is the documented generic
fallback at the end of the resolution chain (provider-specific env vars are checked
first, then ZEROCLAW_API_KEY, then API_KEY). There is no functional bug here.

However, api_key = "" in config.toml is a V1 legacy field. V1Compat::has_legacy_fields()
returns true when api_key.is_some(), including for an empty string, and the runtime
logs a migration notice on every startup as a result. Users will see a deprecation
warning that references a migration step they have no reason to take. That is confusing
and noisy for an otherwise clean deployment.

Remove the api_key = "" line from the config.toml block in configmap-sample.yaml.
The API_KEY env var is resolved at the env-fallback stage regardless of whether the
legacy field is present. The line can be deleted without any change in runtime behavior.

If you want to make the provider-specific convention more explicit, you could also rename
the env var from API_KEY to ANTHROPIC_API_KEY in deployment-sample.yaml (that is
the name ZeroClaw's own error messages reference for Anthropic), but API_KEY is valid —
this is your call. The deletion of the legacy config field is the required part.


ℹ️ Notes (no action required to merge)

State and workspace are ephemeral.
Both state and workspace volumes are emptyDir: {} — agent memory, session history,
and workspace files are lost on pod restart. For a sample this is the right choice (it
avoids PVC complexity that would obscure the core deployment pattern). Worth a one-liner
in the README's Configuration table or a note before the Cleanup section so users are
not surprised when a pod reschedule wipes their agent's context:
"Note: state and workspace use emptyDir — agent memory does not persist across pod
restarts. For production deployments, replace these volumes with PersistentVolumeClaims."

No Ingress path for vanilla Kubernetes.
The Route object is OpenShift-specific. The test plan mentions "Test on vanilla
Kubernetes (without Route)" but the README only shows oc commands. A single line — "On
vanilla Kubernetes, replace route-sample.yaml with a Kubernetes Ingress targeting port
42617"
— would complete the story for non-OpenShift users without requiring a new file
this PR.

:latest image tag.
Adding a comment like # For production, replace :latest with a pinned version tag (e.g. v0.7.1)
aligns with the action-pinning discipline tracked in #5876
and signals good practice to readers who will copy this manifest forward.


Summary

Before this can merge:

  1. Fill out the PR template (Blast radius, Security & Privacy Impact, Compatibility,
    Rollback, i18n Follow-Through) — most answers will be "No" or "N/A", that is fine.
  2. Set risk: low and size: S labels via the sidebar.
  3. Assign to the v0.7.2 milestone (or ask a maintainer to set it).
  4. 🔴 Change require_pairing = falserequire_pairing = true in configmap-sample.yaml.
  5. 🟡 Remove api_key = "" from the config.toml block in configmap-sample.yaml.

Items 4 and 5 are both one-line changes in the same file. Once the template is filled and
the config defaults are corrected, this is ready to merge. The manifests are well-constructed,
the security hardening is right, and the cluster validation evidence is solid.

@WareWolf-MoonWall WareWolf-MoonWall added this to the v0.7.2 milestone Apr 18, 2026
Address PR zeroclaw-labs#5880 review feedback:
- Enable require_pairing by default in configmap-sample (was false)
- Remove legacy api_key field that triggers V1 migration warnings
- Add note about pinning :latest to a version tag
- Document ephemeral state and vanilla K8s Ingress alternative

Signed-off-by: Pavel Anni <panni@redhat.com>
Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Pavel Anni <panni@redhat.com>
@pavelanni
Copy link
Copy Markdown
Contributor Author

I pushed the changes and filled out the PR template. But it looks like I don't have access to the labels and milestone settings. Please let me know if I missed something.

Copy link
Copy Markdown
Collaborator

@WareWolf-MoonWall WareWolf-MoonWall left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Re-Review — #5880 feat(deploy): add OpenShift/K8s deployment manifests

Reviewing on commit 5ebc254. I read the full diff, the updated PR body, and the prior
review thread. Here is a precise accounting of what is resolved and what remains.


Resolved items ✅

🔴 Blocking — require_pairing = false (RESOLVED)

configmap-sample.yaml now has require_pairing = true. Verified directly in the
current diff. This was the most consequential item — it closes the unauthenticated
gateway default that the prior quick-start path would have shipped. ✅

🟡 Conditional — api_key = "" legacy field (RESOLVED)

The api_key = "" line is not present in the current configmap-sample.yaml diff.
The API_KEY env var from the Secret resolves correctly at the env-fallback stage
without it, and the migration warning on every pod startup is gone. ✅

ℹ️ Advisory notes — all three incorporated (RESOLVED)

All three informational notes from the prior review were picked up in the current
commits — no action was required, and each one was addressed anyway:

  • emptyDir persistence caveat: README now has a "State is ephemeral" note under
    Notes pointing users toward PersistentVolumeClaims for production. ✅
  • Vanilla Kubernetes path: README now has a "Vanilla Kubernetes" note directing
    non-OpenShift users to replace route-sample.yaml with a Kubernetes Ingress. ✅
  • :latest image tag: deployment-sample.yaml now carries the inline comment
    # For production, pin to a version tag (e.g. ghcr.io/zeroclaw-labs/zeroclaw:v0.7.1). ✅

This level of follow-through on advisory notes is not required — it is appreciated.

Milestone — v0.7.2 (RESOLVED)


Still open

🔴 PR template sections are missing

The current PR body has a Summary section and a Validation Evidence block, but the
required template sections are still absent. For a deploy-k8s/ docs PR most answers
are short — but the template exists so reviewers can confirm each dimension was
considered, and so the audit trail is consistent across all PRs per FND-003.

The sections still needed (from .github/pull_request_template.md):

  • Label Snapshotrisk: low, size: S, scope docs / deploy
  • Change Metadata — change type (feature or docs), primary scope
  • Security Impact — all four Yes/No fields (all No for this PR)
  • Privacy and Data Hygiene — data-hygiene status and neutral wording confirmation
  • Compatibility / Migration — backward compatible: Yes, no config/migration changes
  • i18n Follow-ThroughNo — no user-facing strings changed
  • Human Verification — the cluster test evidence you already have is exactly what
    belongs here; move it from Validation Evidence or duplicate it
  • Side Effects / Blast Radius — affected subsystems: deploy-k8s/ subtree only,
    no runtime changes
  • Rollback Plangit revert <sha> removes the subtree, no side effects

The answers for this PR are nearly all one-liners or "No / N/A". The substance is
already in your description — it is a matter of placing it into the correct sections.

🟡 Labels risk: low and size: S are not set

The label check shows only ["docs"]. Both risk: low and size: S are required
before merge. If you do not have label-setting access as a contributor, leave a comment
here and a maintainer (@theonlyhennygod or @singlerider) can apply them — this is not
a blocker on your end if access is the issue, just flag it.

🟡 Validation evidence is stale

The Validation Evidence block in the current PR body shows a local run with a
cargo clippy error in crates/zeroclaw-config/src/policy.rs:552. That error is a
pre-existing upstream issue unrelated to this PR (which touches no Rust files), and CI
is showing ✓ passing on the current commit. The body should either:

  • Replace the evidence block with a note pointing to the passing CI run on
    commit 5ebc254, or
  • Keep the local run output but add a sentence clarifying that the clippy error is a
    pre-existing upstream issue not introduced by this PR, and that CI on this branch
    passes.

Either is fine. The current state is just confusing — a reader sees a compile error
in the evidence block and then a green checkmark on the PR, and has to reconcile them
without explanation.


Code is correct — no new findings on the diff

To be explicit: the manifests themselves are in good shape. The security context is
complete, secret injection is correct, probe differentiation is intentional, the
.gitignore pattern is clean, and the config defaults now align with FND-006. There are
no new code-level findings in this re-review.


To merge

Two things left:

  1. Fill in the missing PR template sections (most are one-liners or "No").
  2. Set risk: low and size: S labels — or ask a maintainer to set them if you lack
    access.
  3. Update or annotate the validation evidence block to explain the pre-existing clippy
    noise.

Once those are done this is ready to merge.

@singlerider
Copy link
Copy Markdown
Collaborator

@pavelanni can you also take a look at and comment on #5890 when you have a chance while I do my PR review rounds?

Copy link
Copy Markdown
Collaborator

@WareWolf-MoonWall WareWolf-MoonWall left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Re-Review — #5880 feat(deploy): add OpenShift/K8s deployment manifests

Reviewing on commit 5ebc254. All three items from my prior CHANGES_REQUESTED have been
addressed. The manifests themselves are unchanged and remain correct. This is ready to merge.


Prior findings — resolved ✅

🔴 PR template sections missing (RESOLVED ✅)

All required sections are now present: Security & Privacy Impact (all four Yes/No fields
answered), Compatibility, Label Snapshot, Change Metadata, Privacy & Data Hygiene,
i18n Follow-Through, Side Effects / Blast Radius, and Rollback Plan. The answers are
exactly right for this PR type — short, precise, and honest about scope. The section
content matches what was already in the description; it just needed to be placed in the
correct structure for the audit trail. ✅

🟡 Labels risk: low and size: S not set (ADDRESSED ✅)

The Label Snapshot section explicitly notes that risk: low and size: S are the correct
labels, states the reason label permissions aren't available, and tags @theonlyhennygod
and @singlerider by name to apply them. This is exactly the right move for a contributor
without label access — the intent is on the record, the right people are named, and the
work is not blocked. The label application itself is a maintainer action, not a contributor
blocker. ✅

🟡 Validation evidence stale — pre-existing clippy error unexplained (RESOLVED ✅)

The NOTE at the top of the Validation Evidence section is clear and accurate: the clippy
error is pre-existing in zeroclaw-config/src/policy.rs:552, unrelated to this PR (which
touches no Rust files), and CI on 5ebc254 is passing green. A reader no longer has to
reconcile a compile error in the evidence block with a green CI checkmark without
explanation. ✅


No new findings on the diff

The diff is unchanged from the prior re-review. The security context, secret injection,
probe differentiation, .gitignore pattern, and config defaults are all still correct.
The three advisory notes from the first review (ephemeral state caveat, vanilla K8s path,
:latest pin comment) are still present in the README and deployment manifest. Nothing
new to raise.


🟢 Nitpick (entirely optional — do not hold the PR for this)

The Privacy & Data Hygiene section heading has a typo: "Privace" instead of "Privacy".
One character fix if you want to clean it up on a future edit, but this is purely cosmetic
and does not affect anything.


To merge

Two things remain — neither is on pavelanni's plate:

  1. Labels: A maintainer (@theonlyhennygod or @singlerider) needs to apply risk: low
    and size: S via the sidebar.
  2. Review sign-off: JordanTheJet and theonlyhennygod are listed as requested reviewers
    and have not yet weighed in. Once one of them reviews (or a maintainer clears the
    request), this is merge-ready.

The contribution is complete. The code is correct, the security posture is solid, the
cluster validation evidence is real, and the template is now fully filled. Nice work
closing the loop on all three items cleanly.

@WareWolf-MoonWall WareWolf-MoonWall added risk: low Auto risk: docs/chore-only paths. size: S Auto size: 81-250 non-doc changed lines. labels Apr 19, 2026
Copy link
Copy Markdown
Collaborator

@singlerider singlerider left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed. Purely additive deploy-k8s/ directory, no source changes. SecurityContext is properly hardened. emptyDir ephemerality is documented. No issues.

@singlerider singlerider merged commit c155705 into zeroclaw-labs:master Apr 20, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Auto scope: docs/markdown/template files changed. risk: low Auto risk: docs/chore-only paths. size: S Auto size: 81-250 non-doc changed lines.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants