Logs directory: /tmp/vpn-switch-test-results-20260203-153644 ==> Running tests on FreeBSD (local) ==> vpn-switch-unit-test.sh (minimal profile) ==> vpn-switch-unit-test.sh (all profile) ==> vpn-switch-integration-test.sh (minimal profile) ==> vpn-switch-integration-test.sh (all profile) ==> vpn-switch-architecture-test.sh (minimal profile) ==> vpn-switch-architecture-test.sh (all profile) ================================================================================ Test Results Summary - Tue Feb 3 19:44:51 CET 2026 ================================================================================ Status | Platform | Test Suite | Profile | Tests | Assert | Passed | Failed -------|----------|-------------------------------------|---------|-------|--------|--------|------- PASS | FreeBSD | vpn-switch-unit-test.sh | minimal | 146 | 371 | 371 | 0 PASS | FreeBSD | vpn-switch-unit-test.sh | all | 146 | 371 | 371 | 0 PASS | FreeBSD | vpn-switch-integration-test.sh | minimal | 12 | 296 | 296 | 0 PASS | FreeBSD | vpn-switch-integration-test.sh | all | 12 | 296 | 296 | 0 PASS | FreeBSD | vpn-switch-architecture-test.sh | minimal | 238 | 412 | 412 | 0 PASS | FreeBSD | vpn-switch-architecture-test.sh | all | 238 | 408 | 408 | 0 ================================================================================ ALL TESTS PASSED Total: 792 tests, 2154 assertions (2154 passed, 0 failed) Detailed logs saved to: /tmp/vpn-switch-test-results-20260203-153644 Logs directory: /tmp/vpn-switch-test-results-20260203-153649 ==> Running tests on Debian (brj@calabria.local) ==> Syncing code to remote... ==> Setting platform symlink... ==> vpn-switch-unit-test.sh (minimal profile) ==> vpn-switch-unit-test.sh (all profile) ==> vpn-switch-integration-test.sh (minimal profile) ==> vpn-switch-integration-test.sh (all profile) ==> vpn-switch-architecture-test.sh (minimal profile) ==> vpn-switch-architecture-test.sh (all profile) ================================================================================ Test Results Summary - Tue Feb 3 20:48:02 CET 2026 ================================================================================ Status | Platform | Test Suite | Profile | Tests | Assert | Passed | Failed -------|----------|-------------------------------------|---------|-------|--------|--------|------- PASS | Debian | vpn-switch-unit-test.sh | minimal | 146 | 371 | 371 | 0 PASS | Debian | vpn-switch-unit-test.sh | all | 146 | 371 | 371 | 0 PASS | Debian | vpn-switch-integration-test.sh | minimal | 12 | 296 | 296 | 0 PASS | Debian | vpn-switch-integration-test.sh | all | 12 | 296 | 296 | 0 PASS | Debian | vpn-switch-architecture-test.sh | minimal | 238 | 410 | 410 | 0 PASS | Debian | vpn-switch-architecture-test.sh | all | 238 | 410 | 410 | 0 ================================================================================ ALL TESTS PASSED Total: 792 tests, 2154 assertions (2154 passed, 0 failed) Detailed logs saved to: /tmp/vpn-switch-test-results-20260203-153649 ======================================== vpn-switch Architecture Test Suite ======================================== Testing architectural rules for combinator functions Profile: all Running Combinator Tests ======================================== Found 28 combinator functions TEST 1: Combinator: __session_exists1 - validate syntax with variations ✓ __session_exists1: Valid combinator syntax (all variations) TEST 2: Combinator: __session_conflicts2 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-1] ✓ __session_conflicts2: Valid combinator syntax (all variations) TEST 3: Combinator: __interface_check1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-2] ✓ __interface_check1: Valid combinator syntax (all variations) TEST 4: Combinator: __stop1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-3] ✓ __stop1: Valid combinator syntax (all variations) TEST 5: Combinator: __import1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-4] ✓ __import1: Valid combinator syntax (all variations) TEST 6: Combinator: __start1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-5] ✓ __start1: Valid combinator syntax (all variations) TEST 7: Combinator: __start0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-6] ✓ __start0: Valid combinator syntax (all variations) TEST 8: Combinator: __bootstrap1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-7] ✓ __bootstrap1: Valid combinator syntax (all variations) TEST 9: Combinator: __environment_cache0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-8] ✓ __environment_cache0: Valid combinator syntax (all variations) TEST 10: Combinator: __phases_lift1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-9] ✓ __phases_lift1: Valid combinator syntax (all variations) TEST 11: Combinator: __init0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-10] ✓ __init0: Valid combinator syntax (all variations) TEST 12: Combinator: __batch1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-11] ✓ __batch1: Valid combinator syntax (all variations) TEST 13: Combinator: __restore1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-12] ✓ __restore1: Valid combinator syntax (all variations) TEST 14: Combinator: __openvpn_start0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-13] ✓ __openvpn_start0: Valid combinator syntax (all variations) TEST 15: Combinator: __openvpn_start1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-14] ✓ __openvpn_start1: Valid combinator syntax (all variations) TEST 16: Combinator: __openvpn_stop1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-15] ✓ __openvpn_stop1: Valid combinator syntax (all variations) TEST 17: Combinator: __openvpn_add2 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-16] ✓ __openvpn_add2: Valid combinator syntax (all variations) TEST 18: Combinator: __openvpn_help0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-17] ✓ __openvpn_help0: Valid combinator syntax (all variations) TEST 19: Combinator: __session_disconnect1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-18] ✓ __session_disconnect1: Valid combinator syntax (all variations) TEST 20: Combinator: __session_show0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-19] ✓ __session_show0: Valid combinator syntax (all variations) TEST 21: Combinator: __session_start0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-20] ✓ __session_start0: Valid combinator syntax (all variations) TEST 22: Combinator: __session_start1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-21] ✓ __session_start1: Valid combinator syntax (all variations) TEST 23: Combinator: __session_help0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-22] ✓ __session_help0: Valid combinator syntax (all variations) TEST 24: Combinator: __wireguard_start0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-23] ✓ __wireguard_start0: Valid combinator syntax (all variations) TEST 25: Combinator: __wireguard_start1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-24] ✓ __wireguard_start1: Valid combinator syntax (all variations) TEST 26: Combinator: __wireguard_stop1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-25] ✓ __wireguard_stop1: Valid combinator syntax (all variations) TEST 27: Combinator: __wireguard_add2 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-26] ✓ __wireguard_add2: Valid combinator syntax (all variations) TEST 28: Combinator: __wireguard_help0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-27] ✓ __wireguard_help0: Valid combinator syntax (all variations) Running Batch Combinator Tests ======================================== Found 26 batch combinator functions TEST 29: Batch Combinator: ___session_prepare3 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-28] ✓ ___session_prepare3: Valid batch combinator syntax (all variations) TEST 30: Batch Combinator: ___stop0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-29] ✓ ___stop0: Valid batch combinator syntax (all variations) TEST 31: Batch Combinator: ___phases_sync1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-30] ✓ ___phases_sync1: Valid batch combinator syntax (all variations) TEST 32: Batch Combinator: ___phases_sync0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-31] ✓ ___phases_sync0: Valid batch combinator syntax (all variations) TEST 33: Batch Combinator: ___list0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-32] ✓ ___list0: Valid batch combinator syntax (all variations) TEST 34: Batch Combinator: ___bootstrap2 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-33] ✓ ___bootstrap2: Valid batch combinator syntax (all variations) TEST 35: Batch Combinator: ___init1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-34] ✓ ___init1: Valid batch combinator syntax (all variations) TEST 36: Batch Combinator: ___dumpenv1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-35] ✓ ___dumpenv1: Valid batch combinator syntax (all variations) TEST 37: Batch Combinator: ___dump0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-36] ✓ ___dump0: Valid batch combinator syntax (all variations) TEST 38: Batch Combinator: ___batch0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-37] ✓ ___batch0: Valid batch combinator syntax (all variations) TEST 39: Batch Combinator: ___environment_inspect0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-38] ✓ ___environment_inspect0: Valid batch combinator syntax (all variations) TEST 40: Batch Combinator: ___inspect0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-39] ✓ ___inspect0: Valid batch combinator syntax (all variations) TEST 41: Batch Combinator: ___openvpn_create1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-40] ✓ ___openvpn_create1: Valid batch combinator syntax (all variations) TEST 42: Batch Combinator: ___openvpn_stop0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-41] ✓ ___openvpn_stop0: Valid batch combinator syntax (all variations) TEST 43: Batch Combinator: ___openvpn_inspect0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-42] ✓ ___openvpn_inspect0: Valid batch combinator syntax (all variations) TEST 44: Batch Combinator: ___openvpn_clean0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-43] ✓ ___openvpn_clean0: Valid batch combinator syntax (all variations) TEST 45: Batch Combinator: ___openvpn_dump0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-44] ✓ ___openvpn_dump0: Valid batch combinator syntax (all variations) TEST 46: Batch Combinator: ___session_dump0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-45] ✓ ___session_dump0: Valid batch combinator syntax (all variations) TEST 47: Batch Combinator: ___session_inspect0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-46] ✓ ___session_inspect0: Valid batch combinator syntax (all variations) TEST 48: Batch Combinator: ___validate0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-47] ✓ ___validate0: Valid batch combinator syntax (all variations) TEST 49: Batch Combinator: ___wireguard_create1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-48] ✓ ___wireguard_create1: Valid batch combinator syntax (all variations) TEST 50: Batch Combinator: ___wireguard_inspect0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-49] ✓ ___wireguard_inspect0: Valid batch combinator syntax (all variations) TEST 51: Batch Combinator: ___wireguard_stop0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-50] ✓ ___wireguard_stop0: Valid batch combinator syntax (all variations) TEST 52: Batch Combinator: ___wireguard_clean0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-51] ✓ ___wireguard_clean0: Valid batch combinator syntax (all variations) TEST 53: Batch Combinator: ___wireguard_clean1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-52] ✓ ___wireguard_clean1: Valid batch combinator syntax (all variations) TEST 54: Batch Combinator: ___wireguard_dump0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.40159/test-53] ✓ ___wireguard_dump0: Valid batch combinator syntax (all variations) Running Terminal Function Tests ======================================== Found 83 terminal functions TEST 55: Terminal: _session_create1 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-54] ✓ _session_create1: Valid terminal function output (all variations) TEST 56: Terminal: _interface_destroy1 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-55] ✓ _interface_destroy1: Valid terminal function output (all variations) TEST 57: Terminal: _session_populate3 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-56] ✓ _session_populate3: Valid terminal function output (all variations) TEST 58: Terminal: _phases_copy0 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-57] ✓ _phases_copy0: Valid terminal function output (all variations) TEST 59: Terminal: _link2 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-58] ✓ _link2: Valid terminal function output (all variations) TEST 60: Terminal: _remove1 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-59] ✓ _remove1: Valid terminal function output (all variations) TEST 61: Terminal: _error1 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-60] ✓ _error1: Valid terminal function output (all variations) TEST 62: Terminal: _error2 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-61] ✓ _error2: Valid terminal function output (all variations) TEST 63: Terminal: _error3 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-62] ✓ _error3: Valid terminal function output (all variations) TEST 64: Terminal: _fail2 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-63] ✓ _fail2: Valid terminal function output (all variations) TEST 65: Terminal: _log1 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-64] ✓ _log1: Valid terminal function output (all variations) TEST 66: Terminal: _log2 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-65] ✓ _log2: Valid terminal function output (all variations) TEST 67: Terminal: _log3 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-66] ✓ _log3: Valid terminal function output (all variations) TEST 68: Terminal: _lift1 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-67] ✓ _lift1: Valid terminal function output (all variations) TEST 69: Terminal: _database_init0 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-68] ✓ _database_init0: Valid terminal function output (all variations) TEST 70: Terminal: _environment_init1 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-69] ✓ _environment_init1: Valid terminal function output (all variations) TEST 71: Terminal: _environment_cache1 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-70] ✓ _environment_cache1: Valid terminal function output (all variations) TEST 72: Terminal: _lift3 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-71] ✓ _lift3: Valid terminal function output (all variations) TEST 73: Terminal: _setenv2 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-72] ✓ _setenv2: Valid terminal function output (all variations) TEST 74: Terminal: _getenv1 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-73] ✓ _getenv1: Valid terminal function output (all variations) TEST 75: Terminal: _unsetenv1 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-74] ✓ _unsetenv1: Valid terminal function output (all variations) Skipped: _cat1 (requires special setup) TEST 76: Terminal: _batch2 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-75] ✓ _batch2: Valid terminal function output (all variations) TEST 77: Terminal: _printenv0 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-76] ✓ _printenv0: Valid terminal function output (all variations) TEST 78: Terminal: _status0 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-77] ✓ _status0: Valid terminal function output (all variations) TEST 79: Terminal: _help0 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-78] ✓ _help0: Valid terminal function output (all variations) TEST 80: Terminal: _help1 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-79] ✓ _help1: Valid terminal function output (all variations) TEST 81: Terminal: _database_enumerate0 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-80] ✓ _database_enumerate0: Valid terminal function output (all variations) TEST 82: Terminal: _system_inspect0 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-81] ✓ _system_inspect0: Valid terminal function output (all variations) TEST 83: Terminal: _logs_inspect0 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-82] ✓ _logs_inspect0: Valid terminal function output (all variations) TEST 84: Terminal: _phases_inspect0 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-83] ✓ _phases_inspect0: Valid terminal function output (all variations) TEST 85: Terminal: _summary_inspect0 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-84] ✓ _summary_inspect0: Valid terminal function output (all variations) TEST 86: Terminal: _prologue_inspect0 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-85] ✓ _prologue_inspect0: Valid terminal function output (all variations) TEST 87: Terminal: _openvpn_patch2 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-86] ✓ _openvpn_patch2: Valid terminal function output (all variations) TEST 88: Terminal: _openvpn_configure1 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-87] ✓ _openvpn_configure1: Valid terminal function output (all variations) TEST 89: Terminal: _openvpn_connect1 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-88] ✓ _openvpn_connect1: Valid terminal function output (all variations) TEST 90: Terminal: _openvpn_disconnect1 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-89] ✓ _openvpn_disconnect1: Valid terminal function output (all variations) TEST 91: Terminal: _openvpn_patch1 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-90] ✓ _openvpn_patch1: Valid terminal function output (all variations) TEST 92: Terminal: _openvpn_enumerate0 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-91] ✓ _openvpn_enumerate0: Valid terminal function output (all variations) TEST 93: Terminal: _openvpn_import1 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-92] ✓ _openvpn_import1: Valid terminal function output (all variations) TEST 94: Terminal: _openvpn_list0 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-93] ✓ _openvpn_list0: Valid terminal function output (all variations) TEST 95: Terminal: _openvpn_list1 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-94] ✓ _openvpn_list1: Valid terminal function output (all variations) TEST 96: Terminal: _openvpn_add1 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-95] ✓ _openvpn_add1: Valid terminal function output (all variations) TEST 97: Terminal: _openvpn_add3 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-96] ✓ _openvpn_add3: Valid terminal function output (all variations) TEST 98: Terminal: _openvpn_link2 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-97] ✓ _openvpn_link2: Valid terminal function output (all variations) TEST 99: Terminal: _openvpn_remove1 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-98] ✓ _openvpn_remove1: Valid terminal function output (all variations) TEST 100: Terminal: _openvpn_remove2 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-99] ✓ _openvpn_remove2: Valid terminal function output (all variations) TEST 101: Terminal: _openvpn_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-100] ✓ _openvpn_validate0: Valid terminal function output (all variations) TEST 102: Terminal: _openvpn_info1 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-101] ✓ _openvpn_info1: Valid terminal function output (all variations) TEST 103: Terminal: _session_list0 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-102] ✓ _session_list0: Valid terminal function output (all variations) TEST 104: Terminal: _session_show1 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-103] ✓ _session_show1: Valid terminal function output (all variations) TEST 105: Terminal: _session_remove1 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-104] ✓ _session_remove1: Valid terminal function output (all variations) TEST 106: Terminal: _session_connect1 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-105] ✓ _session_connect1: Valid terminal function output (all variations) TEST 107: Terminal: _session_save0 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-106] ✓ _session_save0: Valid terminal function output (all variations) TEST 108: Terminal: _session_save1 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-107] ✓ _session_save1: Valid terminal function output (all variations) TEST 109: Terminal: _session_clean0 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-108] ✓ _session_clean0: Valid terminal function output (all variations) TEST 110: Terminal: _session_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-109] ✓ _session_validate0: Valid terminal function output (all variations) TEST 111: Terminal: _session_enumerate0 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-110] ✓ _session_enumerate0: Valid terminal function output (all variations) TEST 112: Terminal: _session_describe0 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-111] ✓ _session_describe0: Valid terminal function output (all variations) TEST 113: Terminal: _logs_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-112] ✓ _logs_validate0: Valid terminal function output (all variations) TEST 114: Terminal: _logs_clean0 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-113] ✓ _logs_clean0: Valid terminal function output (all variations) TEST 115: Terminal: _phases_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-114] ✓ _phases_validate0: Valid terminal function output (all variations) TEST 116: Terminal: _database_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-115] ✓ _database_validate0: Valid terminal function output (all variations) TEST 117: Terminal: _binaries_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-116] ✓ _binaries_validate0: Valid terminal function output (all variations) TEST 118: Terminal: _network_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-117] ✓ _network_validate0: Valid terminal function output (all variations) TEST 119: Terminal: _permissions_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-118] ✓ _permissions_validate0: Valid terminal function output (all variations) TEST 120: Terminal: _environment_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-119] ✓ _environment_validate0: Valid terminal function output (all variations) TEST 121: Terminal: _wireguard_patch2 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-120] ✓ _wireguard_patch2: Valid terminal function output (all variations) TEST 122: Terminal: _wireguard_configure1 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-121] ✓ _wireguard_configure1: Valid terminal function output (all variations) TEST 123: Terminal: _wireguard_connect1 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-122] ✓ _wireguard_connect1: Valid terminal function output (all variations) TEST 124: Terminal: _wireguard_disconnect1 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-123] ✓ _wireguard_disconnect1: Valid terminal function output (all variations) TEST 125: Terminal: _wireguard_enumerate0 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-124] ✓ _wireguard_enumerate0: Valid terminal function output (all variations) TEST 126: Terminal: _wireguard_import1 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-125] ✓ _wireguard_import1: Valid terminal function output (all variations) TEST 127: Terminal: _wireguard_list0 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-126] ✓ _wireguard_list0: Valid terminal function output (all variations) TEST 128: Terminal: _wireguard_list1 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-127] ✓ _wireguard_list1: Valid terminal function output (all variations) TEST 129: Terminal: _wireguard_add1 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-128] ✓ _wireguard_add1: Valid terminal function output (all variations) TEST 130: Terminal: _wireguard_add3 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-129] ✓ _wireguard_add3: Valid terminal function output (all variations) TEST 131: Terminal: _wireguard_link2 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-130] ✓ _wireguard_link2: Valid terminal function output (all variations) TEST 132: Terminal: _wireguard_remove1 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-131] ✓ _wireguard_remove1: Valid terminal function output (all variations) TEST 133: Terminal: _wireguard_remove2 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-132] ✓ _wireguard_remove2: Valid terminal function output (all variations) TEST 134: Terminal: _wireguard_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-133] ✓ _wireguard_validate0: Valid terminal function output (all variations) TEST 135: Terminal: _wireguard_patch1 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-134] ✓ _wireguard_patch1: Valid terminal function output (all variations) TEST 136: Terminal: _wireguard_info1 - validate output rules [db: /tmp/vpn-switch-arch-test.40159/test-135] ✓ _wireguard_info1: Valid terminal function output (all variations) Running Error Propagation Tests (KEEP_GOING) ======================================== TEST 137: Batch Error Propagation - test _batch2 with failing commands [db: /tmp/vpn-switch-arch-test.40159/test-136] TEST 138: Sub-test: KEEP_GOING=0 (fail-fast mode) [db: /tmp/vpn-switch-arch-test.40159/test-137] ✓ KEEP_GOING=0: Batch execution stopped on first error TEST 139: Sub-test: KEEP_GOING=1 (continue mode) [db: /tmp/vpn-switch-arch-test.40159/test-137] ✓ KEEP_GOING=1: Batch execution completed despite errors ✓ KEEP_GOING=1: All commands were executed (count=3) TEST 140: Recursive Batch Error Propagation - test chained _batch2 calls [db: /tmp/vpn-switch-arch-test.40159/test-137] ✓ Recursive fail-fast: Command 3 in batch 3 was not executed ✓ Recursive fail-fast: Batch 2 stopped after error in batch 3 ✓ Recursive fail-fast: Batch 1 stopped after error in nested batch ✓ Recursive continue: Batch 2 continued after error in batch 3 ✓ Recursive continue: Batch 1 continued after error in nested batch TEST 141: Batch KEEP_GOING with Realistic Dump File [db: /tmp/vpn-switch-arch-test.40159/test-140] ✓ Created realistic batch file with 8 commands ✓ Selected command at position 6/8 for failure injection TEST 142: Sub-test: KEEP_GOING=0 at position 6/8 [db: /tmp/vpn-switch-arch-test.40159/test-141] ✓ KEEP_GOING=0: Stopped at or before position 6 (executed 6 commands) ✓ KEEP_GOING=0: Error stop message present TEST 143: Sub-test: KEEP_GOING=1 at position 6/8 [db: /tmp/vpn-switch-arch-test.40159/test-141] ✓ KEEP_GOING=1: All commands executed (8/8) ✓ KEEP_GOING=1: Completion message present ✓ KEEP_GOING=1: Failure markers present in output Running Batch Combinator Error Propagation Tests ======================================== Testing ALL batch combinators with error injection and KEEP_GOING validation Found 26 batch combinator functions TEST 144: Batch Transitive Hull: ___session_prepare3 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.40159/test-141] TEST 145: Sub-test: Walk command tree for '___session_prepare3' (command: session_prepare) [db: /tmp/vpn-switch-arch-test.40159/test-144] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 8 injectable nodes (combinators/batches) in tree Skipped: Could not select target node for injection TEST 146: Batch Transitive Hull: ___stop0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.40159/test-144] TEST 147: Sub-test: Walk command tree for '___stop0' (command: stop) [db: /tmp/vpn-switch-arch-test.40159/test-146] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 148: Sub-test: Inject failure at node '___stop0' (node 1/2) [db: /tmp/vpn-switch-arch-test.40159/test-146] ✓ KEEP_GOING affects output: fail-fast= 4 lines, continue= 4 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 149: Batch Transitive Hull: ___phases_sync1 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.40159/test-146] TEST 150: Sub-test: Walk command tree for '___phases_sync1' (command: phases_sync) [db: /tmp/vpn-switch-arch-test.40159/test-149] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 151: Sub-test: Inject failure at node '___phases_sync0' (node 1/2) [db: /tmp/vpn-switch-arch-test.40159/test-149] ✓ KEEP_GOING affects output: fail-fast= 4 lines, continue= 4 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 152: Batch Transitive Hull: ___phases_sync0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.40159/test-149] TEST 153: Sub-test: Walk command tree for '___phases_sync0' (command: phases_sync) [db: /tmp/vpn-switch-arch-test.40159/test-152] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 154: Sub-test: Inject failure at node '___phases_sync0' (node 1/2) [db: /tmp/vpn-switch-arch-test.40159/test-152] ✓ KEEP_GOING affects output: fail-fast= 4 lines, continue= 4 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 155: Batch Transitive Hull: ___list0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.40159/test-152] TEST 156: Sub-test: Walk command tree for '___list0' (command: list) [db: /tmp/vpn-switch-arch-test.40159/test-155] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 157: Sub-test: Inject failure at node '___list0' (node 1/2) [db: /tmp/vpn-switch-arch-test.40159/test-155] ✓ KEEP_GOING affects output: fail-fast= 2 lines, continue= 2 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 158: Batch Transitive Hull: ___bootstrap2 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.40159/test-155] TEST 159: Sub-test: Walk command tree for '___bootstrap2' (command: bootstrap) [db: /tmp/vpn-switch-arch-test.40159/test-158] ✓ Command tree collected: 2 nodes in transitive hull ✓ Found 6 injectable nodes (combinators/batches) in tree Skipped: Could not select target node for injection TEST 160: Batch Transitive Hull: ___init1 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.40159/test-158] TEST 161: Sub-test: Walk command tree for '___init1' (command: init) [db: /tmp/vpn-switch-arch-test.40159/test-160] ✓ Command tree collected: 2 nodes in transitive hull ✓ Found 1 injectable nodes (combinators/batches) in tree TEST 162: Sub-test: Inject failure at node '__init0' (node 1/1) [db: /tmp/vpn-switch-arch-test.40159/test-160] ✓ KEEP_GOING affects output: fail-fast= 1 lines, continue= 1 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 163: Batch Transitive Hull: ___dumpenv1 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.40159/test-160] TEST 164: Sub-test: Walk command tree for '___dumpenv1' (command: dumpenv) [db: /tmp/vpn-switch-arch-test.40159/test-163] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 8 injectable nodes (combinators/batches) in tree Skipped: Could not select target node for injection TEST 165: Batch Transitive Hull: ___dump0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.40159/test-163] TEST 166: Sub-test: Walk command tree for '___dump0' (command: dump) [db: /tmp/vpn-switch-arch-test.40159/test-165] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 167: Sub-test: Inject failure at node '___dump0' (node 1/2) [db: /tmp/vpn-switch-arch-test.40159/test-165] ✓ KEEP_GOING affects output: fail-fast= 17 lines, continue= 17 lines Note: No clear error stop indicator in fail-fast mode ✓ KEEP_GOING=1: Execution completed despite injected failure TEST 168: Batch Transitive Hull: ___batch0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.40159/test-165] TEST 169: Sub-test: Walk command tree for '___batch0' (command: batch) [db: /tmp/vpn-switch-arch-test.40159/test-168] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 170: Sub-test: Inject failure at node '___batch0' (node 1/2) [db: /tmp/vpn-switch-arch-test.40159/test-168] ✓ KEEP_GOING affects output: fail-fast= 2 lines, continue= 2 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 171: Batch Transitive Hull: ___environment_inspect0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.40159/test-168] TEST 172: Sub-test: Walk command tree for '___environment_inspect0' (command: environment_inspect) [db: /tmp/vpn-switch-arch-test.40159/test-171] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 173: Sub-test: Inject failure at node '___environment_inspect0' (node 1/2) [db: /tmp/vpn-switch-arch-test.40159/test-171] ✓ KEEP_GOING affects output: fail-fast= 3 lines, continue= 3 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 174: Batch Transitive Hull: ___inspect0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.40159/test-171] TEST 175: Sub-test: Walk command tree for '___inspect0' (command: inspect) [db: /tmp/vpn-switch-arch-test.40159/test-174] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 176: Sub-test: Inject failure at node '___inspect0' (node 1/2) [db: /tmp/vpn-switch-arch-test.40159/test-174] ✓ KEEP_GOING affects output: fail-fast= 12 lines, continue= 12 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 177: Batch Transitive Hull: ___openvpn_create1 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.40159/test-174] TEST 178: Sub-test: Walk command tree for '___openvpn_create1' (command: openvpn_create) [db: /tmp/vpn-switch-arch-test.40159/test-177] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 8 injectable nodes (combinators/batches) in tree Skipped: Could not select target node for injection TEST 179: Batch Transitive Hull: ___openvpn_stop0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.40159/test-177] TEST 180: Sub-test: Walk command tree for '___openvpn_stop0' (command: openvpn_stop) [db: /tmp/vpn-switch-arch-test.40159/test-179] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 1 injectable nodes (combinators/batches) in tree TEST 181: Sub-test: Inject failure at node '___openvpn_stop0' (node 1/1) [db: /tmp/vpn-switch-arch-test.40159/test-179] ✓ KEEP_GOING affects output: fail-fast= 1 lines, continue= 1 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 182: Batch Transitive Hull: ___openvpn_inspect0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.40159/test-179] TEST 183: Sub-test: Walk command tree for '___openvpn_inspect0' (command: openvpn_inspect) [db: /tmp/vpn-switch-arch-test.40159/test-182] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 184: Sub-test: Inject failure at node '___openvpn_inspect0' (node 1/2) [db: /tmp/vpn-switch-arch-test.40159/test-182] ✓ KEEP_GOING affects output: fail-fast= 7 lines, continue= 7 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 185: Batch Transitive Hull: ___openvpn_clean0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.40159/test-182] TEST 186: Sub-test: Walk command tree for '___openvpn_clean0' (command: openvpn_clean) [db: /tmp/vpn-switch-arch-test.40159/test-185] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 3 injectable nodes (combinators/batches) in tree Skipped: Could not select target node for injection TEST 187: Batch Transitive Hull: ___openvpn_dump0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.40159/test-185] TEST 188: Sub-test: Walk command tree for '___openvpn_dump0' (command: openvpn_dump) [db: /tmp/vpn-switch-arch-test.40159/test-187] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 189: Sub-test: Inject failure at node '___openvpn_dump0' (node 1/2) [db: /tmp/vpn-switch-arch-test.40159/test-187] ✓ KEEP_GOING affects output: fail-fast= 20 lines, continue= 20 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 190: Batch Transitive Hull: ___session_dump0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.40159/test-187] TEST 191: Sub-test: Walk command tree for '___session_dump0' (command: session_dump) [db: /tmp/vpn-switch-arch-test.40159/test-190] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 192: Sub-test: Inject failure at node '___session_dump0' (node 1/2) [db: /tmp/vpn-switch-arch-test.40159/test-190] ✓ KEEP_GOING affects output: fail-fast= 41 lines, continue= 41 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 193: Batch Transitive Hull: ___session_inspect0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.40159/test-190] TEST 194: Sub-test: Walk command tree for '___session_inspect0' (command: session_inspect) [db: /tmp/vpn-switch-arch-test.40159/test-193] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 195: Sub-test: Inject failure at node '___session_inspect0' (node 1/2) [db: /tmp/vpn-switch-arch-test.40159/test-193] ✓ KEEP_GOING affects output: fail-fast= 5 lines, continue= 5 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 196: Batch Transitive Hull: ___validate0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.40159/test-193] TEST 197: Sub-test: Walk command tree for '___validate0' (command: validate) [db: /tmp/vpn-switch-arch-test.40159/test-196] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 198: Sub-test: Inject failure at node '___validate0' (node 1/2) [db: /tmp/vpn-switch-arch-test.40159/test-196] ✓ KEEP_GOING affects output: fail-fast= 10 lines, continue= 10 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 199: Batch Transitive Hull: ___wireguard_create1 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.40159/test-196] TEST 200: Sub-test: Walk command tree for '___wireguard_create1' (command: wireguard_create) [db: /tmp/vpn-switch-arch-test.40159/test-199] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 8 injectable nodes (combinators/batches) in tree Skipped: Could not select target node for injection TEST 201: Batch Transitive Hull: ___wireguard_inspect0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.40159/test-199] TEST 202: Sub-test: Walk command tree for '___wireguard_inspect0' (command: wireguard_inspect) [db: /tmp/vpn-switch-arch-test.40159/test-201] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 203: Sub-test: Inject failure at node '___wireguard_inspect0' (node 1/2) [db: /tmp/vpn-switch-arch-test.40159/test-201] ✓ KEEP_GOING affects output: fail-fast= 7 lines, continue= 7 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 204: Batch Transitive Hull: ___wireguard_stop0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.40159/test-201] TEST 205: Sub-test: Walk command tree for '___wireguard_stop0' (command: wireguard_stop) [db: /tmp/vpn-switch-arch-test.40159/test-204] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 1 injectable nodes (combinators/batches) in tree TEST 206: Sub-test: Inject failure at node '___wireguard_stop0' (node 1/1) [db: /tmp/vpn-switch-arch-test.40159/test-204] ✓ KEEP_GOING affects output: fail-fast= 1 lines, continue= 1 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 207: Batch Transitive Hull: ___wireguard_clean0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.40159/test-204] TEST 208: Sub-test: Walk command tree for '___wireguard_clean0' (command: wireguard_clean) [db: /tmp/vpn-switch-arch-test.40159/test-207] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 3 injectable nodes (combinators/batches) in tree Skipped: Could not select target node for injection TEST 209: Batch Transitive Hull: ___wireguard_clean1 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.40159/test-207] TEST 210: Sub-test: Walk command tree for '___wireguard_clean1' (command: wireguard_clean) [db: /tmp/vpn-switch-arch-test.40159/test-209] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 3 injectable nodes (combinators/batches) in tree Skipped: Could not select target node for injection TEST 211: Batch Transitive Hull: ___wireguard_dump0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.40159/test-209] TEST 212: Sub-test: Walk command tree for '___wireguard_dump0' (command: wireguard_dump) [db: /tmp/vpn-switch-arch-test.40159/test-211] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 213: Sub-test: Inject failure at node '___wireguard_dump0' (node 1/2) [db: /tmp/vpn-switch-arch-test.40159/test-211] ✓ KEEP_GOING affects output: fail-fast= 42 lines, continue= 42 lines Note: No clear error stop indicator in fail-fast mode ✓ KEEP_GOING=1: Execution completed despite injected failure Running Batch Combinator KEEP_GOING Precise Tests ======================================== Testing ALL batch combinators with precise architectural KEEP_GOING validation Found 26 batch combinator functions TEST 214: Batch KEEP_GOING Precise: ___session_prepare3 [db: /tmp/vpn-switch-arch-test.40159/test-211] ✓ Captured 175 command lines from ___session_prepare3 ✓ Selected 95 random line(s) for failure injection Skipped: No functions were injected with failures TEST 215: Batch KEEP_GOING Precise: ___stop0 [db: /tmp/vpn-switch-arch-test.40159/test-214] ✓ Captured 2 command lines from ___stop0 ✓ Selected 1 random line(s) for failure injection ✓ Injected failures into 1 function(s) Note: Not all commands attempted (0/2) Note: This may indicate KEEP_GOING=0 or execution stopped early Skipped: ___phases_sync1 (requires phase template setup) Skipped: ___phases_sync0 (requires phase template setup) TEST 216: Batch KEEP_GOING Precise: ___list0 [db: /tmp/vpn-switch-arch-test.40159/test-215] ✓ Captured 2 command lines from ___list0 ✓ Selected 1 random line(s) for failure injection ✓ Injected failures into 1 function(s) ✓ KEEP_GOING=1: All commands attempted (2/2) TEST 217: Batch KEEP_GOING Precise: ___bootstrap2 [db: /tmp/vpn-switch-arch-test.40159/test-216] ✓ Captured 73 command lines from ___bootstrap2 ✓ Selected 67 random line(s) for failure injection Skipped: No functions were injected with failures Skipped: ___init1 (complex initialization logic) TEST 218: Batch KEEP_GOING Precise: ___dumpenv1 [db: /tmp/vpn-switch-arch-test.40159/test-217] ✓ Captured 175 command lines from ___dumpenv1 ✓ Selected 62 random line(s) for failure injection Skipped: No functions were injected with failures TEST 219: Batch KEEP_GOING Precise: ___dump0 [db: /tmp/vpn-switch-arch-test.40159/test-218] ✓ Captured 5 command lines from ___dump0 ✓ Selected 4 random line(s) for failure injection ✓ Injected failures into 3 function(s) Note: Not all commands attempted (3/5) Note: This may indicate KEEP_GOING=0 or execution stopped early TEST 220: Batch KEEP_GOING Precise: ___batch0 [db: /tmp/vpn-switch-arch-test.40159/test-219] ✓ Captured 2 command lines from ___batch0 ✓ Selected 1 random line(s) for failure injection Skipped: No functions were injected with failures TEST 221: Batch KEEP_GOING Precise: ___environment_inspect0 [db: /tmp/vpn-switch-arch-test.40159/test-220] ✓ Captured 2 command lines from ___environment_inspect0 ✓ Selected 2 random line(s) for failure injection ✓ Injected failures into 2 function(s) Note: Not all commands attempted (2/3) Note: This may indicate KEEP_GOING=0 or execution stopped early TEST 222: Batch KEEP_GOING Precise: ___inspect0 [db: /tmp/vpn-switch-arch-test.40159/test-221] ✓ Captured 12 command lines from ___inspect0 ✓ Selected 1 random line(s) for failure injection Skipped: No functions were injected with failures TEST 223: Batch KEEP_GOING Precise: ___openvpn_create1 [db: /tmp/vpn-switch-arch-test.40159/test-222] ✓ Captured 175 command lines from ___openvpn_create1 ✓ Selected 52 random line(s) for failure injection Skipped: No functions were injected with failures TEST 224: Batch KEEP_GOING Precise: ___openvpn_stop0 [db: /tmp/vpn-switch-arch-test.40159/test-223] ✓ Captured 1 command lines from ___openvpn_stop0 ✓ Selected 1 random line(s) for failure injection Skipped: No functions were injected with failures TEST 225: Batch KEEP_GOING Precise: ___openvpn_inspect0 [db: /tmp/vpn-switch-arch-test.40159/test-224] ✓ Captured 3 command lines from ___openvpn_inspect0 ✓ Selected 2 random line(s) for failure injection Skipped: No functions were injected with failures TEST 226: Batch KEEP_GOING Precise: ___openvpn_clean0 [db: /tmp/vpn-switch-arch-test.40159/test-225] ✓ Captured 3 command lines from ___openvpn_clean0 ✓ Selected 3 random line(s) for failure injection Skipped: No functions were injected with failures TEST 227: Batch KEEP_GOING Precise: ___openvpn_dump0 [db: /tmp/vpn-switch-arch-test.40159/test-226] ✓ Captured 13 command lines from ___openvpn_dump0 ✓ Selected 13 random line(s) for failure injection Skipped: No functions were injected with failures TEST 228: Batch KEEP_GOING Precise: ___session_dump0 [db: /tmp/vpn-switch-arch-test.40159/test-227] ✓ Captured 40 command lines from ___session_dump0 ✓ Selected 10 random line(s) for failure injection Skipped: No functions were injected with failures TEST 229: Batch KEEP_GOING Precise: ___session_inspect0 [db: /tmp/vpn-switch-arch-test.40159/test-228] ✓ Captured 4 command lines from ___session_inspect0 ✓ Selected 3 random line(s) for failure injection ✓ Injected failures into 3 function(s) Note: Not all commands attempted (3/4) Note: This may indicate KEEP_GOING=0 or execution stopped early TEST 230: Batch KEEP_GOING Precise: ___validate0 [db: /tmp/vpn-switch-arch-test.40159/test-229] ✓ Captured 10 command lines from ___validate0 ✓ Selected 10 random line(s) for failure injection ✓ Injected failures into 10 function(s) Note: Not all commands attempted (10/11) Note: This may indicate KEEP_GOING=0 or execution stopped early TEST 231: Batch KEEP_GOING Precise: ___wireguard_create1 [db: /tmp/vpn-switch-arch-test.40159/test-230] ✓ Captured 175 command lines from ___wireguard_create1 ✓ Selected 8 random line(s) for failure injection Skipped: No functions were injected with failures TEST 232: Batch KEEP_GOING Precise: ___wireguard_inspect0 [db: /tmp/vpn-switch-arch-test.40159/test-231] ✓ Captured 3 command lines from ___wireguard_inspect0 ✓ Selected 3 random line(s) for failure injection Skipped: No functions were injected with failures TEST 233: Batch KEEP_GOING Precise: ___wireguard_stop0 [db: /tmp/vpn-switch-arch-test.40159/test-232] ✓ Captured 1 command lines from ___wireguard_stop0 ✓ Selected 1 random line(s) for failure injection Skipped: No functions were injected with failures TEST 234: Batch KEEP_GOING Precise: ___wireguard_clean0 [db: /tmp/vpn-switch-arch-test.40159/test-233] ✓ Captured 9 command lines from ___wireguard_clean0 ✓ Selected 9 random line(s) for failure injection Skipped: No functions were injected with failures TEST 235: Batch KEEP_GOING Precise: ___wireguard_clean1 [db: /tmp/vpn-switch-arch-test.40159/test-234] ✓ Captured 9 command lines from ___wireguard_clean1 ✓ Selected 7 random line(s) for failure injection Skipped: No functions were injected with failures TEST 236: Batch KEEP_GOING Precise: ___wireguard_dump0 [db: /tmp/vpn-switch-arch-test.40159/test-235] ✓ Captured 34 command lines from ___wireguard_dump0 ✓ Selected 11 random line(s) for failure injection Skipped: No functions were injected with failures Running Static Analysis Tests ======================================== Testing architecture violation scanner TEST 237: Architecture Violation Scanner [db: /tmp/vpn-switch-arch-test.40159/test-236] ✓ Scanner executed successfully (exit code: 0) Found: \033[0;31m1\033[0m total violations ✓ Scanner detection working (violations found as expected) ✓ Scanner detects MODIFY_* variable usage Running Read-Only Database Tests ======================================== Testing that functions don't modify database at generation time TEST 238: Read-Only Database: All functions [db: /tmp/vpn-switch-arch-test.40159/test-236] Testing terminal functions... ✓ _session_create1: No permission errors on read-only database ✓ _interface_destroy1: No permission errors on read-only database ✓ _session_populate3: No permission errors on read-only database ✓ _link2: No permission errors on read-only database ✓ _remove1: No permission errors on read-only database ✓ _error1: No permission errors on read-only database ✓ _error2: No permission errors on read-only database ✓ _error3: No permission errors on read-only database ✓ _fail2: No permission errors on read-only database ✓ _log1: No permission errors on read-only database ✓ _log2: No permission errors on read-only database ✓ _log3: No permission errors on read-only database ✓ _lift1: No permission errors on read-only database ✓ _lift3: No permission errors on read-only database Warning: setenv2: output differs between writable/readonly (but compliant) ✓ _setenv2: No permission errors on read-only database ✓ _getenv1: No permission errors on read-only database ✓ _unsetenv1: No permission errors on read-only database ✓ _printenv0: No permission errors on read-only database Warning: status0: output differs between writable/readonly (but compliant) ✓ _status0: No permission errors on read-only database ✓ _help0: No permission errors on read-only database ✓ _help1: No permission errors on read-only database Warning: database_enumerate0: output differs between writable/readonly (but compliant) ✓ _database_enumerate0: No permission errors on read-only database ✓ _system_inspect0: No permission errors on read-only database Warning: logs_inspect0: output differs between writable/readonly (but compliant) ✓ _logs_inspect0: No permission errors on read-only database ✓ _phases_inspect0: No permission errors on read-only database ✓ _summary_inspect0: No permission errors on read-only database ✓ _prologue_inspect0: No permission errors on read-only database ✓ _openvpn_patch2: No permission errors on read-only database ✓ _openvpn_configure1: No permission errors on read-only database ✓ _openvpn_connect1: No permission errors on read-only database ✓ _openvpn_disconnect1: No permission errors on read-only database ✓ _openvpn_patch1: No permission errors on read-only database Warning: openvpn_enumerate0: output differs between writable/readonly (but compliant) ✓ _openvpn_enumerate0: No permission errors on read-only database ✓ _openvpn_import1: No permission errors on read-only database ✓ _openvpn_list0: No permission errors on read-only database ✓ _openvpn_list1: No permission errors on read-only database ✓ _openvpn_add1: No permission errors on read-only database ✓ _openvpn_add3: No permission errors on read-only database ✓ _openvpn_link2: No permission errors on read-only database ✓ _openvpn_remove1: No permission errors on read-only database ✓ _openvpn_remove2: No permission errors on read-only database ✓ _openvpn_validate0: No permission errors on read-only database ✓ _openvpn_info1: No permission errors on read-only database ✓ _session_list0: No permission errors on read-only database ✓ _session_show1: No permission errors on read-only database ✓ _session_remove1: No permission errors on read-only database ✓ _session_connect1: No permission errors on read-only database ✓ _session_save0: No permission errors on read-only database ✓ _session_save1: No permission errors on read-only database ✓ _session_clean0: No permission errors on read-only database ✓ _session_validate0: No permission errors on read-only database ✓ _session_enumerate0: No permission errors on read-only database ✓ _session_describe0: No permission errors on read-only database ✓ _logs_validate0: No permission errors on read-only database ✓ _logs_clean0: No permission errors on read-only database ✓ _phases_validate0: No permission errors on read-only database ✓ _database_validate0: No permission errors on read-only database ✓ _binaries_validate0: No permission errors on read-only database ✓ _network_validate0: No permission errors on read-only database ✓ _permissions_validate0: No permission errors on read-only database ✓ _environment_validate0: No permission errors on read-only database ✓ _wireguard_patch2: No permission errors on read-only database ✓ _wireguard_configure1: No permission errors on read-only database ✓ _wireguard_connect1: No permission errors on read-only database ✓ _wireguard_disconnect1: No permission errors on read-only database Warning: wireguard_enumerate0: output differs between writable/readonly (but compliant) ✓ _wireguard_enumerate0: No permission errors on read-only database ✓ _wireguard_import1: No permission errors on read-only database ✓ _wireguard_list0: No permission errors on read-only database ✓ _wireguard_list1: No permission errors on read-only database ✓ _wireguard_add1: No permission errors on read-only database ✓ _wireguard_add3: No permission errors on read-only database ✓ _wireguard_link2: No permission errors on read-only database ✓ _wireguard_remove1: No permission errors on read-only database ✓ _wireguard_remove2: No permission errors on read-only database ✓ _wireguard_validate0: No permission errors on read-only database ✓ _wireguard_patch1: No permission errors on read-only database ✓ _wireguard_info1: No permission errors on read-only database Testing combinator functions... ✓ __session_exists1: No permission errors on read-only database ✓ __session_conflicts2: No permission errors on read-only database ✓ __interface_check1: No permission errors on read-only database ✓ __stop1: No permission errors on read-only database ✓ __import1: No permission errors on read-only database ✓ __start1: No permission errors on read-only database ✓ __start0: No permission errors on read-only database ✓ __bootstrap1: No permission errors on read-only database ✓ __environment_cache0: No permission errors on read-only database ✓ __phases_lift1: No permission errors on read-only database ✓ __init0: No permission errors on read-only database ✓ __batch1: No permission errors on read-only database ✓ __restore1: No permission errors on read-only database Warning: openvpn_start0: output differs between writable/readonly (but compliant) ✓ __openvpn_start0: No permission errors on read-only database ✓ __openvpn_start1: No permission errors on read-only database ✓ __openvpn_stop1: No permission errors on read-only database ✓ __openvpn_add2: No permission errors on read-only database ✓ __openvpn_help0: No permission errors on read-only database ✓ __session_disconnect1: No permission errors on read-only database ✓ __session_show0: No permission errors on read-only database ✓ __session_start0: No permission errors on read-only database ✓ __session_start1: No permission errors on read-only database ✓ __session_help0: No permission errors on read-only database Warning: wireguard_start0: output differs between writable/readonly (but compliant) ✓ __wireguard_start0: No permission errors on read-only database ✓ __wireguard_start1: No permission errors on read-only database ✓ __wireguard_stop1: No permission errors on read-only database ✓ __wireguard_add2: No permission errors on read-only database ✓ __wireguard_help0: No permission errors on read-only database Testing batch combinator functions... ✓ ___session_prepare3: No permission errors on read-only database ✓ ___stop0: No permission errors on read-only database ✓ ___phases_sync1: No permission errors on read-only database ✓ ___phases_sync0: No permission errors on read-only database ✓ ___list0: No permission errors on read-only database ✓ ___dumpenv1: No permission errors on read-only database Warning: dump0: output differs between writable/readonly (but compliant) ✓ ___dump0: No permission errors on read-only database Warning: batch0: output differs between writable/readonly (but compliant) ✓ ___batch0: No permission errors on read-only database ✓ ___environment_inspect0: No permission errors on read-only database ✓ ___inspect0: No permission errors on read-only database Warning: openvpn_create1: output differs between writable/readonly (but compliant) ✓ ___openvpn_create1: No permission errors on read-only database ✓ ___openvpn_stop0: No permission errors on read-only database ✓ ___openvpn_inspect0: No permission errors on read-only database ✓ ___openvpn_clean0: No permission errors on read-only database ✓ ___openvpn_dump0: No permission errors on read-only database ✓ ___session_dump0: No permission errors on read-only database ✓ ___session_inspect0: No permission errors on read-only database ✓ ___validate0: No permission errors on read-only database Warning: wireguard_create1: output differs between writable/readonly (but compliant) ✓ ___wireguard_create1: No permission errors on read-only database ✓ ___wireguard_inspect0: No permission errors on read-only database ✓ ___wireguard_stop0: No permission errors on read-only database ✓ ___wireguard_clean0: No permission errors on read-only database ✓ ___wireguard_clean1: No permission errors on read-only database ✓ ___wireguard_dump0: No permission errors on read-only database Summary: Tested 129 functions, skipped 8 ======================================== Architecture Test Summary ======================================== Test Functions: 238 Total Assertions: 408 Passed Assertions: 408 Failed Assertions: 0 ALL TESTS PASSED Cleaning up test databases... Done. ======================================== vpn-switch Architecture Test Suite ======================================== Testing architectural rules for combinator functions Profile: minimal Running Combinator Tests ======================================== Found 28 combinator functions TEST 1: Combinator: __session_exists1 - validate syntax with variations ✓ __session_exists1: Valid combinator syntax (all variations) TEST 2: Combinator: __session_conflicts2 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-1] ✓ __session_conflicts2: Valid combinator syntax (all variations) TEST 3: Combinator: __interface_check1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-2] ✓ __interface_check1: Valid combinator syntax (all variations) TEST 4: Combinator: __stop1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-3] ✓ __stop1: Valid combinator syntax (all variations) TEST 5: Combinator: __import1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-4] ✓ __import1: Valid combinator syntax (all variations) TEST 6: Combinator: __start1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-5] ✓ __start1: Valid combinator syntax (all variations) TEST 7: Combinator: __start0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-6] ✓ __start0: Valid combinator syntax (all variations) TEST 8: Combinator: __bootstrap1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-7] ✓ __bootstrap1: Valid combinator syntax (all variations) TEST 9: Combinator: __environment_cache0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-8] ✓ __environment_cache0: Valid combinator syntax (all variations) TEST 10: Combinator: __phases_lift1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-9] ✓ __phases_lift1: Valid combinator syntax (all variations) TEST 11: Combinator: __init0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-10] ✓ __init0: Valid combinator syntax (all variations) TEST 12: Combinator: __batch1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-11] ✓ __batch1: Valid combinator syntax (all variations) TEST 13: Combinator: __restore1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-12] ✓ __restore1: Valid combinator syntax (all variations) TEST 14: Combinator: __openvpn_start0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-13] ✓ __openvpn_start0: Valid combinator syntax (all variations) TEST 15: Combinator: __openvpn_start1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-14] ✓ __openvpn_start1: Valid combinator syntax (all variations) TEST 16: Combinator: __openvpn_stop1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-15] ✓ __openvpn_stop1: Valid combinator syntax (all variations) TEST 17: Combinator: __openvpn_add2 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-16] ✓ __openvpn_add2: Valid combinator syntax (all variations) TEST 18: Combinator: __openvpn_help0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-17] ✓ __openvpn_help0: Valid combinator syntax (all variations) TEST 19: Combinator: __session_disconnect1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-18] ✓ __session_disconnect1: Valid combinator syntax (all variations) TEST 20: Combinator: __session_show0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-19] ✓ __session_show0: Valid combinator syntax (all variations) TEST 21: Combinator: __session_start0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-20] ✓ __session_start0: Valid combinator syntax (all variations) TEST 22: Combinator: __session_start1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-21] ✓ __session_start1: Valid combinator syntax (all variations) TEST 23: Combinator: __session_help0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-22] ✓ __session_help0: Valid combinator syntax (all variations) TEST 24: Combinator: __wireguard_start0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-23] ✓ __wireguard_start0: Valid combinator syntax (all variations) TEST 25: Combinator: __wireguard_start1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-24] ✓ __wireguard_start1: Valid combinator syntax (all variations) TEST 26: Combinator: __wireguard_stop1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-25] ✓ __wireguard_stop1: Valid combinator syntax (all variations) TEST 27: Combinator: __wireguard_add2 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-26] ✓ __wireguard_add2: Valid combinator syntax (all variations) TEST 28: Combinator: __wireguard_help0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-27] ✓ __wireguard_help0: Valid combinator syntax (all variations) Running Batch Combinator Tests ======================================== Found 26 batch combinator functions TEST 29: Batch Combinator: ___session_prepare3 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-28] ✓ ___session_prepare3: Valid batch combinator syntax (all variations) TEST 30: Batch Combinator: ___stop0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-29] ✓ ___stop0: Valid batch combinator syntax (all variations) TEST 31: Batch Combinator: ___phases_sync1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-30] ✓ ___phases_sync1: Valid batch combinator syntax (all variations) TEST 32: Batch Combinator: ___phases_sync0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-31] ✓ ___phases_sync0: Valid batch combinator syntax (all variations) TEST 33: Batch Combinator: ___list0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-32] ✓ ___list0: Valid batch combinator syntax (all variations) TEST 34: Batch Combinator: ___bootstrap2 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-33] ✓ ___bootstrap2: Valid batch combinator syntax (all variations) TEST 35: Batch Combinator: ___init1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-34] ✓ ___init1: Valid batch combinator syntax (all variations) TEST 36: Batch Combinator: ___dumpenv1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-35] ✓ ___dumpenv1: Valid batch combinator syntax (all variations) TEST 37: Batch Combinator: ___dump0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-36] ✓ ___dump0: Valid batch combinator syntax (all variations) TEST 38: Batch Combinator: ___batch0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-37] ✓ ___batch0: Valid batch combinator syntax (all variations) TEST 39: Batch Combinator: ___environment_inspect0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-38] ✓ ___environment_inspect0: Valid batch combinator syntax (all variations) TEST 40: Batch Combinator: ___inspect0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-39] ✓ ___inspect0: Valid batch combinator syntax (all variations) TEST 41: Batch Combinator: ___openvpn_create1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-40] ✓ ___openvpn_create1: Valid batch combinator syntax (all variations) TEST 42: Batch Combinator: ___openvpn_stop0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-41] ✓ ___openvpn_stop0: Valid batch combinator syntax (all variations) TEST 43: Batch Combinator: ___openvpn_inspect0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-42] ✓ ___openvpn_inspect0: Valid batch combinator syntax (all variations) TEST 44: Batch Combinator: ___openvpn_clean0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-43] ✓ ___openvpn_clean0: Valid batch combinator syntax (all variations) TEST 45: Batch Combinator: ___openvpn_dump0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-44] ✓ ___openvpn_dump0: Valid batch combinator syntax (all variations) TEST 46: Batch Combinator: ___session_dump0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-45] ✓ ___session_dump0: Valid batch combinator syntax (all variations) TEST 47: Batch Combinator: ___session_inspect0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-46] ✓ ___session_inspect0: Valid batch combinator syntax (all variations) TEST 48: Batch Combinator: ___validate0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-47] ✓ ___validate0: Valid batch combinator syntax (all variations) TEST 49: Batch Combinator: ___wireguard_create1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-48] ✓ ___wireguard_create1: Valid batch combinator syntax (all variations) TEST 50: Batch Combinator: ___wireguard_inspect0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-49] ✓ ___wireguard_inspect0: Valid batch combinator syntax (all variations) TEST 51: Batch Combinator: ___wireguard_stop0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-50] ✓ ___wireguard_stop0: Valid batch combinator syntax (all variations) TEST 52: Batch Combinator: ___wireguard_clean0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-51] ✓ ___wireguard_clean0: Valid batch combinator syntax (all variations) TEST 53: Batch Combinator: ___wireguard_clean1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-52] ✓ ___wireguard_clean1: Valid batch combinator syntax (all variations) TEST 54: Batch Combinator: ___wireguard_dump0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.18197/test-53] ✓ ___wireguard_dump0: Valid batch combinator syntax (all variations) Running Terminal Function Tests ======================================== Found 83 terminal functions TEST 55: Terminal: _session_create1 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-54] ✓ _session_create1: Valid terminal function output (all variations) TEST 56: Terminal: _interface_destroy1 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-55] ✓ _interface_destroy1: Valid terminal function output (all variations) TEST 57: Terminal: _session_populate3 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-56] ✓ _session_populate3: Valid terminal function output (all variations) TEST 58: Terminal: _phases_copy0 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-57] ✓ _phases_copy0: Valid terminal function output (all variations) TEST 59: Terminal: _link2 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-58] ✓ _link2: Valid terminal function output (all variations) TEST 60: Terminal: _remove1 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-59] ✓ _remove1: Valid terminal function output (all variations) TEST 61: Terminal: _error1 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-60] ✓ _error1: Valid terminal function output (all variations) TEST 62: Terminal: _error2 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-61] ✓ _error2: Valid terminal function output (all variations) TEST 63: Terminal: _error3 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-62] ✓ _error3: Valid terminal function output (all variations) TEST 64: Terminal: _fail2 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-63] ✓ _fail2: Valid terminal function output (all variations) TEST 65: Terminal: _log1 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-64] ✓ _log1: Valid terminal function output (all variations) TEST 66: Terminal: _log2 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-65] ✓ _log2: Valid terminal function output (all variations) TEST 67: Terminal: _log3 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-66] ✓ _log3: Valid terminal function output (all variations) TEST 68: Terminal: _lift1 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-67] ✓ _lift1: Valid terminal function output (all variations) TEST 69: Terminal: _database_init0 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-68] ✓ _database_init0: Valid terminal function output (all variations) TEST 70: Terminal: _environment_init1 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-69] ✓ _environment_init1: Valid terminal function output (all variations) TEST 71: Terminal: _environment_cache1 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-70] ✓ _environment_cache1: Valid terminal function output (all variations) TEST 72: Terminal: _lift3 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-71] ✓ _lift3: Valid terminal function output (all variations) TEST 73: Terminal: _setenv2 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-72] ✓ _setenv2: Valid terminal function output (all variations) TEST 74: Terminal: _getenv1 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-73] ✓ _getenv1: Valid terminal function output (all variations) TEST 75: Terminal: _unsetenv1 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-74] ✓ _unsetenv1: Valid terminal function output (all variations) Skipped: _cat1 (requires special setup) TEST 76: Terminal: _batch2 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-75] ✓ _batch2: Valid terminal function output (all variations) TEST 77: Terminal: _printenv0 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-76] ✓ _printenv0: Valid terminal function output (all variations) TEST 78: Terminal: _status0 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-77] ✓ _status0: Valid terminal function output (all variations) TEST 79: Terminal: _help0 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-78] ✓ _help0: Valid terminal function output (all variations) TEST 80: Terminal: _help1 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-79] ✓ _help1: Valid terminal function output (all variations) TEST 81: Terminal: _database_enumerate0 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-80] ✓ _database_enumerate0: Valid terminal function output (all variations) TEST 82: Terminal: _system_inspect0 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-81] ✓ _system_inspect0: Valid terminal function output (all variations) TEST 83: Terminal: _logs_inspect0 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-82] ✓ _logs_inspect0: Valid terminal function output (all variations) TEST 84: Terminal: _phases_inspect0 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-83] ✓ _phases_inspect0: Valid terminal function output (all variations) TEST 85: Terminal: _summary_inspect0 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-84] ✓ _summary_inspect0: Valid terminal function output (all variations) TEST 86: Terminal: _prologue_inspect0 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-85] ✓ _prologue_inspect0: Valid terminal function output (all variations) TEST 87: Terminal: _openvpn_patch2 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-86] ✓ _openvpn_patch2: Valid terminal function output (all variations) TEST 88: Terminal: _openvpn_configure1 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-87] ✓ _openvpn_configure1: Valid terminal function output (all variations) TEST 89: Terminal: _openvpn_connect1 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-88] ✓ _openvpn_connect1: Valid terminal function output (all variations) TEST 90: Terminal: _openvpn_disconnect1 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-89] ✓ _openvpn_disconnect1: Valid terminal function output (all variations) TEST 91: Terminal: _openvpn_patch1 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-90] ✓ _openvpn_patch1: Valid terminal function output (all variations) TEST 92: Terminal: _openvpn_enumerate0 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-91] ✓ _openvpn_enumerate0: Valid terminal function output (all variations) TEST 93: Terminal: _openvpn_import1 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-92] ✓ _openvpn_import1: Valid terminal function output (all variations) TEST 94: Terminal: _openvpn_list0 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-93] ✓ _openvpn_list0: Valid terminal function output (all variations) TEST 95: Terminal: _openvpn_list1 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-94] ✓ _openvpn_list1: Valid terminal function output (all variations) TEST 96: Terminal: _openvpn_add1 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-95] ✓ _openvpn_add1: Valid terminal function output (all variations) TEST 97: Terminal: _openvpn_add3 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-96] ✓ _openvpn_add3: Valid terminal function output (all variations) TEST 98: Terminal: _openvpn_link2 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-97] ✓ _openvpn_link2: Valid terminal function output (all variations) TEST 99: Terminal: _openvpn_remove1 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-98] ✓ _openvpn_remove1: Valid terminal function output (all variations) TEST 100: Terminal: _openvpn_remove2 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-99] ✓ _openvpn_remove2: Valid terminal function output (all variations) TEST 101: Terminal: _openvpn_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-100] ✓ _openvpn_validate0: Valid terminal function output (all variations) TEST 102: Terminal: _openvpn_info1 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-101] ✓ _openvpn_info1: Valid terminal function output (all variations) TEST 103: Terminal: _session_list0 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-102] ✓ _session_list0: Valid terminal function output (all variations) TEST 104: Terminal: _session_show1 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-103] ✓ _session_show1: Valid terminal function output (all variations) TEST 105: Terminal: _session_remove1 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-104] ✓ _session_remove1: Valid terminal function output (all variations) TEST 106: Terminal: _session_connect1 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-105] ✓ _session_connect1: Valid terminal function output (all variations) TEST 107: Terminal: _session_save0 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-106] ✓ _session_save0: Valid terminal function output (all variations) TEST 108: Terminal: _session_save1 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-107] ✓ _session_save1: Valid terminal function output (all variations) TEST 109: Terminal: _session_clean0 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-108] ✓ _session_clean0: Valid terminal function output (all variations) TEST 110: Terminal: _session_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-109] ✓ _session_validate0: Valid terminal function output (all variations) TEST 111: Terminal: _session_enumerate0 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-110] ✓ _session_enumerate0: Valid terminal function output (all variations) TEST 112: Terminal: _session_describe0 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-111] ✓ _session_describe0: Valid terminal function output (all variations) TEST 113: Terminal: _logs_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-112] ✓ _logs_validate0: Valid terminal function output (all variations) TEST 114: Terminal: _logs_clean0 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-113] ✓ _logs_clean0: Valid terminal function output (all variations) TEST 115: Terminal: _phases_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-114] ✓ _phases_validate0: Valid terminal function output (all variations) TEST 116: Terminal: _database_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-115] ✓ _database_validate0: Valid terminal function output (all variations) TEST 117: Terminal: _binaries_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-116] ✓ _binaries_validate0: Valid terminal function output (all variations) TEST 118: Terminal: _network_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-117] ✓ _network_validate0: Valid terminal function output (all variations) TEST 119: Terminal: _permissions_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-118] ✓ _permissions_validate0: Valid terminal function output (all variations) TEST 120: Terminal: _environment_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-119] ✓ _environment_validate0: Valid terminal function output (all variations) TEST 121: Terminal: _wireguard_patch2 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-120] ✓ _wireguard_patch2: Valid terminal function output (all variations) TEST 122: Terminal: _wireguard_configure1 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-121] ✓ _wireguard_configure1: Valid terminal function output (all variations) TEST 123: Terminal: _wireguard_connect1 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-122] ✓ _wireguard_connect1: Valid terminal function output (all variations) TEST 124: Terminal: _wireguard_disconnect1 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-123] ✓ _wireguard_disconnect1: Valid terminal function output (all variations) TEST 125: Terminal: _wireguard_enumerate0 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-124] ✓ _wireguard_enumerate0: Valid terminal function output (all variations) TEST 126: Terminal: _wireguard_import1 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-125] ✓ _wireguard_import1: Valid terminal function output (all variations) TEST 127: Terminal: _wireguard_list0 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-126] ✓ _wireguard_list0: Valid terminal function output (all variations) TEST 128: Terminal: _wireguard_list1 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-127] ✓ _wireguard_list1: Valid terminal function output (all variations) TEST 129: Terminal: _wireguard_add1 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-128] ✓ _wireguard_add1: Valid terminal function output (all variations) TEST 130: Terminal: _wireguard_add3 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-129] ✓ _wireguard_add3: Valid terminal function output (all variations) TEST 131: Terminal: _wireguard_link2 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-130] ✓ _wireguard_link2: Valid terminal function output (all variations) TEST 132: Terminal: _wireguard_remove1 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-131] ✓ _wireguard_remove1: Valid terminal function output (all variations) TEST 133: Terminal: _wireguard_remove2 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-132] ✓ _wireguard_remove2: Valid terminal function output (all variations) TEST 134: Terminal: _wireguard_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-133] ✓ _wireguard_validate0: Valid terminal function output (all variations) TEST 135: Terminal: _wireguard_patch1 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-134] ✓ _wireguard_patch1: Valid terminal function output (all variations) TEST 136: Terminal: _wireguard_info1 - validate output rules [db: /tmp/vpn-switch-arch-test.18197/test-135] ✓ _wireguard_info1: Valid terminal function output (all variations) Running Error Propagation Tests (KEEP_GOING) ======================================== TEST 137: Batch Error Propagation - test _batch2 with failing commands [db: /tmp/vpn-switch-arch-test.18197/test-136] TEST 138: Sub-test: KEEP_GOING=0 (fail-fast mode) [db: /tmp/vpn-switch-arch-test.18197/test-137] ✓ KEEP_GOING=0: Batch execution stopped on first error TEST 139: Sub-test: KEEP_GOING=1 (continue mode) [db: /tmp/vpn-switch-arch-test.18197/test-137] ✓ KEEP_GOING=1: Batch execution completed despite errors ✓ KEEP_GOING=1: All commands were executed (count=3) TEST 140: Recursive Batch Error Propagation - test chained _batch2 calls [db: /tmp/vpn-switch-arch-test.18197/test-137] ✓ Recursive fail-fast: Command 3 in batch 3 was not executed ✓ Recursive fail-fast: Batch 2 stopped after error in batch 3 ✓ Recursive fail-fast: Batch 1 stopped after error in nested batch ✓ Recursive continue: Batch 2 continued after error in batch 3 ✓ Recursive continue: Batch 1 continued after error in nested batch TEST 141: Batch KEEP_GOING with Realistic Dump File [db: /tmp/vpn-switch-arch-test.18197/test-140] ✓ Created realistic batch file with 8 commands ✓ Selected command at position 5/8 for failure injection TEST 142: Sub-test: KEEP_GOING=0 at position 5/8 [db: /tmp/vpn-switch-arch-test.18197/test-141] ✓ KEEP_GOING=0: Stopped at or before position 5 (executed 5 commands) ✓ KEEP_GOING=0: Error stop message present TEST 143: Sub-test: KEEP_GOING=1 at position 5/8 [db: /tmp/vpn-switch-arch-test.18197/test-141] ✓ KEEP_GOING=1: All commands executed (8/8) ✓ KEEP_GOING=1: Completion message present ✓ KEEP_GOING=1: Failure markers present in output Running Batch Combinator Error Propagation Tests ======================================== Testing ALL batch combinators with error injection and KEEP_GOING validation Found 26 batch combinator functions TEST 144: Batch Transitive Hull: ___session_prepare3 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.18197/test-141] TEST 145: Sub-test: Walk command tree for '___session_prepare3' (command: session_prepare) [db: /tmp/vpn-switch-arch-test.18197/test-144] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 8 injectable nodes (combinators/batches) in tree Skipped: Could not select target node for injection TEST 146: Batch Transitive Hull: ___stop0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.18197/test-144] TEST 147: Sub-test: Walk command tree for '___stop0' (command: stop) [db: /tmp/vpn-switch-arch-test.18197/test-146] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 148: Sub-test: Inject failure at node '___stop0' (node 1/2) [db: /tmp/vpn-switch-arch-test.18197/test-146] ✓ KEEP_GOING affects output: fail-fast= 4 lines, continue= 4 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 149: Batch Transitive Hull: ___phases_sync1 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.18197/test-146] TEST 150: Sub-test: Walk command tree for '___phases_sync1' (command: phases_sync) [db: /tmp/vpn-switch-arch-test.18197/test-149] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 151: Sub-test: Inject failure at node '___phases_sync0' (node 1/2) [db: /tmp/vpn-switch-arch-test.18197/test-149] ✓ KEEP_GOING affects output: fail-fast= 4 lines, continue= 4 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 152: Batch Transitive Hull: ___phases_sync0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.18197/test-149] TEST 153: Sub-test: Walk command tree for '___phases_sync0' (command: phases_sync) [db: /tmp/vpn-switch-arch-test.18197/test-152] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 154: Sub-test: Inject failure at node '___phases_sync0' (node 1/2) [db: /tmp/vpn-switch-arch-test.18197/test-152] ✓ KEEP_GOING affects output: fail-fast= 4 lines, continue= 4 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 155: Batch Transitive Hull: ___list0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.18197/test-152] TEST 156: Sub-test: Walk command tree for '___list0' (command: list) [db: /tmp/vpn-switch-arch-test.18197/test-155] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 157: Sub-test: Inject failure at node '___list0' (node 1/2) [db: /tmp/vpn-switch-arch-test.18197/test-155] ✓ KEEP_GOING affects output: fail-fast= 2 lines, continue= 2 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 158: Batch Transitive Hull: ___bootstrap2 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.18197/test-155] TEST 159: Sub-test: Walk command tree for '___bootstrap2' (command: bootstrap) [db: /tmp/vpn-switch-arch-test.18197/test-158] ✓ Command tree collected: 2 nodes in transitive hull ✓ Found 6 injectable nodes (combinators/batches) in tree Skipped: Could not select target node for injection TEST 160: Batch Transitive Hull: ___init1 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.18197/test-158] TEST 161: Sub-test: Walk command tree for '___init1' (command: init) [db: /tmp/vpn-switch-arch-test.18197/test-160] ✓ Command tree collected: 2 nodes in transitive hull ✓ Found 1 injectable nodes (combinators/batches) in tree TEST 162: Sub-test: Inject failure at node '__init0' (node 1/1) [db: /tmp/vpn-switch-arch-test.18197/test-160] ✓ KEEP_GOING affects output: fail-fast= 1 lines, continue= 1 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 163: Batch Transitive Hull: ___dumpenv1 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.18197/test-160] TEST 164: Sub-test: Walk command tree for '___dumpenv1' (command: dumpenv) [db: /tmp/vpn-switch-arch-test.18197/test-163] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 8 injectable nodes (combinators/batches) in tree Skipped: Could not select target node for injection TEST 165: Batch Transitive Hull: ___dump0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.18197/test-163] TEST 166: Sub-test: Walk command tree for '___dump0' (command: dump) [db: /tmp/vpn-switch-arch-test.18197/test-165] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 167: Sub-test: Inject failure at node '___dump0' (node 1/2) [db: /tmp/vpn-switch-arch-test.18197/test-165] ✓ KEEP_GOING affects output: fail-fast= 17 lines, continue= 17 lines Note: No clear error stop indicator in fail-fast mode ✓ KEEP_GOING=1: Execution completed despite injected failure TEST 168: Batch Transitive Hull: ___batch0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.18197/test-165] TEST 169: Sub-test: Walk command tree for '___batch0' (command: batch) [db: /tmp/vpn-switch-arch-test.18197/test-168] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 170: Sub-test: Inject failure at node '___batch0' (node 1/2) [db: /tmp/vpn-switch-arch-test.18197/test-168] ✓ KEEP_GOING affects output: fail-fast= 2 lines, continue= 2 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 171: Batch Transitive Hull: ___environment_inspect0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.18197/test-168] TEST 172: Sub-test: Walk command tree for '___environment_inspect0' (command: environment_inspect) [db: /tmp/vpn-switch-arch-test.18197/test-171] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 173: Sub-test: Inject failure at node '___environment_inspect0' (node 1/2) [db: /tmp/vpn-switch-arch-test.18197/test-171] ✓ KEEP_GOING affects output: fail-fast= 3 lines, continue= 3 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 174: Batch Transitive Hull: ___inspect0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.18197/test-171] TEST 175: Sub-test: Walk command tree for '___inspect0' (command: inspect) [db: /tmp/vpn-switch-arch-test.18197/test-174] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 176: Sub-test: Inject failure at node '___inspect0' (node 1/2) [db: /tmp/vpn-switch-arch-test.18197/test-174] ✓ KEEP_GOING affects output: fail-fast= 12 lines, continue= 12 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 177: Batch Transitive Hull: ___openvpn_create1 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.18197/test-174] TEST 178: Sub-test: Walk command tree for '___openvpn_create1' (command: openvpn_create) [db: /tmp/vpn-switch-arch-test.18197/test-177] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 8 injectable nodes (combinators/batches) in tree Skipped: Could not select target node for injection TEST 179: Batch Transitive Hull: ___openvpn_stop0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.18197/test-177] TEST 180: Sub-test: Walk command tree for '___openvpn_stop0' (command: openvpn_stop) [db: /tmp/vpn-switch-arch-test.18197/test-179] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 1 injectable nodes (combinators/batches) in tree TEST 181: Sub-test: Inject failure at node '___openvpn_stop0' (node 1/1) [db: /tmp/vpn-switch-arch-test.18197/test-179] ✓ KEEP_GOING affects output: fail-fast= 1 lines, continue= 1 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 182: Batch Transitive Hull: ___openvpn_inspect0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.18197/test-179] TEST 183: Sub-test: Walk command tree for '___openvpn_inspect0' (command: openvpn_inspect) [db: /tmp/vpn-switch-arch-test.18197/test-182] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 184: Sub-test: Inject failure at node '___openvpn_inspect0' (node 1/2) [db: /tmp/vpn-switch-arch-test.18197/test-182] ✓ KEEP_GOING affects output: fail-fast= 7 lines, continue= 7 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 185: Batch Transitive Hull: ___openvpn_clean0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.18197/test-182] TEST 186: Sub-test: Walk command tree for '___openvpn_clean0' (command: openvpn_clean) [db: /tmp/vpn-switch-arch-test.18197/test-185] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 3 injectable nodes (combinators/batches) in tree Skipped: Could not select target node for injection TEST 187: Batch Transitive Hull: ___openvpn_dump0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.18197/test-185] TEST 188: Sub-test: Walk command tree for '___openvpn_dump0' (command: openvpn_dump) [db: /tmp/vpn-switch-arch-test.18197/test-187] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 189: Sub-test: Inject failure at node '___openvpn_dump0' (node 1/2) [db: /tmp/vpn-switch-arch-test.18197/test-187] ✓ KEEP_GOING affects output: fail-fast= 20 lines, continue= 20 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 190: Batch Transitive Hull: ___session_dump0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.18197/test-187] TEST 191: Sub-test: Walk command tree for '___session_dump0' (command: session_dump) [db: /tmp/vpn-switch-arch-test.18197/test-190] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 192: Sub-test: Inject failure at node '___session_dump0' (node 1/2) [db: /tmp/vpn-switch-arch-test.18197/test-190] ✓ KEEP_GOING affects output: fail-fast= 41 lines, continue= 41 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 193: Batch Transitive Hull: ___session_inspect0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.18197/test-190] TEST 194: Sub-test: Walk command tree for '___session_inspect0' (command: session_inspect) [db: /tmp/vpn-switch-arch-test.18197/test-193] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 195: Sub-test: Inject failure at node '___session_inspect0' (node 1/2) [db: /tmp/vpn-switch-arch-test.18197/test-193] ✓ KEEP_GOING affects output: fail-fast= 5 lines, continue= 5 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 196: Batch Transitive Hull: ___validate0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.18197/test-193] TEST 197: Sub-test: Walk command tree for '___validate0' (command: validate) [db: /tmp/vpn-switch-arch-test.18197/test-196] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 198: Sub-test: Inject failure at node '___validate0' (node 1/2) [db: /tmp/vpn-switch-arch-test.18197/test-196] ✓ KEEP_GOING affects output: fail-fast= 10 lines, continue= 10 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 199: Batch Transitive Hull: ___wireguard_create1 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.18197/test-196] TEST 200: Sub-test: Walk command tree for '___wireguard_create1' (command: wireguard_create) [db: /tmp/vpn-switch-arch-test.18197/test-199] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 8 injectable nodes (combinators/batches) in tree Skipped: Could not select target node for injection TEST 201: Batch Transitive Hull: ___wireguard_inspect0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.18197/test-199] TEST 202: Sub-test: Walk command tree for '___wireguard_inspect0' (command: wireguard_inspect) [db: /tmp/vpn-switch-arch-test.18197/test-201] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 203: Sub-test: Inject failure at node '___wireguard_inspect0' (node 1/2) [db: /tmp/vpn-switch-arch-test.18197/test-201] ✓ KEEP_GOING affects output: fail-fast= 7 lines, continue= 7 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 204: Batch Transitive Hull: ___wireguard_stop0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.18197/test-201] TEST 205: Sub-test: Walk command tree for '___wireguard_stop0' (command: wireguard_stop) [db: /tmp/vpn-switch-arch-test.18197/test-204] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 1 injectable nodes (combinators/batches) in tree TEST 206: Sub-test: Inject failure at node '___wireguard_stop0' (node 1/1) [db: /tmp/vpn-switch-arch-test.18197/test-204] ✓ KEEP_GOING affects output: fail-fast= 1 lines, continue= 1 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 207: Batch Transitive Hull: ___wireguard_clean0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.18197/test-204] TEST 208: Sub-test: Walk command tree for '___wireguard_clean0' (command: wireguard_clean) [db: /tmp/vpn-switch-arch-test.18197/test-207] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 3 injectable nodes (combinators/batches) in tree Skipped: Could not select target node for injection TEST 209: Batch Transitive Hull: ___wireguard_clean1 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.18197/test-207] TEST 210: Sub-test: Walk command tree for '___wireguard_clean1' (command: wireguard_clean) [db: /tmp/vpn-switch-arch-test.18197/test-209] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 3 injectable nodes (combinators/batches) in tree Skipped: Could not select target node for injection TEST 211: Batch Transitive Hull: ___wireguard_dump0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.18197/test-209] TEST 212: Sub-test: Walk command tree for '___wireguard_dump0' (command: wireguard_dump) [db: /tmp/vpn-switch-arch-test.18197/test-211] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 213: Sub-test: Inject failure at node '___wireguard_dump0' (node 1/2) [db: /tmp/vpn-switch-arch-test.18197/test-211] ✓ KEEP_GOING affects output: fail-fast= 42 lines, continue= 42 lines Note: No clear error stop indicator in fail-fast mode ✓ KEEP_GOING=1: Execution completed despite injected failure Running Batch Combinator KEEP_GOING Precise Tests ======================================== Testing ALL batch combinators with precise architectural KEEP_GOING validation Found 26 batch combinator functions TEST 214: Batch KEEP_GOING Precise: ___session_prepare3 [db: /tmp/vpn-switch-arch-test.18197/test-211] ✓ Captured 143 command lines from ___session_prepare3 ✓ Selected 112 random line(s) for failure injection Skipped: No functions were injected with failures TEST 215: Batch KEEP_GOING Precise: ___stop0 [db: /tmp/vpn-switch-arch-test.18197/test-214] ✓ Captured 2 command lines from ___stop0 ✓ Selected 1 random line(s) for failure injection ✓ Injected failures into 1 function(s) ✓ KEEP_GOING=1: All commands attempted (2/2) Skipped: ___phases_sync1 (requires phase template setup) Skipped: ___phases_sync0 (requires phase template setup) TEST 216: Batch KEEP_GOING Precise: ___list0 [db: /tmp/vpn-switch-arch-test.18197/test-215] ✓ Captured 2 command lines from ___list0 ✓ Selected 1 random line(s) for failure injection ✓ Injected failures into 1 function(s) ✓ KEEP_GOING=1: All commands attempted (2/2) TEST 217: Batch KEEP_GOING Precise: ___bootstrap2 [db: /tmp/vpn-switch-arch-test.18197/test-216] ✓ Captured 73 command lines from ___bootstrap2 ✓ Selected 45 random line(s) for failure injection Skipped: No functions were injected with failures Skipped: ___init1 (complex initialization logic) TEST 218: Batch KEEP_GOING Precise: ___dumpenv1 [db: /tmp/vpn-switch-arch-test.18197/test-217] ✓ Captured 143 command lines from ___dumpenv1 ✓ Selected 139 random line(s) for failure injection Skipped: No functions were injected with failures TEST 219: Batch KEEP_GOING Precise: ___dump0 [db: /tmp/vpn-switch-arch-test.18197/test-218] ✓ Captured 5 command lines from ___dump0 ✓ Selected 3 random line(s) for failure injection ✓ Injected failures into 1 function(s) Note: Not all commands attempted (3/5) Note: This may indicate KEEP_GOING=0 or execution stopped early TEST 220: Batch KEEP_GOING Precise: ___batch0 [db: /tmp/vpn-switch-arch-test.18197/test-219] ✓ Captured 2 command lines from ___batch0 ✓ Selected 1 random line(s) for failure injection Skipped: No functions were injected with failures TEST 221: Batch KEEP_GOING Precise: ___environment_inspect0 [db: /tmp/vpn-switch-arch-test.18197/test-220] ✓ Captured 2 command lines from ___environment_inspect0 ✓ Selected 1 random line(s) for failure injection ✓ Injected failures into 1 function(s) ✓ KEEP_GOING=1: All commands attempted (2/2) TEST 222: Batch KEEP_GOING Precise: ___inspect0 [db: /tmp/vpn-switch-arch-test.18197/test-221] ✓ Captured 12 command lines from ___inspect0 ✓ Selected 5 random line(s) for failure injection ✓ Injected failures into 5 function(s) Note: Not all commands attempted (10/12) Note: This may indicate KEEP_GOING=0 or execution stopped early TEST 223: Batch KEEP_GOING Precise: ___openvpn_create1 [db: /tmp/vpn-switch-arch-test.18197/test-222] ✓ Captured 143 command lines from ___openvpn_create1 ✓ Selected 140 random line(s) for failure injection Skipped: No functions were injected with failures TEST 224: Batch KEEP_GOING Precise: ___openvpn_stop0 [db: /tmp/vpn-switch-arch-test.18197/test-223] ✓ Captured 1 command lines from ___openvpn_stop0 ✓ Selected 1 random line(s) for failure injection Skipped: No functions were injected with failures TEST 225: Batch KEEP_GOING Precise: ___openvpn_inspect0 [db: /tmp/vpn-switch-arch-test.18197/test-224] ✓ Captured 3 command lines from ___openvpn_inspect0 ✓ Selected 2 random line(s) for failure injection Skipped: No functions were injected with failures TEST 226: Batch KEEP_GOING Precise: ___openvpn_clean0 [db: /tmp/vpn-switch-arch-test.18197/test-225] ✓ Captured 3 command lines from ___openvpn_clean0 ✓ Selected 1 random line(s) for failure injection Skipped: No functions were injected with failures TEST 227: Batch KEEP_GOING Precise: ___openvpn_dump0 [db: /tmp/vpn-switch-arch-test.18197/test-226] ✓ Captured 13 command lines from ___openvpn_dump0 ✓ Selected 4 random line(s) for failure injection Skipped: No functions were injected with failures TEST 228: Batch KEEP_GOING Precise: ___session_dump0 [db: /tmp/vpn-switch-arch-test.18197/test-227] ✓ Captured 40 command lines from ___session_dump0 ✓ Selected 30 random line(s) for failure injection Skipped: No functions were injected with failures TEST 229: Batch KEEP_GOING Precise: ___session_inspect0 [db: /tmp/vpn-switch-arch-test.18197/test-228] ✓ Captured 4 command lines from ___session_inspect0 ✓ Selected 1 random line(s) for failure injection ✓ Injected failures into 1 function(s) Note: Not all commands attempted (3/4) Note: This may indicate KEEP_GOING=0 or execution stopped early TEST 230: Batch KEEP_GOING Precise: ___validate0 [db: /tmp/vpn-switch-arch-test.18197/test-229] ✓ Captured 10 command lines from ___validate0 ✓ Selected 2 random line(s) for failure injection ✓ Injected failures into 2 function(s) ✓ KEEP_GOING=1: All commands attempted (10/10) TEST 231: Batch KEEP_GOING Precise: ___wireguard_create1 [db: /tmp/vpn-switch-arch-test.18197/test-230] ✓ Captured 143 command lines from ___wireguard_create1 ✓ Selected 125 random line(s) for failure injection Skipped: No functions were injected with failures TEST 232: Batch KEEP_GOING Precise: ___wireguard_inspect0 [db: /tmp/vpn-switch-arch-test.18197/test-231] ✓ Captured 3 command lines from ___wireguard_inspect0 ✓ Selected 3 random line(s) for failure injection Skipped: No functions were injected with failures TEST 233: Batch KEEP_GOING Precise: ___wireguard_stop0 [db: /tmp/vpn-switch-arch-test.18197/test-232] ✓ Captured 1 command lines from ___wireguard_stop0 ✓ Selected 1 random line(s) for failure injection Skipped: No functions were injected with failures TEST 234: Batch KEEP_GOING Precise: ___wireguard_clean0 [db: /tmp/vpn-switch-arch-test.18197/test-233] ✓ Captured 9 command lines from ___wireguard_clean0 ✓ Selected 6 random line(s) for failure injection Skipped: No functions were injected with failures TEST 235: Batch KEEP_GOING Precise: ___wireguard_clean1 [db: /tmp/vpn-switch-arch-test.18197/test-234] ✓ Captured 9 command lines from ___wireguard_clean1 ✓ Selected 6 random line(s) for failure injection Skipped: No functions were injected with failures TEST 236: Batch KEEP_GOING Precise: ___wireguard_dump0 [db: /tmp/vpn-switch-arch-test.18197/test-235] ✓ Captured 34 command lines from ___wireguard_dump0 ✓ Selected 22 random line(s) for failure injection Skipped: No functions were injected with failures Running Static Analysis Tests ======================================== Testing architecture violation scanner TEST 237: Architecture Violation Scanner [db: /tmp/vpn-switch-arch-test.18197/test-236] ✓ Scanner executed successfully (exit code: 0) Found: \033[0;31m1\033[0m total violations ✓ Scanner detection working (violations found as expected) ✓ Scanner detects MODIFY_* variable usage Running Read-Only Database Tests ======================================== Testing that functions don't modify database at generation time TEST 238: Read-Only Database: All functions [db: /tmp/vpn-switch-arch-test.18197/test-236] Testing terminal functions... ✓ _session_create1: No permission errors on read-only database ✓ _interface_destroy1: No permission errors on read-only database ✓ _session_populate3: No permission errors on read-only database ✓ _link2: No permission errors on read-only database ✓ _remove1: No permission errors on read-only database ✓ _error1: No permission errors on read-only database ✓ _error2: No permission errors on read-only database ✓ _error3: No permission errors on read-only database ✓ _fail2: No permission errors on read-only database ✓ _log1: No permission errors on read-only database ✓ _log2: No permission errors on read-only database ✓ _log3: No permission errors on read-only database ✓ _lift1: No permission errors on read-only database ✓ _lift3: No permission errors on read-only database Warning: setenv2: output differs between writable/readonly (but compliant) ✓ _setenv2: No permission errors on read-only database ✓ _getenv1: No permission errors on read-only database ✓ _unsetenv1: No permission errors on read-only database ✓ _printenv0: No permission errors on read-only database Warning: status0: output differs between writable/readonly (but compliant) ✓ _status0: No permission errors on read-only database ✓ _help0: No permission errors on read-only database ✓ _help1: No permission errors on read-only database Warning: database_enumerate0: output differs between writable/readonly (but compliant) ✓ _database_enumerate0: No permission errors on read-only database ✓ _system_inspect0: No permission errors on read-only database Warning: logs_inspect0: output differs between writable/readonly (but compliant) ✓ _logs_inspect0: No permission errors on read-only database ✓ _phases_inspect0: No permission errors on read-only database ✓ _summary_inspect0: No permission errors on read-only database ✓ _prologue_inspect0: No permission errors on read-only database ✓ _openvpn_patch2: No permission errors on read-only database ✓ _openvpn_configure1: No permission errors on read-only database ✓ _openvpn_connect1: No permission errors on read-only database ✓ _openvpn_disconnect1: No permission errors on read-only database ✓ _openvpn_patch1: No permission errors on read-only database Warning: openvpn_enumerate0: output differs between writable/readonly (but compliant) ✓ _openvpn_enumerate0: No permission errors on read-only database ✓ _openvpn_import1: No permission errors on read-only database ✓ _openvpn_list0: No permission errors on read-only database ✓ _openvpn_list1: No permission errors on read-only database ✓ _openvpn_add1: No permission errors on read-only database ✓ _openvpn_add3: No permission errors on read-only database ✓ _openvpn_link2: No permission errors on read-only database ✓ _openvpn_remove1: No permission errors on read-only database ✓ _openvpn_remove2: No permission errors on read-only database ✓ _openvpn_validate0: No permission errors on read-only database ✓ _openvpn_info1: No permission errors on read-only database ✓ _session_list0: No permission errors on read-only database ✓ _session_show1: No permission errors on read-only database ✓ _session_remove1: No permission errors on read-only database ✓ _session_connect1: No permission errors on read-only database ✓ _session_save0: No permission errors on read-only database ✓ _session_save1: No permission errors on read-only database ✓ _session_clean0: No permission errors on read-only database ✓ _session_validate0: No permission errors on read-only database ✓ _session_enumerate0: No permission errors on read-only database ✓ _session_describe0: No permission errors on read-only database ✓ _logs_validate0: No permission errors on read-only database ✓ _logs_clean0: No permission errors on read-only database ✓ _phases_validate0: No permission errors on read-only database ✓ _database_validate0: No permission errors on read-only database ✓ _binaries_validate0: No permission errors on read-only database ✓ _network_validate0: No permission errors on read-only database ✓ _permissions_validate0: No permission errors on read-only database ✓ _environment_validate0: No permission errors on read-only database ✓ _wireguard_patch2: No permission errors on read-only database ✓ _wireguard_configure1: No permission errors on read-only database ✓ _wireguard_connect1: No permission errors on read-only database ✓ _wireguard_disconnect1: No permission errors on read-only database Warning: wireguard_enumerate0: output differs between writable/readonly (but compliant) ✓ _wireguard_enumerate0: No permission errors on read-only database ✓ _wireguard_import1: No permission errors on read-only database ✓ _wireguard_list0: No permission errors on read-only database ✓ _wireguard_list1: No permission errors on read-only database ✓ _wireguard_add1: No permission errors on read-only database ✓ _wireguard_add3: No permission errors on read-only database ✓ _wireguard_link2: No permission errors on read-only database ✓ _wireguard_remove1: No permission errors on read-only database ✓ _wireguard_remove2: No permission errors on read-only database ✓ _wireguard_validate0: No permission errors on read-only database ✓ _wireguard_patch1: No permission errors on read-only database ✓ _wireguard_info1: No permission errors on read-only database Testing combinator functions... ✓ __session_exists1: No permission errors on read-only database ✓ __session_conflicts2: No permission errors on read-only database ✓ __interface_check1: No permission errors on read-only database ✓ __stop1: No permission errors on read-only database ✓ __import1: No permission errors on read-only database ✓ __start1: No permission errors on read-only database ✓ __start0: No permission errors on read-only database ✓ __bootstrap1: No permission errors on read-only database ✓ __environment_cache0: No permission errors on read-only database ✓ __phases_lift1: No permission errors on read-only database ✓ __init0: No permission errors on read-only database ✓ __batch1: No permission errors on read-only database ✓ __restore1: No permission errors on read-only database Warning: openvpn_start0: output differs between writable/readonly (but compliant) ✓ __openvpn_start0: No permission errors on read-only database ✓ __openvpn_start1: No permission errors on read-only database ✓ __openvpn_stop1: No permission errors on read-only database ✓ __openvpn_add2: No permission errors on read-only database ✓ __openvpn_help0: No permission errors on read-only database ✓ __session_disconnect1: No permission errors on read-only database ✓ __session_show0: No permission errors on read-only database ✓ __session_start0: No permission errors on read-only database ✓ __session_start1: No permission errors on read-only database ✓ __session_help0: No permission errors on read-only database Warning: wireguard_start0: output differs between writable/readonly (but compliant) ✓ __wireguard_start0: No permission errors on read-only database ✓ __wireguard_start1: No permission errors on read-only database ✓ __wireguard_stop1: No permission errors on read-only database ✓ __wireguard_add2: No permission errors on read-only database ✓ __wireguard_help0: No permission errors on read-only database Testing batch combinator functions... ✓ ___session_prepare3: No permission errors on read-only database ✓ ___stop0: No permission errors on read-only database ✓ ___phases_sync1: No permission errors on read-only database ✓ ___phases_sync0: No permission errors on read-only database ✓ ___list0: No permission errors on read-only database ✓ ___dumpenv1: No permission errors on read-only database ✓ ___dump0: No permission errors on read-only database Warning: batch0: output differs between writable/readonly (but compliant) ✓ ___batch0: No permission errors on read-only database ✓ ___environment_inspect0: No permission errors on read-only database ✓ ___inspect0: No permission errors on read-only database Warning: openvpn_create1: output differs between writable/readonly (but compliant) ✓ ___openvpn_create1: No permission errors on read-only database ✓ ___openvpn_stop0: No permission errors on read-only database ✓ ___openvpn_inspect0: No permission errors on read-only database ✓ ___openvpn_clean0: No permission errors on read-only database ✓ ___openvpn_dump0: No permission errors on read-only database ✓ ___session_dump0: No permission errors on read-only database ✓ ___session_inspect0: No permission errors on read-only database ✓ ___validate0: No permission errors on read-only database Warning: wireguard_create1: output differs between writable/readonly (but compliant) ✓ ___wireguard_create1: No permission errors on read-only database ✓ ___wireguard_inspect0: No permission errors on read-only database ✓ ___wireguard_stop0: No permission errors on read-only database ✓ ___wireguard_clean0: No permission errors on read-only database ✓ ___wireguard_clean1: No permission errors on read-only database ✓ ___wireguard_dump0: No permission errors on read-only database Summary: Tested 129 functions, skipped 8 ======================================== Architecture Test Summary ======================================== Test Functions: 238 Total Assertions: 412 Passed Assertions: 412 Failed Assertions: 0 ALL TESTS PASSED Cleaning up test databases... Done. === vpn-switch Integration Tests === Profile: all ▶ User Story 1: Import → Organize → Dump → Restore → Idempotency (Multi-Protocol) Database: /tmp/vpn-integration-old.ahtbZ2 ✓ WG: Imported config 1 ✓ WG: Imported config 2 ✓ WG: Imported config 3 ✓ OVPN: Imported config 1 ✓ OVPN: Imported config 2 ✓ WG: Created category: privacy ✓ WG: Created category: streaming ✓ OVPN: Created group: work ✓ WG: Protocol-level link: quick ✓ WG: Category link: privacy/fast ✓ WG: Category link: privacy/secure ✓ WG: Category link: streaming/hd ✓ OVPN: Protocol-level link: office ✓ OVPN: Group link: work/primary ✓ Dump stderr is clean # ================================ # db: /tmp/vpn-integration-old.ahtbZ2 # ================================ ✓ Dump file created ✓ Dump contains WG import ✓ Dump contains OVPN import ✓ Dump contains WG category ✓ Dump contains OVPN group ✓ Dump contains WG link ✓ Dump contains OVPN link Database: /tmp/vpn-integration-new.KkjL9r ✓ NEW WG: Config 1 imported ✓ NEW WG: Config 2 imported ✓ NEW WG: Config 3 imported ✓ NEW WG: Category privacy created ✓ NEW WG: Category streaming created ✓ NEW WG: Protocol-level link ✓ NEW WG: Category link privacy/fast ✓ NEW WG: Category link privacy/secure ✓ NEW WG: Category link streaming/hd ✓ NEW OVPN: Config 1 imported ✓ NEW OVPN: Config 2 imported ✓ NEW OVPN: Group work created ✓ NEW OVPN: Protocol-level link ✓ NEW OVPN: Group link work/primary ✓ Idempotency dump stderr is clean ✓ Idempotency: dump(restore(dump(OLD))) == dump(OLD) [multi-protocol] ✓ Story 1 completed successfully ▶ User Story 2: Session Management: Save → Dump → Restore → Verify (Multi-Protocol) Database: /tmp/vpn-integration-old.0xPnuc ✓ WG: Named session created: work -> ../.session/15671 ✓ OVPN: Named session created: home -> ../.session/47619 ✓ Dump stderr is clean ✓ Dump contains WG session patch ✓ Dump contains OVPN session patch ✓ Dump contains WG save command ✓ Dump contains OVPN save command Database: /tmp/vpn-integration-new.ZzeT48 ✓ NEW: WG config imported ✓ NEW: OVPN config imported ✓ NEW: WG session dump contains patch + save commands ✓ NEW: OVPN session dump contains patch + save commands ✓ Story 2 completed successfully ▶ User Story 3: Config Expiry: Import → Organize → Check Status Database: /tmp/vpn-integration-test.h1cUj6 ✓ Info output contains fresh config ✓ Info output contains old config ✓ Validate command found no issues (acceptable) ✓ Story 3 completed successfully ▶ User Story 4: Multi-Category Organization: Complex Structure (Multi-Protocol) Database: /tmp/vpn-integration-test.y57Eps ✓ WG: Category: usa ✓ WG: Category: europe ✓ WG: Category: asia ✓ WG: Category: work ✓ WG: Category: personal ✓ OVPN: Group: corporate ✓ OVPN: Group: remote ✓ WG: usa/ny → wg-us-ny.conf ✓ WG: europe/uk → wg-eu-uk.conf ✓ WG: asia/jp → wg-asia-jp.conf ✓ WG: work/office → wg-us-ny.conf ✓ WG: personal/home → wg-us-sf.conf ✓ OVPN: corporate/us → us-office.ovpn ✓ OVPN: corporate/eu → eu-office.ovpn ✓ OVPN: remote/home → home-server.ovpn ✓ WG: default → wg-us-ny.conf ✓ WG: fast → wg-us-sf.conf ✓ OVPN: quick → us-office.ovpn ✓ WG: List shows usa category ✓ WG: List shows europe category ✓ WG: List shows work category ✓ OVPN: List shows corporate group ✓ OVPN: List shows remote group ✓ Story 4 completed successfully ▶ User Story 5: Completeness & Deletion Proof: Comprehensive State Tracking (Multi-Protocol) Database: /tmp/vpn-integration-test.wGKKcC ✓ Dump stderr is clean ✓ Completeness: All 26 operations present in dump (WG: 15, OVPN: 11) ✓ Deletion phase 1 dump stderr is clean ✓ Deletion: WG protocol link 'quick' removed from dump ✓ Deletion: OVPN protocol link 'office' removed from dump ✓ Deletion: WG protocol link 'default' still present ✓ Deletion: WG category 'privacy' still present ✓ Deletion: WG category 'work' still present ✓ Deletion: OVPN group 'corporate' still present ✓ Deletion phase 2 dump stderr is clean ✓ Deletion: WG category link 'privacy/fast' removed from dump ✓ Deletion: WG category link 'work/office' removed from dump ✓ Deletion: OVPN group link 'corporate/primary' removed from dump ✓ Deletion: WG category link 'privacy/secure' still present ✓ Deletion: WG category link 'streaming/hd' still present ✓ Deletion: OVPN group link 'corporate/secondary' still present ✓ Deletion: WG config wg-us-101.conf still present ✓ Deletion: WG config wg-de-303.conf still present ✓ Deletion: OVPN config us-server.ovpn still present ✓ Deletion phase 3 dump stderr is clean ✓ Deletion: WG config wg-jp-404.conf removed from dump ✓ Deletion: WG config wg-au-505.conf removed from dump ✓ Deletion: OVPN config asia-server.ovpn removed from dump ✓ Deletion: WG config wg-us-101.conf still present after removals ✓ Deletion: WG config wg-uk-202.conf still present after removals ✓ Deletion: WG config wg-de-303.conf still present after removals ✓ Deletion: OVPN config us-server.ovpn still present after removals ✓ Deletion: OVPN config eu-server.ovpn still present after removals ✓ Deletion: Empty WG category 'privacy' still present ✓ Deletion: Empty WG category 'work' still present ✓ Deletion: Empty WG category 'streaming' still present ✓ Deletion: OVPN group 'corporate' still present (has link) ✓ Deletion: Empty OVPN group 'remote' still present ✓ Story 5 completed successfully ▶ User Story 6: Dump Quality: Cleanliness, Pipeability, Executability, Transcript Reproducibility Database: /tmp/vpn-quality-test.bDuluq ✓ Property 1: Dump stderr is completely empty ✓ Property 2: Dump output is syntactically valid shell script ✓ Property 3: Direct pipe works (exit code 0) ✓ Property 3: Direct pipe produces identical output ✓ Property 4: All informational output is properly commented ✓ Property 5: All transcript commands present in dump (reproducibility) Database: /tmp/vpn-quality-restore.jHtK1Z ✓ Property 6: Dump is restorable (executable) ✓ Property 6: WG config restored ✓ Property 6: OVPN config restored ✓ Property 6: WG category restored ✓ Property 6: OVPN group restored ✓ Property 6: WG link restored ✓ Property 6: OVPN link restored ✓ Property 7: Normalized idempotency verified (dump(restore(dump)) == dump) ✓ Property 8: No duplicate protocol commands in dump (6 unique) ✓ Story 6 completed successfully ▶ User Story 7: Phase-Based Script Generation (WireGuard and OpenVPN) Database: /tmp/vpn-phase-gen.GmzJ8U ✓ WG: Extract session ID from start output ✓ WG: connect.sh exists ✓ WG: disconnect.sh exists ✓ WG: connect.sh has correct permissions (0750) ✓ WG: disconnect.sh has correct permissions (0750) ✓ WG: connect.sh is executable ✓ WG: disconnect.sh is executable ✓ WG: connect.sh has shebang ✓ WG: disconnect.sh has shebang ✓ OVPN: Extract session ID from start output ✓ OVPN: connect.sh exists ✓ OVPN: disconnect.sh exists ✓ OVPN: connect.sh has correct permissions (0750) ✓ OVPN: disconnect.sh has correct permissions (0750) ✓ OVPN: connect.sh is executable ✓ OVPN: disconnect.sh is executable ✓ OVPN: connect.sh has shebang ✓ OVPN: disconnect.sh has shebang ✓ WG: Session metadata exists (protocol) ✓ WG: Session metadata exists (interface) ✓ OVPN: Session metadata exists (protocol) ✓ OVPN: Session metadata exists (interface) ✓ WG and OVPN sessions are independent (different PIDs) ✓ Story 7 completed successfully ▶ User Story 8: Phase Script Content Verification (Structure and Commands) Database: /tmp/vpn-phase-content.vJCsJu ✓ WG connect: Has title ✓ WG connect: Has generation timestamp ✓ WG connect: Has session ID ✓ WG connect: Has context documentation ✓ WG connect: Has session_dir variable ✓ WG connect: Has protocol variable ✓ WG connect: Has interface variable ✓ WG connect: Has config_path variable ✓ WG connect: Has dns_server variable ✓ WG connect: Has remote_ips variable ✓ WG connect: Has firewall verify function ✓ WG connect: Has vpn verify function ✓ WG connect: Has dns verify function ✓ WG connect: Firewall prepare phase ✓ WG connect: Firewall execute phase ✓ WG connect: VPN prepare phase ✓ WG connect: VPN execute phase ✓ WG connect: DNS prepare phase ✓ WG connect: DNS execute phase ✓ WG connect: Has wg-quick up command ✓ WG connect: Correct phase order ✓ WG disconnect: Has title ✓ WG disconnect: Has session_dir variable ✓ WG disconnect: Has dns verify function ✓ WG disconnect: Has vpn verify function ✓ WG disconnect: Has firewall verify function ✓ WG disconnect: Has wg-quick down command ✓ WG disconnect: Correct reversed phase order ✓ OVPN connect: Has title ✓ OVPN connect: Has generation timestamp ✓ OVPN connect: Has session_dir variable ✓ OVPN connect: Has protocol variable ✓ OVPN connect: Has interface variable ✓ OVPN connect: Has config_path variable ✓ OVPN connect: Has firewall verify function ✓ OVPN connect: Has vpn verify function ✓ OVPN connect: Has dns verify function ✓ OVPN connect: Has openvpn command ✓ OVPN connect: Has daemon flag ✓ OVPN connect: Correct phase order ✓ OVPN disconnect: Has title ✓ OVPN disconnect: Has session_dir variable ✓ OVPN disconnect: Has process kill command ✓ OVPN disconnect: Correct reversed phase order ✓ WG connect: No OpenVPN commands ✓ WG connect: No OpenVPN daemon flag ✓ OVPN connect: No WireGuard commands ✓ Story 8 completed successfully ▶ User Story 9: Phase Customization (Reorder, Add, Skip) Database: /tmp/vpn-phase-custom.b4Z842 ✓ Baseline: Default phase order ✓ Reordered: Custom phase order ✓ Custom phase: Has verify function ✓ Custom phase: Has prepare section ✓ Custom phase: Has execute section ✓ Custom phase: Correct order with routing ✓ Minimal: Has vpn verify function ✓ Minimal: No firewall phase ✓ Minimal: No dns phase ✓ Minimal: Only VPN phase ✓ Custom disconnect: Has dns phase ✓ Custom disconnect: Has vpn phase ✓ Custom disconnect: No firewall phase ✓ Custom disconnect: Only dns and vpn ✓ Multi-custom: Has logging phase ✓ Multi-custom: Has monitoring phase ✓ Multi-custom: Correct custom order ✓ Story 9 completed successfully ▶ User Story 10: Multi-Protocol Phase Support (Isolation and Simultaneous Operation) Database: /tmp/vpn-phase-multi.bM8ARj ✓ WG: Default phase order ✓ OVPN: Default phase order ✓ WG: Has WireGuard command ✓ WG: No OpenVPN commands ✓ OVPN: Has OpenVPN command ✓ OVPN: No WireGuard commands ✓ WG: Correct protocol variable ✓ WG: WireGuard interface naming ✓ WG: Has dns_server context ✓ WG: Has remote_ips context ✓ OVPN: Correct protocol variable ✓ OVPN: OpenVPN interface naming ✓ WG custom: Has custom phase ✓ WG custom: Has custom phase in order ✓ OVPN: No WireGuard custom phase ✓ OVPN: Default phases only ✓ WG: No OpenVPN custom phase ✓ WG: Default phases only ✓ OVPN: Protocol-specific phase config not yet supported ✓ OVPN: Uses default phases (protocol-specific config not implemented) ✓ Simultaneous: WG session exists ✓ Simultaneous: OVPN session exists ✓ Simultaneous: Different session IDs ✓ Simultaneous: WG has correct protocol ✓ Simultaneous: OVPN has correct protocol ✓ Story 10 completed successfully ▶ User Story 11: Multi-Protocol Edge Cases (Stress, Switching, Robustness) Database: /tmp/vpn-edge-cases.CmjeiZ ✓ Scenario 1.1: Duplicate WG import correctly rejected ✓ Scenario 1.1: Duplicate OVPN import correctly rejected ✓ Scenario 1.1: WG includes wg_custom phase ✓ Scenario 1.1: WG excludes ovpn_custom phase ✓ Scenario 1.1: OVPN includes ovpn_custom phase ✓ Scenario 1.1: OVPN excludes wg_custom phase ✓ Scenario 1.1: Phase order differs between protocols ✓ Scenario 1.2: WireGuard test interface configured ✓ Scenario 1.2: OpenVPN test interface configured ✓ Scenario 1.2: Two sessions active simultaneously ✓ Scenario 1.2: WG session uses wg_test* interface ✓ Scenario 1.2: OVPN session uses tun_test* interface ✓ Scenario 1.2: Unreferenced sessions cleaned, 'latest' preserved ✓ Scenario 1.3: WG session has DNS config ✓ Scenario 1.3: Connect scripts differ despite same DNS ✓ Scenario 2.1: WG session created ✓ Scenario 2.1: WG session stopped, 'latest' preserved ✓ Scenario 2.1: OVPN session created after WG stop ✓ Scenario 2.1: New session is OpenVPN protocol ✓ Scenario 2.2: Both sessions coexist ✓ Scenario 2.2: Both protocols running simultaneously ✓ Scenario 2.3: Cycle 1 - WG started ✓ Scenario 2.3: Cycle 1 - WG stopped, 'latest' preserved ✓ Scenario 2.3: Cycle 2 - OVPN started (old session + new) ✓ Scenario 2.3: Cycle 2 - OVPN stopped, unreferenced cleaned ✓ Scenario 2.3: Cycle 3 - WG started (old session + new) ✓ Scenario 2.3: Both sessions present (unreferenced + latest) ✓ Scenario 3.1: WG session saved as wg_work ✓ Scenario 3.1: Both sessions active after resume ✓ Scenario 3.1: Correct protocols after resume ✓ Scenario 3.2: Session 'work' points to WG session ✓ Scenario 3.2: Session 'work' now points to OVPN (overwrite) ✓ Scenario 3.2: Only one 'work' session exists (no duplicates) ✓ Scenario 4.1: Two active sessions before dump ✓ Scenario 4.1: Dump file created with active sessions ✓ Scenario 4.1: Dump excludes .session directory (transient) ✓ Scenario 4.1: Dump includes WG configs ✓ Scenario 4.1: Dump includes OVPN configs Database: /tmp/vpn-restore-a.tEN2Xn Database: /tmp/vpn-restore-b.dylO8z ✓ Scenario 4.2: Restored database has WG config ✓ Scenario 4.2: Restored database has no active sessions ✓ Scenario 5.1: Only 'latest' WG session after 10 cycles ✓ Scenario 5.1: Only 'latest' OVPN session after 10 cycles ✓ Scenario 5.1: Only latest session directory remains ✓ Story 11 completed successfully ▶ User Story 12: Phase Backend Selection (Strategy 7 - Automatic Template Lifting) Database: /tmp/vpn-backend-selection.ZMgQgp ✓ Backend template lifted: firewall/pf.sh ✓ Backend template lifted: firewall/ipfw.sh ✓ Backend template lifted: dns/resolvconf.sh ✓ Backend template lifted: dns/unbound.sh ✓ Scenario 1: Connect script generated ✓ Scenario 1: PF firewall backend used (contains pfctl) ✓ Scenario 1: Resolvconf DNS backend used ✓ Scenario 2: IPFW firewall backend used (contains ipfw) ✓ Scenario 2: Unbound DNS backend used ✓ Scenario 2: PF firewall phase not used (backend isolated) ✓ Scenario 3: Backward compat - connect script generated ✓ Scenario 3: Backward compat - script not empty ✓ Scenario 3: Uses protocol-specific phases (wireguard/) ✓ Scenario 4: Both backends from @base profile used ✓ Scenario 5: Variant-only syntax works (uses default profile) ✓ Scenario 6: Mixed syntax - ipfw backend used ✓ Scenario 6: Mixed syntax - vpn phase executed ✓ Scenario 6: Mixed syntax - traditional dns phase used ✓ Story 12 completed successfully ======================================== Test Summary ======================================== User Stories: 12 Passed: 12 Failed: 0 Assertions: 296 Passed: 296 Failed: 0 ALL STORIES PASSED === vpn-switch Integration Tests === Profile: minimal ▶ User Story 1: Import → Organize → Dump → Restore → Idempotency (Multi-Protocol) Database: /tmp/vpn-integration-old.cbW8p1 ✓ WG: Imported config 1 ✓ WG: Imported config 2 ✓ WG: Imported config 3 ✓ OVPN: Imported config 1 ✓ OVPN: Imported config 2 ✓ WG: Created category: privacy ✓ WG: Created category: streaming ✓ OVPN: Created group: work ✓ WG: Protocol-level link: quick ✓ WG: Category link: privacy/fast ✓ WG: Category link: privacy/secure ✓ WG: Category link: streaming/hd ✓ OVPN: Protocol-level link: office ✓ OVPN: Group link: work/primary ✓ Dump stderr is clean # ================================ # db: /tmp/vpn-integration-old.cbW8p1 # ================================ ✓ Dump file created ✓ Dump contains WG import ✓ Dump contains OVPN import ✓ Dump contains WG category ✓ Dump contains OVPN group ✓ Dump contains WG link ✓ Dump contains OVPN link Database: /tmp/vpn-integration-new.O0PzTg ✓ NEW WG: Config 1 imported ✓ NEW WG: Config 2 imported ✓ NEW WG: Config 3 imported ✓ NEW WG: Category privacy created ✓ NEW WG: Category streaming created ✓ NEW WG: Protocol-level link ✓ NEW WG: Category link privacy/fast ✓ NEW WG: Category link privacy/secure ✓ NEW WG: Category link streaming/hd ✓ NEW OVPN: Config 1 imported ✓ NEW OVPN: Config 2 imported ✓ NEW OVPN: Group work created ✓ NEW OVPN: Protocol-level link ✓ NEW OVPN: Group link work/primary ✓ Idempotency dump stderr is clean ✓ Idempotency: dump(restore(dump(OLD))) == dump(OLD) [multi-protocol] ✓ Story 1 completed successfully ▶ User Story 2: Session Management: Save → Dump → Restore → Verify (Multi-Protocol) Database: /tmp/vpn-integration-old.cBtc1V ✓ WG: Named session created: work -> ../.session/9607 ✓ OVPN: Named session created: home -> ../.session/24852 ✓ Dump stderr is clean ✓ Dump contains WG session patch ✓ Dump contains OVPN session patch ✓ Dump contains WG save command ✓ Dump contains OVPN save command Database: /tmp/vpn-integration-new.eYaBz3 ✓ NEW: WG config imported ✓ NEW: OVPN config imported ✓ NEW: WG session dump contains patch + save commands ✓ NEW: OVPN session dump contains patch + save commands ✓ Story 2 completed successfully ▶ User Story 3: Config Expiry: Import → Organize → Check Status Database: /tmp/vpn-integration-test.bfqw9c ✓ Info output contains fresh config ✓ Info output contains old config ✓ Validate command found no issues (acceptable) ✓ Story 3 completed successfully ▶ User Story 4: Multi-Category Organization: Complex Structure (Multi-Protocol) Database: /tmp/vpn-integration-test.fT3u1i ✓ WG: Category: usa ✓ WG: Category: europe ✓ WG: Category: asia ✓ WG: Category: work ✓ WG: Category: personal ✓ OVPN: Group: corporate ✓ OVPN: Group: remote ✓ WG: usa/ny → wg-us-ny.conf ✓ WG: europe/uk → wg-eu-uk.conf ✓ WG: asia/jp → wg-asia-jp.conf ✓ WG: work/office → wg-us-ny.conf ✓ WG: personal/home → wg-us-sf.conf ✓ OVPN: corporate/us → us-office.ovpn ✓ OVPN: corporate/eu → eu-office.ovpn ✓ OVPN: remote/home → home-server.ovpn ✓ WG: default → wg-us-ny.conf ✓ WG: fast → wg-us-sf.conf ✓ OVPN: quick → us-office.ovpn ✓ WG: List shows usa category ✓ WG: List shows europe category ✓ WG: List shows work category ✓ OVPN: List shows corporate group ✓ OVPN: List shows remote group ✓ Story 4 completed successfully ▶ User Story 5: Completeness & Deletion Proof: Comprehensive State Tracking (Multi-Protocol) Database: /tmp/vpn-integration-test.ycvIt0 ✓ Dump stderr is clean ✓ Completeness: All 26 operations present in dump (WG: 15, OVPN: 11) ✓ Deletion phase 1 dump stderr is clean ✓ Deletion: WG protocol link 'quick' removed from dump ✓ Deletion: OVPN protocol link 'office' removed from dump ✓ Deletion: WG protocol link 'default' still present ✓ Deletion: WG category 'privacy' still present ✓ Deletion: WG category 'work' still present ✓ Deletion: OVPN group 'corporate' still present ✓ Deletion phase 2 dump stderr is clean ✓ Deletion: WG category link 'privacy/fast' removed from dump ✓ Deletion: WG category link 'work/office' removed from dump ✓ Deletion: OVPN group link 'corporate/primary' removed from dump ✓ Deletion: WG category link 'privacy/secure' still present ✓ Deletion: WG category link 'streaming/hd' still present ✓ Deletion: OVPN group link 'corporate/secondary' still present ✓ Deletion: WG config wg-us-101.conf still present ✓ Deletion: WG config wg-de-303.conf still present ✓ Deletion: OVPN config us-server.ovpn still present ✓ Deletion phase 3 dump stderr is clean ✓ Deletion: WG config wg-jp-404.conf removed from dump ✓ Deletion: WG config wg-au-505.conf removed from dump ✓ Deletion: OVPN config asia-server.ovpn removed from dump ✓ Deletion: WG config wg-us-101.conf still present after removals ✓ Deletion: WG config wg-uk-202.conf still present after removals ✓ Deletion: WG config wg-de-303.conf still present after removals ✓ Deletion: OVPN config us-server.ovpn still present after removals ✓ Deletion: OVPN config eu-server.ovpn still present after removals ✓ Deletion: Empty WG category 'privacy' still present ✓ Deletion: Empty WG category 'work' still present ✓ Deletion: Empty WG category 'streaming' still present ✓ Deletion: OVPN group 'corporate' still present (has link) ✓ Deletion: Empty OVPN group 'remote' still present ✓ Story 5 completed successfully ▶ User Story 6: Dump Quality: Cleanliness, Pipeability, Executability, Transcript Reproducibility Database: /tmp/vpn-quality-test.byNNK6 ✓ Property 1: Dump stderr is completely empty ✓ Property 2: Dump output is syntactically valid shell script ✓ Property 3: Direct pipe works (exit code 0) ✓ Property 3: Direct pipe produces identical output ✓ Property 4: All informational output is properly commented ✓ Property 5: All transcript commands present in dump (reproducibility) Database: /tmp/vpn-quality-restore.yvzHDW ✓ Property 6: Dump is restorable (executable) ✓ Property 6: WG config restored ✓ Property 6: OVPN config restored ✓ Property 6: WG category restored ✓ Property 6: OVPN group restored ✓ Property 6: WG link restored ✓ Property 6: OVPN link restored ✓ Property 7: Normalized idempotency verified (dump(restore(dump)) == dump) ✓ Property 8: No duplicate protocol commands in dump (6 unique) ✓ Story 6 completed successfully ▶ User Story 7: Phase-Based Script Generation (WireGuard and OpenVPN) Database: /tmp/vpn-phase-gen.M7IRB6 ✓ WG: Extract session ID from start output ✓ WG: connect.sh exists ✓ WG: disconnect.sh exists ✓ WG: connect.sh has correct permissions (0750) ✓ WG: disconnect.sh has correct permissions (0750) ✓ WG: connect.sh is executable ✓ WG: disconnect.sh is executable ✓ WG: connect.sh has shebang ✓ WG: disconnect.sh has shebang ✓ OVPN: Extract session ID from start output ✓ OVPN: connect.sh exists ✓ OVPN: disconnect.sh exists ✓ OVPN: connect.sh has correct permissions (0750) ✓ OVPN: disconnect.sh has correct permissions (0750) ✓ OVPN: connect.sh is executable ✓ OVPN: disconnect.sh is executable ✓ OVPN: connect.sh has shebang ✓ OVPN: disconnect.sh has shebang ✓ WG: Session metadata exists (protocol) ✓ WG: Session metadata exists (interface) ✓ OVPN: Session metadata exists (protocol) ✓ OVPN: Session metadata exists (interface) ✓ WG and OVPN sessions are independent (different PIDs) ✓ Story 7 completed successfully ▶ User Story 8: Phase Script Content Verification (Structure and Commands) Database: /tmp/vpn-phase-content.DzfpTE ✓ WG connect: Has title ✓ WG connect: Has generation timestamp ✓ WG connect: Has session ID ✓ WG connect: Has context documentation ✓ WG connect: Has session_dir variable ✓ WG connect: Has protocol variable ✓ WG connect: Has interface variable ✓ WG connect: Has config_path variable ✓ WG connect: Has dns_server variable ✓ WG connect: Has remote_ips variable ✓ WG connect: Has firewall verify function ✓ WG connect: Has vpn verify function ✓ WG connect: Has dns verify function ✓ WG connect: Firewall prepare phase ✓ WG connect: Firewall execute phase ✓ WG connect: VPN prepare phase ✓ WG connect: VPN execute phase ✓ WG connect: DNS prepare phase ✓ WG connect: DNS execute phase ✓ WG connect: Has wg-quick up command ✓ WG connect: Correct phase order ✓ WG disconnect: Has title ✓ WG disconnect: Has session_dir variable ✓ WG disconnect: Has dns verify function ✓ WG disconnect: Has vpn verify function ✓ WG disconnect: Has firewall verify function ✓ WG disconnect: Has wg-quick down command ✓ WG disconnect: Correct reversed phase order ✓ OVPN connect: Has title ✓ OVPN connect: Has generation timestamp ✓ OVPN connect: Has session_dir variable ✓ OVPN connect: Has protocol variable ✓ OVPN connect: Has interface variable ✓ OVPN connect: Has config_path variable ✓ OVPN connect: Has firewall verify function ✓ OVPN connect: Has vpn verify function ✓ OVPN connect: Has dns verify function ✓ OVPN connect: Has openvpn command ✓ OVPN connect: Has daemon flag ✓ OVPN connect: Correct phase order ✓ OVPN disconnect: Has title ✓ OVPN disconnect: Has session_dir variable ✓ OVPN disconnect: Has process kill command ✓ OVPN disconnect: Correct reversed phase order ✓ WG connect: No OpenVPN commands ✓ WG connect: No OpenVPN daemon flag ✓ OVPN connect: No WireGuard commands ✓ Story 8 completed successfully ▶ User Story 9: Phase Customization (Reorder, Add, Skip) Database: /tmp/vpn-phase-custom.U8XhYA ✓ Baseline: Default phase order ✓ Reordered: Custom phase order ✓ Custom phase: Has verify function ✓ Custom phase: Has prepare section ✓ Custom phase: Has execute section ✓ Custom phase: Correct order with routing ✓ Minimal: Has vpn verify function ✓ Minimal: No firewall phase ✓ Minimal: No dns phase ✓ Minimal: Only VPN phase ✓ Custom disconnect: Has dns phase ✓ Custom disconnect: Has vpn phase ✓ Custom disconnect: No firewall phase ✓ Custom disconnect: Only dns and vpn ✓ Multi-custom: Has logging phase ✓ Multi-custom: Has monitoring phase ✓ Multi-custom: Correct custom order ✓ Story 9 completed successfully ▶ User Story 10: Multi-Protocol Phase Support (Isolation and Simultaneous Operation) Database: /tmp/vpn-phase-multi.RkI3Mk ✓ WG: Default phase order ✓ OVPN: Default phase order ✓ WG: Has WireGuard command ✓ WG: No OpenVPN commands ✓ OVPN: Has OpenVPN command ✓ OVPN: No WireGuard commands ✓ WG: Correct protocol variable ✓ WG: WireGuard interface naming ✓ WG: Has dns_server context ✓ WG: Has remote_ips context ✓ OVPN: Correct protocol variable ✓ OVPN: OpenVPN interface naming ✓ WG custom: Has custom phase ✓ WG custom: Has custom phase in order ✓ OVPN: No WireGuard custom phase ✓ OVPN: Default phases only ✓ WG: No OpenVPN custom phase ✓ WG: Default phases only ✓ OVPN: Protocol-specific phase config not yet supported ✓ OVPN: Uses default phases (protocol-specific config not implemented) ✓ Simultaneous: WG session exists ✓ Simultaneous: OVPN session exists ✓ Simultaneous: Different session IDs ✓ Simultaneous: WG has correct protocol ✓ Simultaneous: OVPN has correct protocol ✓ Story 10 completed successfully ▶ User Story 11: Multi-Protocol Edge Cases (Stress, Switching, Robustness) Database: /tmp/vpn-edge-cases.Bp7waY ✓ Scenario 1.1: Duplicate WG import correctly rejected ✓ Scenario 1.1: Duplicate OVPN import correctly rejected ✓ Scenario 1.1: WG includes wg_custom phase ✓ Scenario 1.1: WG excludes ovpn_custom phase ✓ Scenario 1.1: OVPN includes ovpn_custom phase ✓ Scenario 1.1: OVPN excludes wg_custom phase ✓ Scenario 1.1: Phase order differs between protocols ✓ Scenario 1.2: WireGuard test interface configured ✓ Scenario 1.2: OpenVPN test interface configured ✓ Scenario 1.2: Two sessions active simultaneously ✓ Scenario 1.2: WG session uses wg_test* interface ✓ Scenario 1.2: OVPN session uses tun_test* interface ✓ Scenario 1.2: Unreferenced sessions cleaned, 'latest' preserved ✓ Scenario 1.3: WG session has DNS config ✓ Scenario 1.3: Connect scripts differ despite same DNS ✓ Scenario 2.1: WG session created ✓ Scenario 2.1: WG session stopped, 'latest' preserved ✓ Scenario 2.1: OVPN session created after WG stop ✓ Scenario 2.1: New session is OpenVPN protocol ✓ Scenario 2.2: Both sessions coexist ✓ Scenario 2.2: Both protocols running simultaneously ✓ Scenario 2.3: Cycle 1 - WG started ✓ Scenario 2.3: Cycle 1 - WG stopped, 'latest' preserved ✓ Scenario 2.3: Cycle 2 - OVPN started (old session + new) ✓ Scenario 2.3: Cycle 2 - OVPN stopped, unreferenced cleaned ✓ Scenario 2.3: Cycle 3 - WG started (old session + new) ✓ Scenario 2.3: Both sessions present (unreferenced + latest) ✓ Scenario 3.1: WG session saved as wg_work ✓ Scenario 3.1: Both sessions active after resume ✓ Scenario 3.1: Correct protocols after resume ✓ Scenario 3.2: Session 'work' points to WG session ✓ Scenario 3.2: Session 'work' now points to OVPN (overwrite) ✓ Scenario 3.2: Only one 'work' session exists (no duplicates) ✓ Scenario 4.1: Two active sessions before dump ✓ Scenario 4.1: Dump file created with active sessions ✓ Scenario 4.1: Dump excludes .session directory (transient) ✓ Scenario 4.1: Dump includes WG configs ✓ Scenario 4.1: Dump includes OVPN configs Database: /tmp/vpn-restore-a.krjTed Database: /tmp/vpn-restore-b.VdLbBh ✓ Scenario 4.2: Restored database has WG config ✓ Scenario 4.2: Restored database has no active sessions ✓ Scenario 5.1: Only 'latest' WG session after 10 cycles ✓ Scenario 5.1: Only 'latest' OVPN session after 10 cycles ✓ Scenario 5.1: Only latest session directory remains ✓ Story 11 completed successfully ▶ User Story 12: Phase Backend Selection (Strategy 7 - Automatic Template Lifting) Database: /tmp/vpn-backend-selection.DWCW3o ✓ Backend template lifted: firewall/pf.sh ✓ Backend template lifted: firewall/ipfw.sh ✓ Backend template lifted: dns/resolvconf.sh ✓ Backend template lifted: dns/unbound.sh ✓ Scenario 1: Connect script generated ✓ Scenario 1: PF firewall backend used (contains pfctl) ✓ Scenario 1: Resolvconf DNS backend used ✓ Scenario 2: IPFW firewall backend used (contains ipfw) ✓ Scenario 2: Unbound DNS backend used ✓ Scenario 2: PF firewall phase not used (backend isolated) ✓ Scenario 3: Backward compat - connect script generated ✓ Scenario 3: Backward compat - script not empty ✓ Scenario 3: Uses protocol-specific phases (wireguard/) ✓ Scenario 4: Both backends from @base profile used ✓ Scenario 5: Variant-only syntax works (uses default profile) ✓ Scenario 6: Mixed syntax - ipfw backend used ✓ Scenario 6: Mixed syntax - vpn phase executed ✓ Scenario 6: Mixed syntax - traditional dns phase used ✓ Story 12 completed successfully ======================================== Test Summary ======================================== User Stories: 12 Passed: 12 Failed: 0 Assertions: 296 Passed: 296 Failed: 0 ALL STORIES PASSED ======================================== vpn-switch Unit Test Suite (Formalized) ======================================== Running Tests ======================================== Filter active - running only:test_header test_summary test_setup test_printenv_command test_status_command test_wireguard_import_valid test_wireguard_add_category test_wireguard_link_create test_wireguard_list test_wireguard_validate test_wireguard_info test_wireguard_start_basic test_wireguard_connect_resume test_wireguard_stop_basic test_session_list test_session_show test_session_remove test_session_save_default test_session_save_named test_session_start_default test_session_start_named test_session_start_bypid test_session_stop_named test_session_stop_bypid test_session_stop_inactive test_wireguard_remove_config_in_use test_wireguard_remove_config_with_refs test_wireguard_remove_symlink test_wireguard_remove_category_link test_wireguard_clean_no_broken test_wireguard_clean_broken_protocol_link test_wireguard_clean_broken_category_link test_wireguard_clean_category_no_broken test_wireguard_clean_category_with_broken test_wireguard_validate_broken_symlink test_wireguard_validate_broken_category_symlink test_wireguard_validate_naming_conflict test_wireguard_validate_invalid_config test_stop_no_sessions test_stop_specific_interface test_wireguard_disconnect_interface test_stop_nonexistent_interface test_disconnect_without_session test_stop_twice_idempotent test_wireguard_import_nonexistent test_wireguard_import_duplicate test_wireguard_add_category_conflict test_wireguard_add_link_conflict test_wireguard_link_conflict test_error_invalid_category test_error_broken_symlink test_error_invalid_command test_edge_duplicate_instance_prevention test_edge_stale_session_cleanup test_wireguard_patch_valid test_wireguard_patch_nonexistent test_wireguard_patch_absolute test_wireguard_info_category test_session_save_default test_session_save_named test_session_start_default test_session_start_named test_session_start_by_pid test_protocol_agnostic_import_wireguard test_protocol_agnostic_list test_protocol_agnostic_link test_protocol_agnostic_remove test_protocol_agnostic_validate test_network_validate test_permissions_validate test_environment_validate test_batch_validate_includes_system test_interpreter_single_underscore test_interpreter_double_underscore test_interpreter_triple_underscore test_interpreter_resolution_priority test_start_wireguard_only test_start_openvpn_only test_start_not_found test_start_no_default test_start_with_default_wireguard test_start_with_default_openvpn test_start_default_invalid_target test_init_extension_links test_database_init test_environment_init test_phases_copy test_phases_lift test_phases_sync_single test_phases_sync_all test_init_batch_combinator test_init_combinator test_start_extension_link_fast_path test_start_multiple_matches test_openvpn_import_valid test_openvpn_list test_openvpn_add_group test_openvpn_link test_openvpn_remove test_openvpn_validate test_openvpn_info test_openvpn_dump test_openvpn_patch_valid test_openvpn_patch_nonexistent test_openvpn_patch_absolute test_openvpn_patch_credentials_bare test_openvpn_patch_credentials_existing test_openvpn_patch_credentials_missing test_openvpn_start_basic test_openvpn_stop_basic test_openvpn_disconnect_interface test_openvpn_clean test_setenv_basic test_setenv_invalid_name test_getenv_local_override test_getenv_fallback_chain test_unsetenv_existing test_unsetenv_not_set test_dumpenv_prologue test_dumpenv_epilogue test_dumpenv_profile_filtering test_environment_cache_on test_environment_cache_off test_environment_cache_status test_environment_cache_no_args test_cache_invalidation_setenv test_cache_invalidation_unsetenv test_cache_invalidation_environment_init test_dumpenv_cache_preservation test_dumpenv_cache_not_included_when_disabled test_cache_no_recursion test_inspect_batch_complete test_environment_inspect test_system_inspect test_batch_syntax_wireguard_clean test_combinators_literal_variable test_function_classification_correct test_no_terminal_output_vpnswitch_commands test_metadata_function_lists test_combinator_syntax_validation test_error_command_single_line test_error_command_two_lines test_error_command_three_lines test_error_command_ansi_colors test_batch_id_sequential test_store_batch_exits_basic test_store_batch_exits_references test_free_batch_id test_batch_infrastructure_lifecycle TEST 1 (test_batch_id_sequential): get_batch_id - sequential allocation Database: /tmp/vpn-switch-test.88851/test_1 ✓ First batch ID is 0 ✓ Second batch ID is 1 ✓ Third batch ID is 2 ✓ Counter file has correct value (3) TEST 2 (test_store_batch_exits_basic): store_batch_exits - stores exit codes to file Database: /tmp/vpn-switch-test.88851/test_2 ✓ Batch file created ✓ Batch file has correct content TEST 3 (test_store_batch_exits_references): store_batch_exits - stores exit codes with batch references Database: /tmp/vpn-switch-test.88851/test_3 ✓ Batch file stores references correctly TEST 4 (test_free_batch_id): free_batch_id - deletes batch file Database: /tmp/vpn-switch-test.88851/test_4 ✓ Batch file exists before cleanup ✓ Batch file deleted after cleanup TEST 5 (test_batch_infrastructure_lifecycle): Batch infrastructure - full allocation/store/free lifecycle Database: /tmp/vpn-switch-test.88851/test_5 ✓ Allocated batch ID: 0 ✓ Batch results stored ✓ Batch results readable ✓ Batch cleaned up successfully TEST 6 (test_printenv_command): printenv - basic environment display Database: /tmp/vpn-switch-test.88851/test_6 ✓ Printenv command executed and shows header ✓ Printenv shows VPN_SWITCH_BASE variable TEST 7 (test_status_command): status - VPN status display Database: /tmp/vpn-switch-test.88851/test_7 ✓ Status command shows header ✓ Status shows disconnected state ✓ Status checks network interfaces TEST 8 (test_error_command_single_line): error command - single line message Database: /tmp/vpn-switch-test.88851/test_8 ✓ error command outputs printf with 'Error:' prefix ✓ error command outputs exit 1 ✓ error command redirects to stderr TEST 9 (test_error_command_two_lines): error command - two line message Database: /tmp/vpn-switch-test.88851/test_9 ✓ error command first line has 'Error:' prefix ✓ error command second line is indented without 'Error:' prefix ✓ error command outputs exit 1 TEST 10 (test_error_command_three_lines): error command - three line message Database: /tmp/vpn-switch-test.88851/test_10 ✓ error command first line has 'Error:' prefix ✓ error command has properly indented continuation lines ✓ error command includes all three message lines ✓ error command outputs exit 1 TEST 11 (test_error_command_ansi_colors): error command - ANSI color support Database: /tmp/vpn-switch-test.88851/test_11 ✓ error command includes ANSI escape codes when enabled ✓ error command includes ANSI reset code TEST 12 (test_wireguard_list): wireguard list - display configurations Database: /tmp/vpn-switch-test.88851/test_12 ✓ Configuration section header displayed ✓ Config files section displayed ✓ Imported config file listed TEST 13 (test_wireguard_validate): wireguard validate - validate clean configuration Database: /tmp/vpn-switch-test.88851/test_13 ✓ Validation header displayed ✓ No issues found in clean configuration TEST 14 (test_wireguard_info): wireguard info - display category information Database: /tmp/vpn-switch-test.88851/test_14 ✓ Category header displayed ✓ Category path displayed ✓ Contents section displayed ✓ Category contents listed with symlink arrows TEST 15 (test_wireguard_import_valid): wireguard import - import valid config Database: /tmp/vpn-switch-test.88851/test_15 ✓ Config file imported to database ✓ Permissions set to 0400 (read-only) TEST 16 (test_wireguard_add_category): wireguard add - create category with permissions Database: /tmp/vpn-switch-test.88851/test_16 ✓ Category directory created ✓ Permissions set to 0755 TEST 17 (test_wireguard_link_create): wireguard link - create symlink in protocol directory Database: /tmp/vpn-switch-test.88851/test_17 ✓ Symlink created ✓ Symlink points to correct relative path (./wg-TEST-RS-1.conf) TEST 18 (test_wireguard_start_basic): wireguard start - create session and connect to VPN Database: /tmp/vpn-switch-test.88851/test_18 ✓ Session creation logged ✓ wg-quick command in connect.sh ✓ Session directory created in .session/ ✓ Session metadata files created ✓ connect.sh script generated ✓ connect.sh is executable ✓ connect.sh documents original config with relative path ✓ Patched config (wg_test13.conf) created ✓ Patched config correctly strips PostUp hook (phase-based DNS) ✓ Patched config correctly strips PostDown hook (phase-based DNS) TEST 19 (test_wireguard_connect_resume): wireguard connect - resume existing session by ID Database: /tmp/vpn-switch-test.88851/test_19 ✓ wireguard connect generated wg-quick command in connect.sh ✓ wireguard connect generated pfctl command in connect.sh ✓ wireguard connect used session configuration ✓ connect.sh preserved after connect TEST 20 (test_wireguard_stop_basic): stop - disconnect active VPN session Database: /tmp/vpn-switch-test.88851/test_20 ✓ Session exists before stop ✓ disconnect.sh contains wg-quick down command ✓ Stop command executed ✓ Session preserved after stop (has 'latest' link) TEST 21 (test_session_list): session list - display active and stale sessions Database: /tmp/vpn-switch-test.88851/test_21 ✓ Session list header displayed ✓ Active session (PID 27440) listed ✓ Stale session (PID 99997) listed ✓ Stale session (dead process) marked as stopped TEST 22 (test_session_show): session show - display connect script Database: /tmp/vpn-switch-test.88851/test_22 ✓ Extracted session ID (89236) from start command output ✓ Session ID displayed in header ✓ Session protocol displayed ✓ Connect script contents displayed TEST 23 (test_session_remove): session remove - remove stale, refuse active Database: /tmp/vpn-switch-test.88851/test_23 ✓ Stale session created for removal test ✓ Removal operation logged for stale session ✓ Active session (PID 88851) created for refusal test ✓ Refuses to remove active session (PID 88851) TEST 24 (test_session_save_default): session save - save current session as default Database: /tmp/vpn-switch-test.88851/test_24 ✓ Default session symlink created ✓ Default symlink points to correct session TEST 25 (test_session_save_named): session save work - save with custom name Database: /tmp/vpn-switch-test.88851/test_25 ✓ Named session symlink created ✓ Named symlink points to correct session TEST 26 (test_session_start_default): session start - resume default session Database: /tmp/vpn-switch-test.88851/test_26 ✓ Connect script created before stopping ✓ Session directory kept for resumption (referenced) ✓ Default symlink persists after stop ✓ Session start executed successfully TEST 27 (test_session_start_named): session start work - resume named session Database: /tmp/vpn-switch-test.88851/test_27 ✓ Named symlink persists after stop ✓ Named session start executed successfully TEST 28 (test_session_start_bypid): session start - resume session by PID Database: /tmp/vpn-switch-test.88851/test_28 ✓ Mock session (PID 11111) created for PID resume test ✓ Session start resumes by explicit PID (11111) TEST 29 (test_session_stop_named): session stop work - stop active named session Database: /tmp/vpn-switch-test.88851/test_29 ✓ Session stop resolves named session 'work' TEST 30 (test_session_stop_bypid): session stop - stop active session by PID Database: /tmp/vpn-switch-test.88851/test_30 ✓ Session stop handles PID (88888) TEST 31 (test_session_stop_inactive): session stop - inactive session should log (not error) Database: /tmp/vpn-switch-test.88851/test_31 ✓ Session stop handles inactive session gracefully TEST 32 (test_wireguard_remove_config_in_use): wireguard remove - refuse removal when config in use Database: /tmp/vpn-switch-test.88851/test_32 ✓ Active session (PID 88851) created using config ✓ Error message when config in use by session ✓ Error suggests removing session first TEST 33 (test_wireguard_remove_config_with_refs): wireguard remove - refuse removal when config has symlink refs Database: /tmp/vpn-switch-test.88851/test_33 ✓ Category symlink created (privacy/rm2) ✓ Error message when config has symlink references ✓ Error lists symlink references TEST 34 (test_wireguard_remove_symlink): wireguard remove - remove symlink (no safety checks) Database: /tmp/vpn-switch-test.88851/test_34 ✓ Test symlink created ✓ Symlink removal operation logged ✓ Symlink was removed TEST 35 (test_wireguard_remove_category_link): wireguard remove - remove link from category Database: /tmp/vpn-switch-test.88851/test_35 ✓ Category link (privacy/rm4) created ✓ Category link removal operation logged ✓ Category link was removed TEST 36 (test_wireguard_clean_no_broken): wireguard clean - no broken links found Database: /tmp/vpn-switch-test.88851/test_36 ✓ Clean header displayed ✓ No broken symlinks message displayed ✓ Usage hint displayed TEST 37 (test_wireguard_clean_broken_protocol_link): wireguard clean - detect and generate remove for broken protocol link Database: /tmp/vpn-switch-test.88851/test_37 ✓ Broken protocol symlink created for testing ✓ Remove command generated for broken protocol link ✓ Command includes link name TEST 38 (test_wireguard_clean_broken_category_link): wireguard clean - detect and generate remove for broken category link Database: /tmp/vpn-switch-test.88851/test_38 ✓ Broken category symlink created for testing ✓ Remove command generated for broken category link ✓ Command includes category name TEST 39 (test_wireguard_clean_category_no_broken): wireguard clean privacy - category with no broken links Database: /tmp/vpn-switch-test.88851/test_39 ✓ Category-specific header displayed ✓ No broken symlinks message for category TEST 40 (test_wireguard_clean_category_with_broken): wireguard clean privacy - category with broken links Database: /tmp/vpn-switch-test.88851/test_40 ✓ Broken symlink created in privacy category ✓ Remove command generated for category link ✓ Category-specific clean (not global) TEST 41 (test_wireguard_validate_broken_symlink): wireguard validate - detect broken symlinks Database: /tmp/vpn-switch-test.88851/test_41 ✓ Broken symlink created for validation test ✓ Broken symlink detected in protocol directory ✓ Error status reported TEST 42 (test_wireguard_validate_broken_category_symlink): wireguard validate - detect broken symlinks in categories Database: /tmp/vpn-switch-test.88851/test_42 ✓ Broken category symlink created for validation test ✓ Broken symlink detected in category TEST 43 (test_wireguard_validate_naming_conflict): wireguard validate - detect naming conflicts Database: /tmp/vpn-switch-test.88851/test_43 ✓ Naming conflict created (file + directory) ✓ Naming conflict detected TEST 44 (test_wireguard_validate_invalid_config): wireguard validate - detect invalid config files Database: /tmp/vpn-switch-test.88851/test_44 ✓ Empty config file created for validation test ✓ Empty config file detected ✓ Missing [Interface] section detected TEST 45 (test_stop_no_sessions): stop - no sessions exist (empty output) Database: /tmp/vpn-switch-test.88851/test_45 ✓ No output or log message when no sessions exist TEST 46 (test_stop_specific_interface): stop wg_test_safe - stop specific interface by name Database: /tmp/vpn-switch-test.88851/test_46 ✓ Active session (PID 88851, interface wg_test_safe) created ✓ Stopped specific interface wg_test_safe ✓ Interface wg_test_safe disconnect command generated TEST 47 (test_wireguard_disconnect_interface): wireguard disconnect wg_test_safe - direct disconnect command Database: /tmp/vpn-switch-test.88851/test_47 ✓ Active session (PID 88851) created for disconnect test ✓ Disconnect command executed for wg_test_safe ✓ Session PID displayed correctly TEST 48 (test_stop_nonexistent_interface): stop wg_test_other - error when interface not found Database: /tmp/vpn-switch-test.88851/test_48 ✓ Active session with wg_test_safe interface created ✓ Error message for nonexistent interface TEST 49 (test_disconnect_without_session): disconnect without session - error handling Database: /tmp/vpn-switch-test.88851/test_49 ✓ Error message when no session exists TEST 50 (test_stop_twice_idempotent): stop twice - idempotent (safe to call multiple times) Database: /tmp/vpn-switch-test.88851/test_50 ✓ First stop: handles no sessions gracefully ✓ Second stop: still handles no sessions (idempotent) TEST 51 (test_wireguard_import_nonexistent): wireguard import - error when file doesn't exist Database: /tmp/vpn-switch-test.88851/test_51 ✓ Error message for non-existent file TEST 52 (test_wireguard_import_duplicate): wireguard import - error when config already exists Database: /tmp/vpn-switch-test.88851/test_52 ✓ First import succeeded ✓ Error message when config already exists TEST 53 (test_wireguard_add_category_conflict): wireguard add - error when category already exists Database: /tmp/vpn-switch-test.88851/test_53 ✓ First add succeeded (privacy category created) ✓ Error message when category already exists TEST 54 (test_wireguard_add_link_conflict): wireguard add - error when link already exists Database: /tmp/vpn-switch-test.88851/test_54 ✓ First link created successfully ✓ Error message when link already exists TEST 55 (test_wireguard_link_conflict): wireguard link - error when alias already exists Database: /tmp/vpn-switch-test.88851/test_55 ✓ Config imported successfully ✓ Error message when alias already exists TEST 56 (test_error_invalid_category): error handling - invalid category shows error Database: /tmp/vpn-switch-test.88851/test_56 ✓ Error message for invalid category TEST 57 (test_error_broken_symlink): error handling - broken symlink handled gracefully Database: /tmp/vpn-switch-test.88851/test_57 ✓ Broken symlink created for testing ✓ Handled broken symlink (error or skipped) TEST 58 (test_error_invalid_command): error handling - invalid command shows usage Database: /tmp/vpn-switch-test.88851/test_58 ✓ Usage/help shown for invalid command TEST 59 (test_edge_duplicate_instance_prevention): edge case - prevent duplicate VPN instances Database: /tmp/vpn-switch-test.88851/test_59 ✓ First VPN session created (PID 88851) ✓ Detected existing VPN instance ✓ No duplicate session created TEST 60 (test_edge_stale_session_cleanup): edge case - stale sessions don't block new sessions Database: /tmp/vpn-switch-test.88851/test_60 ✓ Stale session created for testing ✓ Proceeded with new session (stale session didn't block) ✓ Stale session preserved (manual cleanup via 'session clean' required) TEST 61 (test_wireguard_patch_valid): wireguard patch - displays patched configuration Database: /tmp/vpn-switch-test.88851/test_61 ✓ Patch output correctly strips PostUp hook (phase-based DNS) ✓ Patch output correctly strips PostDown hook (phase-based DNS) ✓ Patch output preserves [Interface] section ✓ Patch output preserves [Peer] section TEST 62 (test_wireguard_patch_nonexistent): wireguard patch - handles nonexistent config Database: /tmp/vpn-switch-test.88851/test_62 ✓ Patch rejects nonexistent config with error TEST 63 (test_wireguard_patch_absolute): wireguard patch - handles absolute path Database: /tmp/vpn-switch-test.88851/test_63 ✓ Patch works with absolute path (strips DNS hooks) TEST 64 (test_wireguard_info_category): wireguard info - displays category information Database: /tmp/vpn-switch-test.88851/test_64 ✓ Category header displayed ✓ Config count displayed ✓ Link count displayed ✓ Category path displayed ✓ Contents section header displayed ✓ Category contents listed with symlink arrows TEST 65 (test_session_save_default): session save - save current session as default Database: /tmp/vpn-switch-test.88851/test_65 ✓ Default session symlink created ✓ Default symlink points to correct session TEST 66 (test_session_save_named): session save work - save with custom name Database: /tmp/vpn-switch-test.88851/test_66 ✓ Named session symlink created ✓ Named symlink points to correct session TEST 67 (test_session_start_default): session start - resume default session Database: /tmp/vpn-switch-test.88851/test_67 ✓ Connect script created before stopping ✓ Session directory kept for resumption (referenced) ✓ Default symlink persists after stop ✓ Session start executed successfully TEST 68 (test_session_start_named): session start work - resume named session Database: /tmp/vpn-switch-test.88851/test_68 ✓ Named symlink persists after stop ✓ Named session start executed successfully TEST 69 (test_session_start_by_pid): session start - resume by PID Database: /tmp/vpn-switch-test.88851/test_69 ✓ Session start by PID executed successfully TEST 70 (test_openvpn_import_valid): openvpn import - import valid .ovpn config Database: /tmp/vpn-switch-test.88851/test_70 ✓ Config imported to openvpn/ ✓ Permissions set to 0400 TEST 71 (test_openvpn_list): openvpn list - list configs and groups Database: /tmp/vpn-switch-test.88851/test_71 ✓ Lists config: us-server.ovpn ✓ Lists group: work/ ✓ Lists group link with arity-1: work/office TEST 72 (test_openvpn_add_group): openvpn add - create group Database: /tmp/vpn-switch-test.88851/test_72 ✓ Group directory created ✓ Group permissions correct (0700) TEST 73 (test_openvpn_link): openvpn link - create protocol-level link Database: /tmp/vpn-switch-test.88851/test_73 ✓ Protocol-level link created ✓ Link target correct TEST 74 (test_openvpn_remove): openvpn remove - remove config safely Database: /tmp/vpn-switch-test.88851/test_74 ✓ Config removed ✓ Other config preserved TEST 75 (test_openvpn_validate): openvpn validate - detect broken links Database: /tmp/vpn-switch-test.88851/test_75 ✓ Broken symlink detected ✓ Valid database passes validation TEST 76 (test_openvpn_info): openvpn info - show group information Database: /tmp/vpn-switch-test.88851/test_76 ✓ Shows group name ✓ Shows correct link count ✓ Shows link: office TEST 77 (test_openvpn_dump): openvpn dump - export database Database: /tmp/vpn-switch-test.88851/test_77 ✓ Dump includes import command ✓ Dump includes group creation ✓ Dump includes protocol link ✓ Dump includes group link TEST 78 (test_openvpn_patch_valid): openvpn patch - displays patched configuration Database: /tmp/vpn-switch-test.88851/test_78 ✓ Patch output correctly strips up script (phase-based DNS) ✓ Patch output correctly strips down script (phase-based DNS) ✓ Patch output contains daemon mode ✓ Patch output contains device interface ✓ Patch output contains writepid directive ✓ Patch output preserves client directive ✓ Patch output preserves remote server TEST 79 (test_openvpn_patch_nonexistent): openvpn patch - handles nonexistent config Database: /tmp/vpn-switch-test.88851/test_79 ✓ Error message for nonexistent config TEST 80 (test_openvpn_patch_absolute): openvpn patch - handles absolute path Database: /tmp/vpn-switch-test.88851/test_80 ✓ Absolute path patch works TEST 81 (test_openvpn_patch_credentials_bare): openvpn patch - patches bare auth-user-pass with credentials Database: /tmp/vpn-switch-test.88851/test_81 ✓ Bare auth-user-pass patched with credentials path ✓ Bare auth-user-pass preserved when no credentials set TEST 82 (test_openvpn_patch_credentials_existing): openvpn patch - preserves existing auth-user-pass path Database: /tmp/vpn-switch-test.88851/test_82 ✓ Existing auth-user-pass path preserved (not overridden) TEST 83 (test_openvpn_patch_credentials_missing): openvpn patch - handles config without auth-user-pass Database: /tmp/vpn-switch-test.88851/test_83 ✓ Config without auth-user-pass remains unchanged TEST 84 (test_openvpn_start_basic): openvpn start - create session and connect to VPN Database: /tmp/vpn-switch-test.88851/test_84 ✓ Session creation logged ✓ openvpn command in connect.sh ✓ Session directory created in .session/ ✓ Session metadata files created ✓ connect.sh script generated ✓ connect.sh is executable ✓ Patched config (tun_test80.ovpn) created ✓ Patched config contains daemon mode ✓ Patched config correctly strips up script (phase-based DNS) ✓ Patched config correctly strips down script (phase-based DNS) TEST 85 (test_openvpn_stop_basic): openvpn stop - cleanup commands for session Database: /tmp/vpn-switch-test.88851/test_85 ✓ Session created via user interface ✓ Disconnect commands reference correct interface (tun_test85) ✓ Disconnect generates process kill commands TEST 86 (test_openvpn_disconnect_interface): openvpn disconnect - tear down OpenVPN interface Database: /tmp/vpn-switch-test.88851/test_86 ✓ Disconnect generates process termination commands TEST 87 (test_openvpn_clean): openvpn clean - generate cleanup commands for broken links Database: /tmp/vpn-switch-test.88851/test_87 ✓ Clean generates remove commands ✓ Clean detected broken symlink TEST 88 (test_protocol_agnostic_import_wireguard): import (protocol-agnostic) - detects WireGuard .conf file Database: /tmp/vpn-switch-test.88851/test_88 ✓ Protocol-agnostic import detected .conf and delegated to wireguard import ✓ Protocol-agnostic import generates correct cp command TEST 89 (test_protocol_agnostic_list): list (protocol-agnostic) - delegates to all protocols Database: /tmp/vpn-switch-test.88851/test_89 ✓ Protocol-agnostic list delegated to wireguard list ✓ Protocol-agnostic list shows wireguard config sections ✓ Protocol-agnostic list has no duplicate lines (3 unique) TEST 90 (test_protocol_agnostic_link): link (protocol-agnostic) - creates protocol-level alias Database: /tmp/vpn-switch-test.88851/test_90 ✓ Protocol-agnostic link generates ln command ✓ Protocol-agnostic link uses correct relative path (./wireguard) ✓ Protocol-agnostic link includes correct alias name TEST 91 (test_protocol_agnostic_remove): remove (protocol-agnostic) - removes protocol-level link Database: /tmp/vpn-switch-test.88851/test_91 ✓ Protocol-agnostic remove generates rm command ✓ Protocol-agnostic remove includes descriptive comment ✓ Protocol-agnostic remove errors on non-existent link TEST 92 (test_protocol_agnostic_validate): validate (protocol-agnostic) - delegates to all protocols Database: /tmp/vpn-switch-test.88851/test_92 ✓ Protocol-agnostic validate delegated to wireguard validate ✓ Protocol-agnostic validate shows validation output TEST 93 (test_network_validate): network validate - check network prerequisites Database: /tmp/vpn-switch-test.88851/test_93 ✓ Network validation header displayed ✓ Network validate passed on clean configuration TEST 94 (test_permissions_validate): permissions validate - check filesystem permissions Database: /tmp/vpn-switch-test.88851/test_94 ✓ Permissions validation header displayed ✓ Permissions validate passed on clean configuration TEST 95 (test_environment_validate): environment validate - check environment variables Database: /tmp/vpn-switch-test.88851/test_95 ✓ Environment validation header displayed ✓ Environment validate passed on clean configuration TEST 96 (test_batch_validate_includes_system): validate (batch) - includes system validators Database: /tmp/vpn-switch-test.88851/test_96 ✓ Batch validate includes database validator ✓ Batch validate includes binaries validator ✓ Batch validate includes phases validator ✓ Batch validate includes network validator ✓ Batch validate includes permissions validator ✓ Batch validate includes environment validator TEST 97 (test_start_wireguard_only): start - auto-detect WireGuard config Database: /tmp/vpn-switch-test.88851/test_97 ✓ Delegates to wireguard commands for WireGuard-only config TEST 98 (test_start_openvpn_only): start - auto-detect OpenVPN config Database: /tmp/vpn-switch-test.88851/test_98 ✓ Delegates to openvpn commands for OpenVPN-only config TEST 99 (test_start_not_found): start - error on nonexistent config Database: /tmp/vpn-switch-test.88851/test_99 ✓ Error message for nonexistent config ✓ Error shows both search locations TEST 100 (test_start_no_default): start - error when no configs exist (Phase 3.4.1) Database: /tmp/vpn-switch-test.88851/test_100 ✓ Error message when no configs available ✓ Error provides hint to import configs TEST 101 (test_start_with_default_wireguard): start - use default link (WireGuard) via API Database: /tmp/vpn-switch-test.88851/test_101 ✓ Default session link created via API ✓ Start with no args resolves to default session TEST 102 (test_start_with_default_openvpn): start - use default link (OpenVPN) via API Database: /tmp/vpn-switch-test.88851/test_102 ✓ Default session link created via API ✓ Start with no args resolves to default session TEST 103 (test_start_default_invalid_target): start - error on invalid default link target Database: /tmp/vpn-switch-test.88851/test_103 ✓ Error detected for invalid default session target TEST 104 (test_init_extension_links): init - creates protocol extension links (Phase 3.4.1) Database: /tmp/vpn-switch-test.88851/test_104 ✓ conf link created ✓ ovpn link created ✓ conf → wireguard ✓ ovpn → openvpn TEST 105 (test_start_extension_link_fast_path): start - uses extension link for protocol resolution (Phase 3.4.1) Database: /tmp/vpn-switch-test.88851/test_105 ✓ Extension link used for fast protocol resolution (wireguard commands found) TEST 106 (test_start_multiple_matches): start - error on multiple protocol matches (Phase 3.4.1) Database: /tmp/vpn-switch-test.88851/test_106 ✓ Multiple matches error shown ✓ Both matches listed TEST 107 (test_database_init): database init - creates directory structure (Phase 4.4) Database: /tmp/vpn-switch-test.88851/test_107 ✓ wireguard/ created ✓ openvpn/ created ✓ .session/ created ✓ session/ created ✓ .env/default/ created ✓ .env/local/ created ✓ .include/phase/ created TEST 108 (test_environment_init): environment init - copies profile templates (Phase 4.4) Database: /tmp/vpn-switch-test.88851/test_108 ✓ minimal profile copied ✓ profile has correct permissions (0600) TEST 109 (test_phases_copy): phases copy - copies phase templates (Phase 4.4) Database: /tmp/vpn-switch-test.88851/test_109 ✓ wireguard phases copied ✓ openvpn phases copied ✓ wireguard phase subdirs exist TEST 110 (test_phases_lift): phases lift - lifts phase:backend templates (Phase 4.4) Database: /tmp/vpn-switch-test.88851/test_110 ✓ generates lift command ✓ output file is executable TEST 111 (test_phases_sync_single): phases sync - discovers and lifts backends (Phase 4.4) Database: /tmp/vpn-switch-test.88851/test_111 ✓ delegates to phases lift TEST 112 (test_phases_sync_all): phases sync - syncs all phases (Phase 4.4) Database: /tmp/vpn-switch-test.88851/test_112 ✓ delegates to single-phase sync TEST 113 (test_init_batch_combinator): init - orchestrates full initialization (Phase 4.4) Database: /tmp/vpn-switch-test.88851/test_113 ✓ database init executed ✓ environment init executed ✓ phases copy executed TEST 114 (test_init_combinator): init combinator - delegates to batch combinator (Phase 4.4) Database: /tmp/vpn-switch-test.88851/test_114 ✓ database created ✓ profile installed TEST 115 (test_setenv_basic): setenv - basic variable setting Database: /tmp/vpn-switch-test.88851/test_115 ✓ .env/local directory created ✓ Variable file created ✓ Variable has correct value ✓ File has correct permissions (0600 or 0640 for cross-user support) ✓ Shows confirmation message TEST 116 (test_setenv_invalid_name): setenv - invalid variable name Database: /tmp/vpn-switch-test.88851/test_116 ✓ Rejects invalid variable name ✓ No file created for invalid name TEST 117 (test_getenv_local_override): getenv - shows local override Database: /tmp/vpn-switch-test.88851/test_117 ✓ Shows local override source ✓ Outputs correct value from local TEST 118 (test_getenv_fallback_chain): getenv - fallback chain (local > default > template) Database: /tmp/vpn-switch-test.88851/test_118 ✓ Shows error if variable not found ✓ Falls back to .env/default ✓ Falls back to template/environment TEST 119 (test_unsetenv_existing): unsetenv - remove existing variable Database: /tmp/vpn-switch-test.88851/test_119 ✓ Variable file was removed ✓ Shows confirmation message TEST 120 (test_unsetenv_not_set): unsetenv - variable not set in local Database: /tmp/vpn-switch-test.88851/test_120 ✓ Shows informative message when not set TEST 121 (test_dumpenv_prologue): dumpenv prologue - outputs safe minimal set Database: /tmp/vpn-switch-test.88851/test_121 ✓ Prologue includes VPN_SWITCH_TERMINAL_INTERPRETER ✓ Prologue includes VPN_SWITCH_DISPLAY_ANSI ✓ Prologue excludes VPN_SWITCH_INTERPRETER_wireguard_list (epilogue-only) ✓ Prologue excludes VPN_SWITCH_INTERPRETER_wireguard_import1 (epilogue-only) TEST 122 (test_dumpenv_epilogue): dumpenv epilogue - outputs complete set Database: /tmp/vpn-switch-test.88851/test_122 ✓ Epilogue includes VPN_SWITCH_TERMINAL_INTERPRETER ✓ Epilogue includes VPN_SWITCH_DISPLAY_ANSI ✓ Epilogue includes VPN_SWITCH_INTERPRETER_wireguard_list ✓ Epilogue includes VPN_SWITCH_INTERPRETER_wireguard_import1 TEST 123 (test_dumpenv_profile_filtering): dumpenv - profile filtering prevents restore breakage Database: /tmp/vpn-switch-test.88851/test_123 ✓ Prologue correctly excludes function-specific interpreter ✓ Epilogue correctly includes function-specific interpreter TEST 124 (test_environment_cache_on): environment cache on - creates cache file with correct permissions Database: /tmp/vpn-switch-test.88851/test_124 ✓ Cache file created ✓ Cache file has correct permissions (0600) ✓ Shows cache enabled message ✓ Cache file has content TEST 125 (test_environment_cache_off): environment cache off - removes cache file Database: /tmp/vpn-switch-test.88851/test_125 ✓ Cache file removed ✓ Shows cache disabled message TEST 126 (test_environment_cache_status): environment cache status - shows correct status Database: /tmp/vpn-switch-test.88851/test_126 ✓ Shows DISABLED status when cache off ✓ Shows ENABLED status when cache on ✓ Shows cached variable count TEST 127 (test_environment_cache_no_args): environment cache (no args) - defaults to status Database: /tmp/vpn-switch-test.88851/test_127 ✓ Shows status with no arguments TEST 128 (test_cache_invalidation_setenv): setenv - rebuilds cache automatically Database: /tmp/vpn-switch-test.88851/test_128 ✓ Cache rebuilt automatically after setenv ✓ Rebuilt cache contains new variable TEST_VAR TEST 129 (test_cache_invalidation_unsetenv): unsetenv - rebuilds cache automatically Database: /tmp/vpn-switch-test.88851/test_129 ✓ Cache rebuilt automatically after unsetenv ✓ Rebuilt cache no longer contains TEST_VAR TEST 130 (test_cache_invalidation_environment_init): environment init - invalidates cache automatically Database: /tmp/vpn-switch-test.88851/test_130 ✓ Cache file removed after environment init ✓ Shows cache invalidation warning TEST 131 (test_dumpenv_cache_preservation): dumpenv epilogue - includes cache if enabled Database: /tmp/vpn-switch-test.88851/test_131 ✓ Epilogue includes cache content ✓ Epilogue includes cache restore comment TEST 132 (test_dumpenv_cache_not_included_when_disabled): dumpenv epilogue - excludes cache when disabled Database: /tmp/vpn-switch-test.88851/test_132 ✓ Epilogue correctly excludes cache when disabled TEST 133 (test_cache_no_recursion): environment cache on - excludes cache file from scan Database: /tmp/vpn-switch-test.88851/test_133 ✓ Cache correctly excludes itself TEST 134 (test_interpreter_single_underscore): interpreter resolution - single underscore uses TERMINAL_INTERPRETER Database: /tmp/vpn-switch-test.88851/test_134 # Set VPN_SWITCH_TERMINAL_INTERPRETER (effective next command) ✓ Single underscore function used TERMINAL_INTERPRETER TEST 135 (test_interpreter_double_underscore): interpreter resolution - double underscore uses COMBINATOR_INTERPRETER Database: /tmp/vpn-switch-test.88851/test_135 # Set VPN_SWITCH_COMBINATOR_INTERPRETER (effective next command) ✓ Double underscore function used COMBINATOR_INTERPRETER TEST 136 (test_interpreter_triple_underscore): interpreter resolution - triple underscore uses BATCH_COMBINATOR_INTERPRETER Database: /tmp/vpn-switch-test.88851/test_136 # Set VPN_SWITCH_BATCH_COMBINATOR_INTERPRETER (effective next command) ✓ Triple underscore function used BATCH_COMBINATOR_INTERPRETER TEST 137 (test_interpreter_resolution_priority): interpreter resolution - function-specific override beats intrinsic classification Database: /tmp/vpn-switch-test.88851/test_137 # Set VPN_SWITCH_TERMINAL_INTERPRETER (effective next command) ✓ Function-specific override takes priority over intrinsic classification ✓ Intrinsic classification was correctly bypassed TEST 138 (test_inspect_batch_complete): inspect (batch) - includes all inspection sections Database: /tmp/vpn-switch-test.88851/test_138 ✓ Batch inspect includes environment section ✓ Batch inspect includes system section ✓ Batch inspect includes WireGuard section ✓ Batch inspect includes OpenVPN section ✓ Batch inspect includes session section ✓ Batch inspect includes phases section TEST 139 (test_environment_inspect): environment inspect - displays environment variables Database: /tmp/vpn-switch-test.88851/test_139 ✓ Environment inspect shows header ✓ Environment inspect shows VPN_SWITCH_BASE ✓ Environment inspect shows database structure TEST 140 (test_system_inspect): system inspect - displays system configuration Database: /tmp/vpn-switch-test.88851/test_140 ✓ System inspect shows header ✓ System inspect shows system info section ✓ System inspect shows network interfaces section TEST 141 (test_batch_syntax_wireguard_clean): wireguard clean - validates batch syntax Database: /tmp/vpn-switch-test.88851/test_141 ✓ wireguard clean outputs valid batch syntax ✓ wireguard clean uses literal $VPN_SWITCH_CONTEXT_SCRIPT TEST 142 (test_combinators_literal_variable): combinators - use literal $VPN_SWITCH_CONTEXT_SCRIPT Database: /tmp/vpn-switch-test.88851/test_142 ✓ wireguard start uses literal variable ✓ wireguard start variable not expanded TEST 143 (test_combinator_syntax_validation): combinators - validate single-command output syntax Database: /tmp/vpn-switch-test.88851/test_143 ✓ wireguard start outputs exactly one command ✓ wireguard start uses literal variable ✓ wireguard start variable not expanded ✓ openvpn start outputs exactly one command ✓ start (protocol-agnostic) outputs exactly one command TEST 144 (test_function_classification_correct): function classification - naming matches behavior ✓ wireguard add2 correctly classified as combinator (__) ✓ wireguard clean0 correctly classified as batch (___) ✓ openvpn clean0 correctly classified as batch (___) TEST 145 (test_no_terminal_output_vpnswitch_commands): terminal functions - must not output vpn-switch commands ✓ No terminal functions output vpn-switch commands TEST 146 (test_metadata_function_lists): metadata - function lists accurate after renames ✓ Metadata includes __wireguard_add2 in combinators ✓ Metadata includes ___wireguard_clean0 in batch combinators ✓ Metadata includes ___openvpn_clean0 in batch combinators ======================================== Test Summary ======================================== Test Functions: 146 Total Assertions: 371 Passed Assertions: 371 Failed Assertions: 0 ALL TESTS PASSED ======================================== vpn-switch Unit Test Suite (Formalized) ======================================== Running Tests ======================================== Filter active - running only:test_header test_summary test_setup test_printenv_command test_status_command test_wireguard_import_valid test_wireguard_add_category test_wireguard_link_create test_wireguard_list test_wireguard_validate test_wireguard_info test_wireguard_start_basic test_wireguard_connect_resume test_wireguard_stop_basic test_session_list test_session_show test_session_remove test_session_save_default test_session_save_named test_session_start_default test_session_start_named test_session_start_bypid test_session_stop_named test_session_stop_bypid test_session_stop_inactive test_wireguard_remove_config_in_use test_wireguard_remove_config_with_refs test_wireguard_remove_symlink test_wireguard_remove_category_link test_wireguard_clean_no_broken test_wireguard_clean_broken_protocol_link test_wireguard_clean_broken_category_link test_wireguard_clean_category_no_broken test_wireguard_clean_category_with_broken test_wireguard_validate_broken_symlink test_wireguard_validate_broken_category_symlink test_wireguard_validate_naming_conflict test_wireguard_validate_invalid_config test_stop_no_sessions test_stop_specific_interface test_wireguard_disconnect_interface test_stop_nonexistent_interface test_disconnect_without_session test_stop_twice_idempotent test_wireguard_import_nonexistent test_wireguard_import_duplicate test_wireguard_add_category_conflict test_wireguard_add_link_conflict test_wireguard_link_conflict test_error_invalid_category test_error_broken_symlink test_error_invalid_command test_edge_duplicate_instance_prevention test_edge_stale_session_cleanup test_wireguard_patch_valid test_wireguard_patch_nonexistent test_wireguard_patch_absolute test_wireguard_info_category test_session_save_default test_session_save_named test_session_start_default test_session_start_named test_session_start_by_pid test_protocol_agnostic_import_wireguard test_protocol_agnostic_list test_protocol_agnostic_link test_protocol_agnostic_remove test_protocol_agnostic_validate test_network_validate test_permissions_validate test_environment_validate test_batch_validate_includes_system test_interpreter_single_underscore test_interpreter_double_underscore test_interpreter_triple_underscore test_interpreter_resolution_priority test_start_wireguard_only test_start_openvpn_only test_start_not_found test_start_no_default test_start_with_default_wireguard test_start_with_default_openvpn test_start_default_invalid_target test_init_extension_links test_database_init test_environment_init test_phases_copy test_phases_lift test_phases_sync_single test_phases_sync_all test_init_batch_combinator test_init_combinator test_start_extension_link_fast_path test_start_multiple_matches test_openvpn_import_valid test_openvpn_list test_openvpn_add_group test_openvpn_link test_openvpn_remove test_openvpn_validate test_openvpn_info test_openvpn_dump test_openvpn_patch_valid test_openvpn_patch_nonexistent test_openvpn_patch_absolute test_openvpn_patch_credentials_bare test_openvpn_patch_credentials_existing test_openvpn_patch_credentials_missing test_openvpn_start_basic test_openvpn_stop_basic test_openvpn_disconnect_interface test_openvpn_clean test_setenv_basic test_setenv_invalid_name test_getenv_local_override test_getenv_fallback_chain test_unsetenv_existing test_unsetenv_not_set test_dumpenv_prologue test_dumpenv_epilogue test_dumpenv_profile_filtering test_environment_cache_on test_environment_cache_off test_environment_cache_status test_environment_cache_no_args test_cache_invalidation_setenv test_cache_invalidation_unsetenv test_cache_invalidation_environment_init test_dumpenv_cache_preservation test_dumpenv_cache_not_included_when_disabled test_cache_no_recursion test_inspect_batch_complete test_environment_inspect test_system_inspect test_batch_syntax_wireguard_clean test_combinators_literal_variable test_function_classification_correct test_no_terminal_output_vpnswitch_commands test_metadata_function_lists test_combinator_syntax_validation test_error_command_single_line test_error_command_two_lines test_error_command_three_lines test_error_command_ansi_colors test_batch_id_sequential test_store_batch_exits_basic test_store_batch_exits_references test_free_batch_id test_batch_infrastructure_lifecycle TEST 1 (test_batch_id_sequential): get_batch_id - sequential allocation Database: /tmp/vpn-switch-test.12000/test_1 ✓ First batch ID is 0 ✓ Second batch ID is 1 ✓ Third batch ID is 2 ✓ Counter file has correct value (3) TEST 2 (test_store_batch_exits_basic): store_batch_exits - stores exit codes to file Database: /tmp/vpn-switch-test.12000/test_2 ✓ Batch file created ✓ Batch file has correct content TEST 3 (test_store_batch_exits_references): store_batch_exits - stores exit codes with batch references Database: /tmp/vpn-switch-test.12000/test_3 ✓ Batch file stores references correctly TEST 4 (test_free_batch_id): free_batch_id - deletes batch file Database: /tmp/vpn-switch-test.12000/test_4 ✓ Batch file exists before cleanup ✓ Batch file deleted after cleanup TEST 5 (test_batch_infrastructure_lifecycle): Batch infrastructure - full allocation/store/free lifecycle Database: /tmp/vpn-switch-test.12000/test_5 ✓ Allocated batch ID: 0 ✓ Batch results stored ✓ Batch results readable ✓ Batch cleaned up successfully TEST 6 (test_printenv_command): printenv - basic environment display Database: /tmp/vpn-switch-test.12000/test_6 ✓ Printenv command executed and shows header ✓ Printenv shows VPN_SWITCH_BASE variable TEST 7 (test_status_command): status - VPN status display Database: /tmp/vpn-switch-test.12000/test_7 ✓ Status command shows header ✓ Status shows disconnected state ✓ Status checks network interfaces TEST 8 (test_error_command_single_line): error command - single line message Database: /tmp/vpn-switch-test.12000/test_8 ✓ error command outputs printf with 'Error:' prefix ✓ error command outputs exit 1 ✓ error command redirects to stderr TEST 9 (test_error_command_two_lines): error command - two line message Database: /tmp/vpn-switch-test.12000/test_9 ✓ error command first line has 'Error:' prefix ✓ error command second line is indented without 'Error:' prefix ✓ error command outputs exit 1 TEST 10 (test_error_command_three_lines): error command - three line message Database: /tmp/vpn-switch-test.12000/test_10 ✓ error command first line has 'Error:' prefix ✓ error command has properly indented continuation lines ✓ error command includes all three message lines ✓ error command outputs exit 1 TEST 11 (test_error_command_ansi_colors): error command - ANSI color support Database: /tmp/vpn-switch-test.12000/test_11 ✓ error command includes ANSI escape codes when enabled ✓ error command includes ANSI reset code TEST 12 (test_wireguard_list): wireguard list - display configurations Database: /tmp/vpn-switch-test.12000/test_12 ✓ Configuration section header displayed ✓ Config files section displayed ✓ Imported config file listed TEST 13 (test_wireguard_validate): wireguard validate - validate clean configuration Database: /tmp/vpn-switch-test.12000/test_13 ✓ Validation header displayed ✓ No issues found in clean configuration TEST 14 (test_wireguard_info): wireguard info - display category information Database: /tmp/vpn-switch-test.12000/test_14 ✓ Category header displayed ✓ Category path displayed ✓ Contents section displayed ✓ Category contents listed with symlink arrows TEST 15 (test_wireguard_import_valid): wireguard import - import valid config Database: /tmp/vpn-switch-test.12000/test_15 ✓ Config file imported to database ✓ Permissions set to 0400 (read-only) TEST 16 (test_wireguard_add_category): wireguard add - create category with permissions Database: /tmp/vpn-switch-test.12000/test_16 ✓ Category directory created ✓ Permissions set to 0755 TEST 17 (test_wireguard_link_create): wireguard link - create symlink in protocol directory Database: /tmp/vpn-switch-test.12000/test_17 ✓ Symlink created ✓ Symlink points to correct relative path (./wg-TEST-RS-1.conf) TEST 18 (test_wireguard_start_basic): wireguard start - create session and connect to VPN Database: /tmp/vpn-switch-test.12000/test_18 ✓ Session creation logged ✓ wg-quick command in connect.sh ✓ Session directory created in .session/ ✓ Session metadata files created ✓ connect.sh script generated ✓ connect.sh is executable ✓ connect.sh documents original config with relative path ✓ Patched config (wg_test13.conf) created ✓ Patched config correctly strips PostUp hook (phase-based DNS) ✓ Patched config correctly strips PostDown hook (phase-based DNS) TEST 19 (test_wireguard_connect_resume): wireguard connect - resume existing session by ID Database: /tmp/vpn-switch-test.12000/test_19 ✓ wireguard connect generated wg-quick command in connect.sh ✓ wireguard connect generated pfctl command in connect.sh ✓ wireguard connect used session configuration ✓ connect.sh preserved after connect TEST 20 (test_wireguard_stop_basic): stop - disconnect active VPN session Database: /tmp/vpn-switch-test.12000/test_20 ✓ Session exists before stop ✓ disconnect.sh contains wg-quick down command ✓ Stop command executed ✓ Session preserved after stop (has 'latest' link) TEST 21 (test_session_list): session list - display active and stale sessions Database: /tmp/vpn-switch-test.12000/test_21 ✓ Session list header displayed ✓ Active session (PID 91555) listed ✓ Stale session (PID 99997) listed ✓ Stale session (dead process) marked as stopped TEST 22 (test_session_show): session show - display connect script Database: /tmp/vpn-switch-test.12000/test_22 ✓ Extracted session ID (78522) from start command output ✓ Session ID displayed in header ✓ Session protocol displayed ✓ Connect script contents displayed TEST 23 (test_session_remove): session remove - remove stale, refuse active Database: /tmp/vpn-switch-test.12000/test_23 ✓ Stale session created for removal test ✓ Removal operation logged for stale session ✓ Active session (PID 12000) created for refusal test ✓ Refuses to remove active session (PID 12000) TEST 24 (test_session_save_default): session save - save current session as default Database: /tmp/vpn-switch-test.12000/test_24 ✓ Default session symlink created ✓ Default symlink points to correct session TEST 25 (test_session_save_named): session save work - save with custom name Database: /tmp/vpn-switch-test.12000/test_25 ✓ Named session symlink created ✓ Named symlink points to correct session TEST 26 (test_session_start_default): session start - resume default session Database: /tmp/vpn-switch-test.12000/test_26 ✓ Connect script created before stopping ✓ Session directory kept for resumption (referenced) ✓ Default symlink persists after stop ✓ Session start executed successfully TEST 27 (test_session_start_named): session start work - resume named session Database: /tmp/vpn-switch-test.12000/test_27 ✓ Named symlink persists after stop ✓ Named session start executed successfully TEST 28 (test_session_start_bypid): session start - resume session by PID Database: /tmp/vpn-switch-test.12000/test_28 ✓ Mock session (PID 11111) created for PID resume test ✓ Session start resumes by explicit PID (11111) TEST 29 (test_session_stop_named): session stop work - stop active named session Database: /tmp/vpn-switch-test.12000/test_29 ✓ Session stop resolves named session 'work' TEST 30 (test_session_stop_bypid): session stop - stop active session by PID Database: /tmp/vpn-switch-test.12000/test_30 ✓ Session stop handles PID (88888) TEST 31 (test_session_stop_inactive): session stop - inactive session should log (not error) Database: /tmp/vpn-switch-test.12000/test_31 ✓ Session stop handles inactive session gracefully TEST 32 (test_wireguard_remove_config_in_use): wireguard remove - refuse removal when config in use Database: /tmp/vpn-switch-test.12000/test_32 ✓ Active session (PID 12000) created using config ✓ Error message when config in use by session ✓ Error suggests removing session first TEST 33 (test_wireguard_remove_config_with_refs): wireguard remove - refuse removal when config has symlink refs Database: /tmp/vpn-switch-test.12000/test_33 ✓ Category symlink created (privacy/rm2) ✓ Error message when config has symlink references ✓ Error lists symlink references TEST 34 (test_wireguard_remove_symlink): wireguard remove - remove symlink (no safety checks) Database: /tmp/vpn-switch-test.12000/test_34 ✓ Test symlink created ✓ Symlink removal operation logged ✓ Symlink was removed TEST 35 (test_wireguard_remove_category_link): wireguard remove - remove link from category Database: /tmp/vpn-switch-test.12000/test_35 ✓ Category link (privacy/rm4) created ✓ Category link removal operation logged ✓ Category link was removed TEST 36 (test_wireguard_clean_no_broken): wireguard clean - no broken links found Database: /tmp/vpn-switch-test.12000/test_36 ✓ Clean header displayed ✓ No broken symlinks message displayed ✓ Usage hint displayed TEST 37 (test_wireguard_clean_broken_protocol_link): wireguard clean - detect and generate remove for broken protocol link Database: /tmp/vpn-switch-test.12000/test_37 ✓ Broken protocol symlink created for testing ✓ Remove command generated for broken protocol link ✓ Command includes link name TEST 38 (test_wireguard_clean_broken_category_link): wireguard clean - detect and generate remove for broken category link Database: /tmp/vpn-switch-test.12000/test_38 ✓ Broken category symlink created for testing ✓ Remove command generated for broken category link ✓ Command includes category name TEST 39 (test_wireguard_clean_category_no_broken): wireguard clean privacy - category with no broken links Database: /tmp/vpn-switch-test.12000/test_39 ✓ Category-specific header displayed ✓ No broken symlinks message for category TEST 40 (test_wireguard_clean_category_with_broken): wireguard clean privacy - category with broken links Database: /tmp/vpn-switch-test.12000/test_40 ✓ Broken symlink created in privacy category ✓ Remove command generated for category link ✓ Category-specific clean (not global) TEST 41 (test_wireguard_validate_broken_symlink): wireguard validate - detect broken symlinks Database: /tmp/vpn-switch-test.12000/test_41 ✓ Broken symlink created for validation test ✓ Broken symlink detected in protocol directory ✓ Error status reported TEST 42 (test_wireguard_validate_broken_category_symlink): wireguard validate - detect broken symlinks in categories Database: /tmp/vpn-switch-test.12000/test_42 ✓ Broken category symlink created for validation test ✓ Broken symlink detected in category TEST 43 (test_wireguard_validate_naming_conflict): wireguard validate - detect naming conflicts Database: /tmp/vpn-switch-test.12000/test_43 ✓ Naming conflict created (file + directory) ✓ Naming conflict detected TEST 44 (test_wireguard_validate_invalid_config): wireguard validate - detect invalid config files Database: /tmp/vpn-switch-test.12000/test_44 ✓ Empty config file created for validation test ✓ Empty config file detected ✓ Missing [Interface] section detected TEST 45 (test_stop_no_sessions): stop - no sessions exist (empty output) Database: /tmp/vpn-switch-test.12000/test_45 ✓ No output or log message when no sessions exist TEST 46 (test_stop_specific_interface): stop wg_test_safe - stop specific interface by name Database: /tmp/vpn-switch-test.12000/test_46 ✓ Active session (PID 12000, interface wg_test_safe) created ✓ Stopped specific interface wg_test_safe ✓ Interface wg_test_safe disconnect command generated TEST 47 (test_wireguard_disconnect_interface): wireguard disconnect wg_test_safe - direct disconnect command Database: /tmp/vpn-switch-test.12000/test_47 ✓ Active session (PID 12000) created for disconnect test ✓ Disconnect command executed for wg_test_safe ✓ Session PID displayed correctly TEST 48 (test_stop_nonexistent_interface): stop wg_test_other - error when interface not found Database: /tmp/vpn-switch-test.12000/test_48 ✓ Active session with wg_test_safe interface created ✓ Error message for nonexistent interface TEST 49 (test_disconnect_without_session): disconnect without session - error handling Database: /tmp/vpn-switch-test.12000/test_49 ✓ Error message when no session exists TEST 50 (test_stop_twice_idempotent): stop twice - idempotent (safe to call multiple times) Database: /tmp/vpn-switch-test.12000/test_50 ✓ First stop: handles no sessions gracefully ✓ Second stop: still handles no sessions (idempotent) TEST 51 (test_wireguard_import_nonexistent): wireguard import - error when file doesn't exist Database: /tmp/vpn-switch-test.12000/test_51 ✓ Error message for non-existent file TEST 52 (test_wireguard_import_duplicate): wireguard import - error when config already exists Database: /tmp/vpn-switch-test.12000/test_52 ✓ First import succeeded ✓ Error message when config already exists TEST 53 (test_wireguard_add_category_conflict): wireguard add - error when category already exists Database: /tmp/vpn-switch-test.12000/test_53 ✓ First add succeeded (privacy category created) ✓ Error message when category already exists TEST 54 (test_wireguard_add_link_conflict): wireguard add - error when link already exists Database: /tmp/vpn-switch-test.12000/test_54 ✓ First link created successfully ✓ Error message when link already exists TEST 55 (test_wireguard_link_conflict): wireguard link - error when alias already exists Database: /tmp/vpn-switch-test.12000/test_55 ✓ Config imported successfully ✓ Error message when alias already exists TEST 56 (test_error_invalid_category): error handling - invalid category shows error Database: /tmp/vpn-switch-test.12000/test_56 ✓ Error message for invalid category TEST 57 (test_error_broken_symlink): error handling - broken symlink handled gracefully Database: /tmp/vpn-switch-test.12000/test_57 ✓ Broken symlink created for testing ✓ Handled broken symlink (error or skipped) TEST 58 (test_error_invalid_command): error handling - invalid command shows usage Database: /tmp/vpn-switch-test.12000/test_58 ✓ Usage/help shown for invalid command TEST 59 (test_edge_duplicate_instance_prevention): edge case - prevent duplicate VPN instances Database: /tmp/vpn-switch-test.12000/test_59 ✓ First VPN session created (PID 12000) ✓ Detected existing VPN instance ✓ No duplicate session created TEST 60 (test_edge_stale_session_cleanup): edge case - stale sessions don't block new sessions Database: /tmp/vpn-switch-test.12000/test_60 ✓ Stale session created for testing ✓ Proceeded with new session (stale session didn't block) ✓ Stale session preserved (manual cleanup via 'session clean' required) TEST 61 (test_wireguard_patch_valid): wireguard patch - displays patched configuration Database: /tmp/vpn-switch-test.12000/test_61 ✓ Patch output correctly strips PostUp hook (phase-based DNS) ✓ Patch output correctly strips PostDown hook (phase-based DNS) ✓ Patch output preserves [Interface] section ✓ Patch output preserves [Peer] section TEST 62 (test_wireguard_patch_nonexistent): wireguard patch - handles nonexistent config Database: /tmp/vpn-switch-test.12000/test_62 ✓ Patch rejects nonexistent config with error TEST 63 (test_wireguard_patch_absolute): wireguard patch - handles absolute path Database: /tmp/vpn-switch-test.12000/test_63 ✓ Patch works with absolute path (strips DNS hooks) TEST 64 (test_wireguard_info_category): wireguard info - displays category information Database: /tmp/vpn-switch-test.12000/test_64 ✓ Category header displayed ✓ Config count displayed ✓ Link count displayed ✓ Category path displayed ✓ Contents section header displayed ✓ Category contents listed with symlink arrows TEST 65 (test_session_save_default): session save - save current session as default Database: /tmp/vpn-switch-test.12000/test_65 ✓ Default session symlink created ✓ Default symlink points to correct session TEST 66 (test_session_save_named): session save work - save with custom name Database: /tmp/vpn-switch-test.12000/test_66 ✓ Named session symlink created ✓ Named symlink points to correct session TEST 67 (test_session_start_default): session start - resume default session Database: /tmp/vpn-switch-test.12000/test_67 ✓ Connect script created before stopping ✓ Session directory kept for resumption (referenced) ✓ Default symlink persists after stop ✓ Session start executed successfully TEST 68 (test_session_start_named): session start work - resume named session Database: /tmp/vpn-switch-test.12000/test_68 ✓ Named symlink persists after stop ✓ Named session start executed successfully TEST 69 (test_session_start_by_pid): session start - resume by PID Database: /tmp/vpn-switch-test.12000/test_69 ✓ Session start by PID executed successfully TEST 70 (test_openvpn_import_valid): openvpn import - import valid .ovpn config Database: /tmp/vpn-switch-test.12000/test_70 ✓ Config imported to openvpn/ ✓ Permissions set to 0400 TEST 71 (test_openvpn_list): openvpn list - list configs and groups Database: /tmp/vpn-switch-test.12000/test_71 ✓ Lists config: us-server.ovpn ✓ Lists group: work/ ✓ Lists group link with arity-1: work/office TEST 72 (test_openvpn_add_group): openvpn add - create group Database: /tmp/vpn-switch-test.12000/test_72 ✓ Group directory created ✓ Group permissions correct (0700) TEST 73 (test_openvpn_link): openvpn link - create protocol-level link Database: /tmp/vpn-switch-test.12000/test_73 ✓ Protocol-level link created ✓ Link target correct TEST 74 (test_openvpn_remove): openvpn remove - remove config safely Database: /tmp/vpn-switch-test.12000/test_74 ✓ Config removed ✓ Other config preserved TEST 75 (test_openvpn_validate): openvpn validate - detect broken links Database: /tmp/vpn-switch-test.12000/test_75 ✓ Broken symlink detected ✓ Valid database passes validation TEST 76 (test_openvpn_info): openvpn info - show group information Database: /tmp/vpn-switch-test.12000/test_76 ✓ Shows group name ✓ Shows correct link count ✓ Shows link: office TEST 77 (test_openvpn_dump): openvpn dump - export database Database: /tmp/vpn-switch-test.12000/test_77 ✓ Dump includes import command ✓ Dump includes group creation ✓ Dump includes protocol link ✓ Dump includes group link TEST 78 (test_openvpn_patch_valid): openvpn patch - displays patched configuration Database: /tmp/vpn-switch-test.12000/test_78 ✓ Patch output correctly strips up script (phase-based DNS) ✓ Patch output correctly strips down script (phase-based DNS) ✓ Patch output contains daemon mode ✓ Patch output contains device interface ✓ Patch output contains writepid directive ✓ Patch output preserves client directive ✓ Patch output preserves remote server TEST 79 (test_openvpn_patch_nonexistent): openvpn patch - handles nonexistent config Database: /tmp/vpn-switch-test.12000/test_79 ✓ Error message for nonexistent config TEST 80 (test_openvpn_patch_absolute): openvpn patch - handles absolute path Database: /tmp/vpn-switch-test.12000/test_80 ✓ Absolute path patch works TEST 81 (test_openvpn_patch_credentials_bare): openvpn patch - patches bare auth-user-pass with credentials Database: /tmp/vpn-switch-test.12000/test_81 ✓ Bare auth-user-pass patched with credentials path ✓ Bare auth-user-pass preserved when no credentials set TEST 82 (test_openvpn_patch_credentials_existing): openvpn patch - preserves existing auth-user-pass path Database: /tmp/vpn-switch-test.12000/test_82 ✓ Existing auth-user-pass path preserved (not overridden) TEST 83 (test_openvpn_patch_credentials_missing): openvpn patch - handles config without auth-user-pass Database: /tmp/vpn-switch-test.12000/test_83 ✓ Config without auth-user-pass remains unchanged TEST 84 (test_openvpn_start_basic): openvpn start - create session and connect to VPN Database: /tmp/vpn-switch-test.12000/test_84 ✓ Session creation logged ✓ openvpn command in connect.sh ✓ Session directory created in .session/ ✓ Session metadata files created ✓ connect.sh script generated ✓ connect.sh is executable ✓ Patched config (tun_test80.ovpn) created ✓ Patched config contains daemon mode ✓ Patched config correctly strips up script (phase-based DNS) ✓ Patched config correctly strips down script (phase-based DNS) TEST 85 (test_openvpn_stop_basic): openvpn stop - cleanup commands for session Database: /tmp/vpn-switch-test.12000/test_85 ✓ Session created via user interface ✓ Disconnect commands reference correct interface (tun_test85) ✓ Disconnect generates process kill commands TEST 86 (test_openvpn_disconnect_interface): openvpn disconnect - tear down OpenVPN interface Database: /tmp/vpn-switch-test.12000/test_86 ✓ Disconnect generates process termination commands TEST 87 (test_openvpn_clean): openvpn clean - generate cleanup commands for broken links Database: /tmp/vpn-switch-test.12000/test_87 ✓ Clean generates remove commands ✓ Clean detected broken symlink TEST 88 (test_protocol_agnostic_import_wireguard): import (protocol-agnostic) - detects WireGuard .conf file Database: /tmp/vpn-switch-test.12000/test_88 ✓ Protocol-agnostic import detected .conf and delegated to wireguard import ✓ Protocol-agnostic import generates correct cp command TEST 89 (test_protocol_agnostic_list): list (protocol-agnostic) - delegates to all protocols Database: /tmp/vpn-switch-test.12000/test_89 ✓ Protocol-agnostic list delegated to wireguard list ✓ Protocol-agnostic list shows wireguard config sections ✓ Protocol-agnostic list has no duplicate lines (3 unique) TEST 90 (test_protocol_agnostic_link): link (protocol-agnostic) - creates protocol-level alias Database: /tmp/vpn-switch-test.12000/test_90 ✓ Protocol-agnostic link generates ln command ✓ Protocol-agnostic link uses correct relative path (./wireguard) ✓ Protocol-agnostic link includes correct alias name TEST 91 (test_protocol_agnostic_remove): remove (protocol-agnostic) - removes protocol-level link Database: /tmp/vpn-switch-test.12000/test_91 ✓ Protocol-agnostic remove generates rm command ✓ Protocol-agnostic remove includes descriptive comment ✓ Protocol-agnostic remove errors on non-existent link TEST 92 (test_protocol_agnostic_validate): validate (protocol-agnostic) - delegates to all protocols Database: /tmp/vpn-switch-test.12000/test_92 ✓ Protocol-agnostic validate delegated to wireguard validate ✓ Protocol-agnostic validate shows validation output TEST 93 (test_network_validate): network validate - check network prerequisites Database: /tmp/vpn-switch-test.12000/test_93 ✓ Network validation header displayed ✓ Network validate passed on clean configuration TEST 94 (test_permissions_validate): permissions validate - check filesystem permissions Database: /tmp/vpn-switch-test.12000/test_94 ✓ Permissions validation header displayed ✓ Permissions validate passed on clean configuration TEST 95 (test_environment_validate): environment validate - check environment variables Database: /tmp/vpn-switch-test.12000/test_95 ✓ Environment validation header displayed ✓ Environment validate passed on clean configuration TEST 96 (test_batch_validate_includes_system): validate (batch) - includes system validators Database: /tmp/vpn-switch-test.12000/test_96 ✓ Batch validate includes database validator ✓ Batch validate includes binaries validator ✓ Batch validate includes phases validator ✓ Batch validate includes network validator ✓ Batch validate includes permissions validator ✓ Batch validate includes environment validator TEST 97 (test_start_wireguard_only): start - auto-detect WireGuard config Database: /tmp/vpn-switch-test.12000/test_97 ✓ Delegates to wireguard commands for WireGuard-only config TEST 98 (test_start_openvpn_only): start - auto-detect OpenVPN config Database: /tmp/vpn-switch-test.12000/test_98 ✓ Delegates to openvpn commands for OpenVPN-only config TEST 99 (test_start_not_found): start - error on nonexistent config Database: /tmp/vpn-switch-test.12000/test_99 ✓ Error message for nonexistent config ✓ Error shows both search locations TEST 100 (test_start_no_default): start - error when no configs exist (Phase 3.4.1) Database: /tmp/vpn-switch-test.12000/test_100 ✓ Error message when no configs available ✓ Error provides hint to import configs TEST 101 (test_start_with_default_wireguard): start - use default link (WireGuard) via API Database: /tmp/vpn-switch-test.12000/test_101 ✓ Default session link created via API ✓ Start with no args resolves to default session TEST 102 (test_start_with_default_openvpn): start - use default link (OpenVPN) via API Database: /tmp/vpn-switch-test.12000/test_102 ✓ Default session link created via API ✓ Start with no args resolves to default session TEST 103 (test_start_default_invalid_target): start - error on invalid default link target Database: /tmp/vpn-switch-test.12000/test_103 ✓ Error detected for invalid default session target TEST 104 (test_init_extension_links): init - creates protocol extension links (Phase 3.4.1) Database: /tmp/vpn-switch-test.12000/test_104 ✓ conf link created ✓ ovpn link created ✓ conf → wireguard ✓ ovpn → openvpn TEST 105 (test_start_extension_link_fast_path): start - uses extension link for protocol resolution (Phase 3.4.1) Database: /tmp/vpn-switch-test.12000/test_105 ✓ Extension link used for fast protocol resolution (wireguard commands found) TEST 106 (test_start_multiple_matches): start - error on multiple protocol matches (Phase 3.4.1) Database: /tmp/vpn-switch-test.12000/test_106 ✓ Multiple matches error shown ✓ Both matches listed TEST 107 (test_database_init): database init - creates directory structure (Phase 4.4) Database: /tmp/vpn-switch-test.12000/test_107 ✓ wireguard/ created ✓ openvpn/ created ✓ .session/ created ✓ session/ created ✓ .env/default/ created ✓ .env/local/ created ✓ .include/phase/ created TEST 108 (test_environment_init): environment init - copies profile templates (Phase 4.4) Database: /tmp/vpn-switch-test.12000/test_108 ✓ minimal profile copied ✓ profile has correct permissions (0600) TEST 109 (test_phases_copy): phases copy - copies phase templates (Phase 4.4) Database: /tmp/vpn-switch-test.12000/test_109 ✓ wireguard phases copied ✓ openvpn phases copied ✓ wireguard phase subdirs exist TEST 110 (test_phases_lift): phases lift - lifts phase:backend templates (Phase 4.4) Database: /tmp/vpn-switch-test.12000/test_110 ✓ generates lift command ✓ output file is executable TEST 111 (test_phases_sync_single): phases sync - discovers and lifts backends (Phase 4.4) Database: /tmp/vpn-switch-test.12000/test_111 ✓ delegates to phases lift TEST 112 (test_phases_sync_all): phases sync - syncs all phases (Phase 4.4) Database: /tmp/vpn-switch-test.12000/test_112 ✓ delegates to single-phase sync TEST 113 (test_init_batch_combinator): init - orchestrates full initialization (Phase 4.4) Database: /tmp/vpn-switch-test.12000/test_113 ✓ database init executed ✓ environment init executed ✓ phases copy executed TEST 114 (test_init_combinator): init combinator - delegates to batch combinator (Phase 4.4) Database: /tmp/vpn-switch-test.12000/test_114 ✓ database created ✓ profile installed TEST 115 (test_setenv_basic): setenv - basic variable setting Database: /tmp/vpn-switch-test.12000/test_115 ✓ .env/local directory created ✓ Variable file created ✓ Variable has correct value ✓ File has correct permissions (0600 or 0640 for cross-user support) ✓ Shows confirmation message TEST 116 (test_setenv_invalid_name): setenv - invalid variable name Database: /tmp/vpn-switch-test.12000/test_116 ✓ Rejects invalid variable name ✓ No file created for invalid name TEST 117 (test_getenv_local_override): getenv - shows local override Database: /tmp/vpn-switch-test.12000/test_117 ✓ Shows local override source ✓ Outputs correct value from local TEST 118 (test_getenv_fallback_chain): getenv - fallback chain (local > default > template) Database: /tmp/vpn-switch-test.12000/test_118 ✓ Shows error if variable not found ✓ Falls back to .env/default ✓ Falls back to template/environment TEST 119 (test_unsetenv_existing): unsetenv - remove existing variable Database: /tmp/vpn-switch-test.12000/test_119 ✓ Variable file was removed ✓ Shows confirmation message TEST 120 (test_unsetenv_not_set): unsetenv - variable not set in local Database: /tmp/vpn-switch-test.12000/test_120 ✓ Shows informative message when not set TEST 121 (test_dumpenv_prologue): dumpenv prologue - outputs safe minimal set Database: /tmp/vpn-switch-test.12000/test_121 ✓ Prologue includes VPN_SWITCH_TERMINAL_INTERPRETER ✓ Prologue includes VPN_SWITCH_DISPLAY_ANSI ✓ Prologue excludes VPN_SWITCH_INTERPRETER_wireguard_list (epilogue-only) ✓ Prologue excludes VPN_SWITCH_INTERPRETER_wireguard_import1 (epilogue-only) TEST 122 (test_dumpenv_epilogue): dumpenv epilogue - outputs complete set Database: /tmp/vpn-switch-test.12000/test_122 ✓ Epilogue includes VPN_SWITCH_TERMINAL_INTERPRETER ✓ Epilogue includes VPN_SWITCH_DISPLAY_ANSI ✓ Epilogue includes VPN_SWITCH_INTERPRETER_wireguard_list ✓ Epilogue includes VPN_SWITCH_INTERPRETER_wireguard_import1 TEST 123 (test_dumpenv_profile_filtering): dumpenv - profile filtering prevents restore breakage Database: /tmp/vpn-switch-test.12000/test_123 ✓ Prologue correctly excludes function-specific interpreter ✓ Epilogue correctly includes function-specific interpreter TEST 124 (test_environment_cache_on): environment cache on - creates cache file with correct permissions Database: /tmp/vpn-switch-test.12000/test_124 ✓ Cache file created ✓ Cache file has correct permissions (0600) ✓ Shows cache enabled message ✓ Cache file has content TEST 125 (test_environment_cache_off): environment cache off - removes cache file Database: /tmp/vpn-switch-test.12000/test_125 ✓ Cache file removed ✓ Shows cache disabled message TEST 126 (test_environment_cache_status): environment cache status - shows correct status Database: /tmp/vpn-switch-test.12000/test_126 ✓ Shows DISABLED status when cache off ✓ Shows ENABLED status when cache on ✓ Shows cached variable count TEST 127 (test_environment_cache_no_args): environment cache (no args) - defaults to status Database: /tmp/vpn-switch-test.12000/test_127 ✓ Shows status with no arguments TEST 128 (test_cache_invalidation_setenv): setenv - rebuilds cache automatically Database: /tmp/vpn-switch-test.12000/test_128 ✓ Cache rebuilt automatically after setenv ✓ Rebuilt cache contains new variable TEST_VAR TEST 129 (test_cache_invalidation_unsetenv): unsetenv - rebuilds cache automatically Database: /tmp/vpn-switch-test.12000/test_129 ✓ Cache rebuilt automatically after unsetenv ✓ Rebuilt cache no longer contains TEST_VAR TEST 130 (test_cache_invalidation_environment_init): environment init - invalidates cache automatically Database: /tmp/vpn-switch-test.12000/test_130 ✓ Cache file removed after environment init ✓ Shows cache invalidation warning TEST 131 (test_dumpenv_cache_preservation): dumpenv epilogue - includes cache if enabled Database: /tmp/vpn-switch-test.12000/test_131 ✓ Epilogue includes cache content ✓ Epilogue includes cache restore comment TEST 132 (test_dumpenv_cache_not_included_when_disabled): dumpenv epilogue - excludes cache when disabled Database: /tmp/vpn-switch-test.12000/test_132 ✓ Epilogue correctly excludes cache when disabled TEST 133 (test_cache_no_recursion): environment cache on - excludes cache file from scan Database: /tmp/vpn-switch-test.12000/test_133 ✓ Cache correctly excludes itself TEST 134 (test_interpreter_single_underscore): interpreter resolution - single underscore uses TERMINAL_INTERPRETER Database: /tmp/vpn-switch-test.12000/test_134 # Set VPN_SWITCH_TERMINAL_INTERPRETER (effective next command) ✓ Single underscore function used TERMINAL_INTERPRETER TEST 135 (test_interpreter_double_underscore): interpreter resolution - double underscore uses COMBINATOR_INTERPRETER Database: /tmp/vpn-switch-test.12000/test_135 # Set VPN_SWITCH_COMBINATOR_INTERPRETER (effective next command) ✓ Double underscore function used COMBINATOR_INTERPRETER TEST 136 (test_interpreter_triple_underscore): interpreter resolution - triple underscore uses BATCH_COMBINATOR_INTERPRETER Database: /tmp/vpn-switch-test.12000/test_136 # Set VPN_SWITCH_BATCH_COMBINATOR_INTERPRETER (effective next command) ✓ Triple underscore function used BATCH_COMBINATOR_INTERPRETER TEST 137 (test_interpreter_resolution_priority): interpreter resolution - function-specific override beats intrinsic classification Database: /tmp/vpn-switch-test.12000/test_137 # Set VPN_SWITCH_TERMINAL_INTERPRETER (effective next command) ✓ Function-specific override takes priority over intrinsic classification ✓ Intrinsic classification was correctly bypassed TEST 138 (test_inspect_batch_complete): inspect (batch) - includes all inspection sections Database: /tmp/vpn-switch-test.12000/test_138 ✓ Batch inspect includes environment section ✓ Batch inspect includes system section ✓ Batch inspect includes WireGuard section ✓ Batch inspect includes OpenVPN section ✓ Batch inspect includes session section ✓ Batch inspect includes phases section TEST 139 (test_environment_inspect): environment inspect - displays environment variables Database: /tmp/vpn-switch-test.12000/test_139 ✓ Environment inspect shows header ✓ Environment inspect shows VPN_SWITCH_BASE ✓ Environment inspect shows database structure TEST 140 (test_system_inspect): system inspect - displays system configuration Database: /tmp/vpn-switch-test.12000/test_140 ✓ System inspect shows header ✓ System inspect shows system info section ✓ System inspect shows network interfaces section TEST 141 (test_batch_syntax_wireguard_clean): wireguard clean - validates batch syntax Database: /tmp/vpn-switch-test.12000/test_141 ✓ wireguard clean outputs valid batch syntax ✓ wireguard clean uses literal $VPN_SWITCH_CONTEXT_SCRIPT TEST 142 (test_combinators_literal_variable): combinators - use literal $VPN_SWITCH_CONTEXT_SCRIPT Database: /tmp/vpn-switch-test.12000/test_142 ✓ wireguard start uses literal variable ✓ wireguard start variable not expanded TEST 143 (test_combinator_syntax_validation): combinators - validate single-command output syntax Database: /tmp/vpn-switch-test.12000/test_143 ✓ wireguard start outputs exactly one command ✓ wireguard start uses literal variable ✓ wireguard start variable not expanded ✓ openvpn start outputs exactly one command ✓ start (protocol-agnostic) outputs exactly one command TEST 144 (test_function_classification_correct): function classification - naming matches behavior ✓ wireguard add2 correctly classified as combinator (__) ✓ wireguard clean0 correctly classified as batch (___) ✓ openvpn clean0 correctly classified as batch (___) TEST 145 (test_no_terminal_output_vpnswitch_commands): terminal functions - must not output vpn-switch commands ✓ No terminal functions output vpn-switch commands TEST 146 (test_metadata_function_lists): metadata - function lists accurate after renames ✓ Metadata includes __wireguard_add2 in combinators ✓ Metadata includes ___wireguard_clean0 in batch combinators ✓ Metadata includes ___openvpn_clean0 in batch combinators ======================================== Test Summary ======================================== Test Functions: 146 Total Assertions: 371 Passed Assertions: 371 Failed Assertions: 0 ALL TESTS PASSED ======================================== vpn-switch Architecture Test Suite ======================================== Testing architectural rules for combinator functions Profile: all Running Combinator Tests ======================================== Found 28 combinator functions TEST 1: Combinator: __session_exists1 - validate syntax with variations ✓ __session_exists1: Valid combinator syntax (all variations) TEST 2: Combinator: __session_conflicts2 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-1] ✓ __session_conflicts2: Valid combinator syntax (all variations) TEST 3: Combinator: __interface_check1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-2] ✓ __interface_check1: Valid combinator syntax (all variations) TEST 4: Combinator: __stop1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-3] ✓ __stop1: Valid combinator syntax (all variations) TEST 5: Combinator: __import1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-4] ✓ __import1: Valid combinator syntax (all variations) TEST 6: Combinator: __start1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-5] ✓ __start1: Valid combinator syntax (all variations) TEST 7: Combinator: __start0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-6] ✓ __start0: Valid combinator syntax (all variations) TEST 8: Combinator: __bootstrap1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-7] ✓ __bootstrap1: Valid combinator syntax (all variations) TEST 9: Combinator: __environment_cache0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-8] ✓ __environment_cache0: Valid combinator syntax (all variations) TEST 10: Combinator: __phases_lift1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-9] ✓ __phases_lift1: Valid combinator syntax (all variations) TEST 11: Combinator: __init0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-10] ✓ __init0: Valid combinator syntax (all variations) TEST 12: Combinator: __batch1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-11] ✓ __batch1: Valid combinator syntax (all variations) TEST 13: Combinator: __restore1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-12] ✓ __restore1: Valid combinator syntax (all variations) TEST 14: Combinator: __openvpn_start0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-13] ✓ __openvpn_start0: Valid combinator syntax (all variations) TEST 15: Combinator: __openvpn_start1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-14] ✓ __openvpn_start1: Valid combinator syntax (all variations) TEST 16: Combinator: __openvpn_stop1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-15] ✓ __openvpn_stop1: Valid combinator syntax (all variations) TEST 17: Combinator: __openvpn_add2 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-16] ✓ __openvpn_add2: Valid combinator syntax (all variations) TEST 18: Combinator: __openvpn_help0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-17] ✓ __openvpn_help0: Valid combinator syntax (all variations) TEST 19: Combinator: __session_disconnect1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-18] ✓ __session_disconnect1: Valid combinator syntax (all variations) TEST 20: Combinator: __session_show0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-19] ✓ __session_show0: Valid combinator syntax (all variations) TEST 21: Combinator: __session_start0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-20] ✓ __session_start0: Valid combinator syntax (all variations) TEST 22: Combinator: __session_start1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-21] ✓ __session_start1: Valid combinator syntax (all variations) TEST 23: Combinator: __session_help0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-22] ✓ __session_help0: Valid combinator syntax (all variations) TEST 24: Combinator: __wireguard_start0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-23] ✓ __wireguard_start0: Valid combinator syntax (all variations) TEST 25: Combinator: __wireguard_start1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-24] ✓ __wireguard_start1: Valid combinator syntax (all variations) TEST 26: Combinator: __wireguard_stop1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-25] ✓ __wireguard_stop1: Valid combinator syntax (all variations) TEST 27: Combinator: __wireguard_add2 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-26] ✓ __wireguard_add2: Valid combinator syntax (all variations) TEST 28: Combinator: __wireguard_help0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-27] ✓ __wireguard_help0: Valid combinator syntax (all variations) Running Batch Combinator Tests ======================================== Found 26 batch combinator functions TEST 29: Batch Combinator: ___session_prepare3 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-28] ✓ ___session_prepare3: Valid batch combinator syntax (all variations) TEST 30: Batch Combinator: ___stop0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-29] ✓ ___stop0: Valid batch combinator syntax (all variations) TEST 31: Batch Combinator: ___phases_sync1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-30] ✓ ___phases_sync1: Valid batch combinator syntax (all variations) TEST 32: Batch Combinator: ___phases_sync0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-31] ✓ ___phases_sync0: Valid batch combinator syntax (all variations) TEST 33: Batch Combinator: ___list0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-32] ✓ ___list0: Valid batch combinator syntax (all variations) TEST 34: Batch Combinator: ___bootstrap2 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-33] ✓ ___bootstrap2: Valid batch combinator syntax (all variations) TEST 35: Batch Combinator: ___init1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-34] ✓ ___init1: Valid batch combinator syntax (all variations) TEST 36: Batch Combinator: ___dumpenv1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-35] ✓ ___dumpenv1: Valid batch combinator syntax (all variations) TEST 37: Batch Combinator: ___dump0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-36] ✓ ___dump0: Valid batch combinator syntax (all variations) TEST 38: Batch Combinator: ___batch0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-37] ✓ ___batch0: Valid batch combinator syntax (all variations) TEST 39: Batch Combinator: ___environment_inspect0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-38] ✓ ___environment_inspect0: Valid batch combinator syntax (all variations) TEST 40: Batch Combinator: ___inspect0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-39] ✓ ___inspect0: Valid batch combinator syntax (all variations) TEST 41: Batch Combinator: ___openvpn_create1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-40] ✓ ___openvpn_create1: Valid batch combinator syntax (all variations) TEST 42: Batch Combinator: ___openvpn_stop0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-41] ✓ ___openvpn_stop0: Valid batch combinator syntax (all variations) TEST 43: Batch Combinator: ___openvpn_inspect0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-42] ✓ ___openvpn_inspect0: Valid batch combinator syntax (all variations) TEST 44: Batch Combinator: ___openvpn_clean0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-43] ✓ ___openvpn_clean0: Valid batch combinator syntax (all variations) TEST 45: Batch Combinator: ___openvpn_dump0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-44] ✓ ___openvpn_dump0: Valid batch combinator syntax (all variations) TEST 46: Batch Combinator: ___session_dump0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-45] ✓ ___session_dump0: Valid batch combinator syntax (all variations) TEST 47: Batch Combinator: ___session_inspect0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-46] ✓ ___session_inspect0: Valid batch combinator syntax (all variations) TEST 48: Batch Combinator: ___validate0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-47] ✓ ___validate0: Valid batch combinator syntax (all variations) TEST 49: Batch Combinator: ___wireguard_create1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-48] ✓ ___wireguard_create1: Valid batch combinator syntax (all variations) TEST 50: Batch Combinator: ___wireguard_inspect0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-49] ✓ ___wireguard_inspect0: Valid batch combinator syntax (all variations) TEST 51: Batch Combinator: ___wireguard_stop0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-50] ✓ ___wireguard_stop0: Valid batch combinator syntax (all variations) TEST 52: Batch Combinator: ___wireguard_clean0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-51] ✓ ___wireguard_clean0: Valid batch combinator syntax (all variations) TEST 53: Batch Combinator: ___wireguard_clean1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-52] ✓ ___wireguard_clean1: Valid batch combinator syntax (all variations) TEST 54: Batch Combinator: ___wireguard_dump0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.483595/test-53] ✓ ___wireguard_dump0: Valid batch combinator syntax (all variations) Running Terminal Function Tests ======================================== Found 83 terminal functions TEST 55: Terminal: _session_create1 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-54] ✓ _session_create1: Valid terminal function output (all variations) TEST 56: Terminal: _interface_destroy1 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-55] ✓ _interface_destroy1: Valid terminal function output (all variations) TEST 57: Terminal: _session_populate3 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-56] ✓ _session_populate3: Valid terminal function output (all variations) TEST 58: Terminal: _phases_copy0 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-57] ✓ _phases_copy0: Valid terminal function output (all variations) TEST 59: Terminal: _link2 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-58] ✓ _link2: Valid terminal function output (all variations) TEST 60: Terminal: _remove1 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-59] ✓ _remove1: Valid terminal function output (all variations) TEST 61: Terminal: _error1 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-60] ✓ _error1: Valid terminal function output (all variations) TEST 62: Terminal: _error2 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-61] ✓ _error2: Valid terminal function output (all variations) TEST 63: Terminal: _error3 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-62] ✓ _error3: Valid terminal function output (all variations) TEST 64: Terminal: _fail2 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-63] ✓ _fail2: Valid terminal function output (all variations) TEST 65: Terminal: _log1 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-64] ✓ _log1: Valid terminal function output (all variations) TEST 66: Terminal: _log2 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-65] ✓ _log2: Valid terminal function output (all variations) TEST 67: Terminal: _log3 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-66] ✓ _log3: Valid terminal function output (all variations) TEST 68: Terminal: _lift1 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-67] ✓ _lift1: Valid terminal function output (all variations) TEST 69: Terminal: _database_init0 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-68] ✓ _database_init0: Valid terminal function output (all variations) TEST 70: Terminal: _environment_init1 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-69] ✓ _environment_init1: Valid terminal function output (all variations) TEST 71: Terminal: _environment_cache1 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-70] ✓ _environment_cache1: Valid terminal function output (all variations) TEST 72: Terminal: _lift3 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-71] ✓ _lift3: Valid terminal function output (all variations) TEST 73: Terminal: _setenv2 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-72] ✓ _setenv2: Valid terminal function output (all variations) TEST 74: Terminal: _getenv1 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-73] ✓ _getenv1: Valid terminal function output (all variations) TEST 75: Terminal: _unsetenv1 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-74] ✓ _unsetenv1: Valid terminal function output (all variations) Skipped: _cat1 (requires special setup) TEST 76: Terminal: _batch2 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-75] ✓ _batch2: Valid terminal function output (all variations) TEST 77: Terminal: _printenv0 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-76] ✓ _printenv0: Valid terminal function output (all variations) TEST 78: Terminal: _status0 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-77] ✓ _status0: Valid terminal function output (all variations) TEST 79: Terminal: _help0 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-78] ✓ _help0: Valid terminal function output (all variations) TEST 80: Terminal: _help1 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-79] ✓ _help1: Valid terminal function output (all variations) TEST 81: Terminal: _database_enumerate0 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-80] ✓ _database_enumerate0: Valid terminal function output (all variations) TEST 82: Terminal: _system_inspect0 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-81] ✓ _system_inspect0: Valid terminal function output (all variations) TEST 83: Terminal: _logs_inspect0 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-82] ✓ _logs_inspect0: Valid terminal function output (all variations) TEST 84: Terminal: _phases_inspect0 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-83] ✓ _phases_inspect0: Valid terminal function output (all variations) TEST 85: Terminal: _summary_inspect0 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-84] ✓ _summary_inspect0: Valid terminal function output (all variations) TEST 86: Terminal: _prologue_inspect0 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-85] ✓ _prologue_inspect0: Valid terminal function output (all variations) TEST 87: Terminal: _openvpn_patch2 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-86] ✓ _openvpn_patch2: Valid terminal function output (all variations) TEST 88: Terminal: _openvpn_configure1 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-87] ✓ _openvpn_configure1: Valid terminal function output (all variations) TEST 89: Terminal: _openvpn_connect1 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-88] ✓ _openvpn_connect1: Valid terminal function output (all variations) TEST 90: Terminal: _openvpn_disconnect1 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-89] ✓ _openvpn_disconnect1: Valid terminal function output (all variations) TEST 91: Terminal: _openvpn_patch1 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-90] ✓ _openvpn_patch1: Valid terminal function output (all variations) TEST 92: Terminal: _openvpn_enumerate0 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-91] ✓ _openvpn_enumerate0: Valid terminal function output (all variations) TEST 93: Terminal: _openvpn_import1 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-92] ✓ _openvpn_import1: Valid terminal function output (all variations) TEST 94: Terminal: _openvpn_list0 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-93] ✓ _openvpn_list0: Valid terminal function output (all variations) TEST 95: Terminal: _openvpn_list1 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-94] ✓ _openvpn_list1: Valid terminal function output (all variations) TEST 96: Terminal: _openvpn_add1 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-95] ✓ _openvpn_add1: Valid terminal function output (all variations) TEST 97: Terminal: _openvpn_add3 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-96] ✓ _openvpn_add3: Valid terminal function output (all variations) TEST 98: Terminal: _openvpn_link2 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-97] ✓ _openvpn_link2: Valid terminal function output (all variations) TEST 99: Terminal: _openvpn_remove1 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-98] ✓ _openvpn_remove1: Valid terminal function output (all variations) TEST 100: Terminal: _openvpn_remove2 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-99] ✓ _openvpn_remove2: Valid terminal function output (all variations) TEST 101: Terminal: _openvpn_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-100] ✓ _openvpn_validate0: Valid terminal function output (all variations) TEST 102: Terminal: _openvpn_info1 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-101] ✓ _openvpn_info1: Valid terminal function output (all variations) TEST 103: Terminal: _session_list0 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-102] ✓ _session_list0: Valid terminal function output (all variations) TEST 104: Terminal: _session_show1 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-103] ✓ _session_show1: Valid terminal function output (all variations) TEST 105: Terminal: _session_remove1 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-104] ✓ _session_remove1: Valid terminal function output (all variations) TEST 106: Terminal: _session_connect1 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-105] ✓ _session_connect1: Valid terminal function output (all variations) TEST 107: Terminal: _session_save0 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-106] ✓ _session_save0: Valid terminal function output (all variations) TEST 108: Terminal: _session_save1 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-107] ✓ _session_save1: Valid terminal function output (all variations) TEST 109: Terminal: _session_clean0 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-108] ✓ _session_clean0: Valid terminal function output (all variations) TEST 110: Terminal: _session_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-109] ✓ _session_validate0: Valid terminal function output (all variations) TEST 111: Terminal: _session_enumerate0 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-110] ✓ _session_enumerate0: Valid terminal function output (all variations) TEST 112: Terminal: _session_describe0 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-111] ✓ _session_describe0: Valid terminal function output (all variations) TEST 113: Terminal: _logs_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-112] ✓ _logs_validate0: Valid terminal function output (all variations) TEST 114: Terminal: _logs_clean0 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-113] ✓ _logs_clean0: Valid terminal function output (all variations) TEST 115: Terminal: _phases_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-114] ✓ _phases_validate0: Valid terminal function output (all variations) TEST 116: Terminal: _database_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-115] ✓ _database_validate0: Valid terminal function output (all variations) TEST 117: Terminal: _binaries_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-116] ✓ _binaries_validate0: Valid terminal function output (all variations) TEST 118: Terminal: _network_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-117] ✓ _network_validate0: Valid terminal function output (all variations) TEST 119: Terminal: _permissions_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-118] ✓ _permissions_validate0: Valid terminal function output (all variations) TEST 120: Terminal: _environment_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-119] ✓ _environment_validate0: Valid terminal function output (all variations) TEST 121: Terminal: _wireguard_patch2 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-120] ✓ _wireguard_patch2: Valid terminal function output (all variations) TEST 122: Terminal: _wireguard_configure1 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-121] ✓ _wireguard_configure1: Valid terminal function output (all variations) TEST 123: Terminal: _wireguard_connect1 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-122] ✓ _wireguard_connect1: Valid terminal function output (all variations) TEST 124: Terminal: _wireguard_disconnect1 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-123] ✓ _wireguard_disconnect1: Valid terminal function output (all variations) TEST 125: Terminal: _wireguard_enumerate0 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-124] ✓ _wireguard_enumerate0: Valid terminal function output (all variations) TEST 126: Terminal: _wireguard_import1 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-125] ✓ _wireguard_import1: Valid terminal function output (all variations) TEST 127: Terminal: _wireguard_list0 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-126] ✓ _wireguard_list0: Valid terminal function output (all variations) TEST 128: Terminal: _wireguard_list1 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-127] ✓ _wireguard_list1: Valid terminal function output (all variations) TEST 129: Terminal: _wireguard_add1 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-128] ✓ _wireguard_add1: Valid terminal function output (all variations) TEST 130: Terminal: _wireguard_add3 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-129] ✓ _wireguard_add3: Valid terminal function output (all variations) TEST 131: Terminal: _wireguard_link2 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-130] ✓ _wireguard_link2: Valid terminal function output (all variations) TEST 132: Terminal: _wireguard_remove1 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-131] ✓ _wireguard_remove1: Valid terminal function output (all variations) TEST 133: Terminal: _wireguard_remove2 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-132] ✓ _wireguard_remove2: Valid terminal function output (all variations) TEST 134: Terminal: _wireguard_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-133] ✓ _wireguard_validate0: Valid terminal function output (all variations) TEST 135: Terminal: _wireguard_patch1 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-134] ✓ _wireguard_patch1: Valid terminal function output (all variations) TEST 136: Terminal: _wireguard_info1 - validate output rules [db: /tmp/vpn-switch-arch-test.483595/test-135] ✓ _wireguard_info1: Valid terminal function output (all variations) Running Error Propagation Tests (KEEP_GOING) ======================================== TEST 137: Batch Error Propagation - test _batch2 with failing commands [db: /tmp/vpn-switch-arch-test.483595/test-136] TEST 138: Sub-test: KEEP_GOING=0 (fail-fast mode) [db: /tmp/vpn-switch-arch-test.483595/test-137] ✓ KEEP_GOING=0: Batch execution stopped on first error TEST 139: Sub-test: KEEP_GOING=1 (continue mode) [db: /tmp/vpn-switch-arch-test.483595/test-137] ✓ KEEP_GOING=1: Batch execution completed despite errors ✓ KEEP_GOING=1: All commands were executed (count=3) TEST 140: Recursive Batch Error Propagation - test chained _batch2 calls [db: /tmp/vpn-switch-arch-test.483595/test-137] ✓ Recursive fail-fast: Command 3 in batch 3 was not executed ✓ Recursive fail-fast: Batch 2 stopped after error in batch 3 ✓ Recursive fail-fast: Batch 1 stopped after error in nested batch ✓ Recursive continue: Batch 2 continued after error in batch 3 ✓ Recursive continue: Batch 1 continued after error in nested batch TEST 141: Batch KEEP_GOING with Realistic Dump File [db: /tmp/vpn-switch-arch-test.483595/test-140] ✓ Created realistic batch file with 8 commands ✓ Selected command at position 4/8 for failure injection TEST 142: Sub-test: KEEP_GOING=0 at position 4/8 [db: /tmp/vpn-switch-arch-test.483595/test-141] ✓ KEEP_GOING=0: Stopped at or before position 4 (executed 4 commands) ✓ KEEP_GOING=0: Error stop message present TEST 143: Sub-test: KEEP_GOING=1 at position 4/8 [db: /tmp/vpn-switch-arch-test.483595/test-141] ✓ KEEP_GOING=1: All commands executed (8/8) ✓ KEEP_GOING=1: Completion message present ✓ KEEP_GOING=1: Failure markers present in output Running Batch Combinator Error Propagation Tests ======================================== Testing ALL batch combinators with error injection and KEEP_GOING validation Found 26 batch combinator functions TEST 144: Batch Transitive Hull: ___session_prepare3 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.483595/test-141] TEST 145: Sub-test: Walk command tree for '___session_prepare3' (command: session_prepare) [db: /tmp/vpn-switch-arch-test.483595/test-144] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 8 injectable nodes (combinators/batches) in tree Skipped: Could not select target node for injection TEST 146: Batch Transitive Hull: ___stop0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.483595/test-144] TEST 147: Sub-test: Walk command tree for '___stop0' (command: stop) [db: /tmp/vpn-switch-arch-test.483595/test-146] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 148: Sub-test: Inject failure at node '___stop0' (node 1/2) [db: /tmp/vpn-switch-arch-test.483595/test-146] ✓ KEEP_GOING affects output: fail-fast=4 lines, continue=4 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 149: Batch Transitive Hull: ___phases_sync1 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.483595/test-146] TEST 150: Sub-test: Walk command tree for '___phases_sync1' (command: phases_sync) [db: /tmp/vpn-switch-arch-test.483595/test-149] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 151: Sub-test: Inject failure at node '___phases_sync0' (node 1/2) [db: /tmp/vpn-switch-arch-test.483595/test-149] ✓ KEEP_GOING affects output: fail-fast=3 lines, continue=3 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 152: Batch Transitive Hull: ___phases_sync0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.483595/test-149] TEST 153: Sub-test: Walk command tree for '___phases_sync0' (command: phases_sync) [db: /tmp/vpn-switch-arch-test.483595/test-152] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 154: Sub-test: Inject failure at node '___phases_sync0' (node 1/2) [db: /tmp/vpn-switch-arch-test.483595/test-152] ✓ KEEP_GOING affects output: fail-fast=3 lines, continue=3 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 155: Batch Transitive Hull: ___list0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.483595/test-152] TEST 156: Sub-test: Walk command tree for '___list0' (command: list) [db: /tmp/vpn-switch-arch-test.483595/test-155] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 157: Sub-test: Inject failure at node '___list0' (node 1/2) [db: /tmp/vpn-switch-arch-test.483595/test-155] ✓ KEEP_GOING affects output: fail-fast=2 lines, continue=2 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 158: Batch Transitive Hull: ___bootstrap2 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.483595/test-155] TEST 159: Sub-test: Walk command tree for '___bootstrap2' (command: bootstrap) [db: /tmp/vpn-switch-arch-test.483595/test-158] ✓ Command tree collected: 2 nodes in transitive hull ✓ Found 6 injectable nodes (combinators/batches) in tree Skipped: Could not select target node for injection TEST 160: Batch Transitive Hull: ___init1 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.483595/test-158] TEST 161: Sub-test: Walk command tree for '___init1' (command: init) [db: /tmp/vpn-switch-arch-test.483595/test-160] ✓ Command tree collected: 2 nodes in transitive hull ✓ Found 1 injectable nodes (combinators/batches) in tree TEST 162: Sub-test: Inject failure at node '__init0' (node 1/1) [db: /tmp/vpn-switch-arch-test.483595/test-160] ✓ KEEP_GOING affects output: fail-fast=1 lines, continue=1 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 163: Batch Transitive Hull: ___dumpenv1 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.483595/test-160] TEST 164: Sub-test: Walk command tree for '___dumpenv1' (command: dumpenv) [db: /tmp/vpn-switch-arch-test.483595/test-163] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 8 injectable nodes (combinators/batches) in tree Skipped: Could not select target node for injection TEST 165: Batch Transitive Hull: ___dump0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.483595/test-163] TEST 166: Sub-test: Walk command tree for '___dump0' (command: dump) [db: /tmp/vpn-switch-arch-test.483595/test-165] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 167: Sub-test: Inject failure at node '___dump0' (node 1/2) [db: /tmp/vpn-switch-arch-test.483595/test-165] ✓ KEEP_GOING affects output: fail-fast=17 lines, continue=17 lines Note: No clear error stop indicator in fail-fast mode ✓ KEEP_GOING=1: Execution completed despite injected failure TEST 168: Batch Transitive Hull: ___batch0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.483595/test-165] TEST 169: Sub-test: Walk command tree for '___batch0' (command: batch) [db: /tmp/vpn-switch-arch-test.483595/test-168] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 170: Sub-test: Inject failure at node '___batch0' (node 1/2) [db: /tmp/vpn-switch-arch-test.483595/test-168] ✓ KEEP_GOING affects output: fail-fast=2 lines, continue=2 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 171: Batch Transitive Hull: ___environment_inspect0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.483595/test-168] TEST 172: Sub-test: Walk command tree for '___environment_inspect0' (command: environment_inspect) [db: /tmp/vpn-switch-arch-test.483595/test-171] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 173: Sub-test: Inject failure at node '___environment_inspect0' (node 1/2) [db: /tmp/vpn-switch-arch-test.483595/test-171] ✓ KEEP_GOING affects output: fail-fast=3 lines, continue=3 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 174: Batch Transitive Hull: ___inspect0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.483595/test-171] TEST 175: Sub-test: Walk command tree for '___inspect0' (command: inspect) [db: /tmp/vpn-switch-arch-test.483595/test-174] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 176: Sub-test: Inject failure at node '___inspect0' (node 1/2) [db: /tmp/vpn-switch-arch-test.483595/test-174] ✓ KEEP_GOING affects output: fail-fast=12 lines, continue=12 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 177: Batch Transitive Hull: ___openvpn_create1 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.483595/test-174] TEST 178: Sub-test: Walk command tree for '___openvpn_create1' (command: openvpn_create) [db: /tmp/vpn-switch-arch-test.483595/test-177] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 8 injectable nodes (combinators/batches) in tree Skipped: Could not select target node for injection TEST 179: Batch Transitive Hull: ___openvpn_stop0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.483595/test-177] TEST 180: Sub-test: Walk command tree for '___openvpn_stop0' (command: openvpn_stop) [db: /tmp/vpn-switch-arch-test.483595/test-179] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 1 injectable nodes (combinators/batches) in tree TEST 181: Sub-test: Inject failure at node '___openvpn_stop0' (node 1/1) [db: /tmp/vpn-switch-arch-test.483595/test-179] ✓ KEEP_GOING affects output: fail-fast=1 lines, continue=1 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 182: Batch Transitive Hull: ___openvpn_inspect0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.483595/test-179] TEST 183: Sub-test: Walk command tree for '___openvpn_inspect0' (command: openvpn_inspect) [db: /tmp/vpn-switch-arch-test.483595/test-182] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 184: Sub-test: Inject failure at node '___openvpn_inspect0' (node 1/2) [db: /tmp/vpn-switch-arch-test.483595/test-182] ✓ KEEP_GOING affects output: fail-fast=7 lines, continue=7 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 185: Batch Transitive Hull: ___openvpn_clean0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.483595/test-182] TEST 186: Sub-test: Walk command tree for '___openvpn_clean0' (command: openvpn_clean) [db: /tmp/vpn-switch-arch-test.483595/test-185] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 3 injectable nodes (combinators/batches) in tree Skipped: Could not select target node for injection TEST 187: Batch Transitive Hull: ___openvpn_dump0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.483595/test-185] TEST 188: Sub-test: Walk command tree for '___openvpn_dump0' (command: openvpn_dump) [db: /tmp/vpn-switch-arch-test.483595/test-187] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 189: Sub-test: Inject failure at node '___openvpn_dump0' (node 1/2) [db: /tmp/vpn-switch-arch-test.483595/test-187] ✓ KEEP_GOING affects output: fail-fast=20 lines, continue=20 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 190: Batch Transitive Hull: ___session_dump0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.483595/test-187] TEST 191: Sub-test: Walk command tree for '___session_dump0' (command: session_dump) [db: /tmp/vpn-switch-arch-test.483595/test-190] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 192: Sub-test: Inject failure at node '___session_dump0' (node 1/2) [db: /tmp/vpn-switch-arch-test.483595/test-190] ✓ KEEP_GOING affects output: fail-fast=41 lines, continue=41 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 193: Batch Transitive Hull: ___session_inspect0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.483595/test-190] TEST 194: Sub-test: Walk command tree for '___session_inspect0' (command: session_inspect) [db: /tmp/vpn-switch-arch-test.483595/test-193] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 195: Sub-test: Inject failure at node '___session_inspect0' (node 1/2) [db: /tmp/vpn-switch-arch-test.483595/test-193] ✓ KEEP_GOING affects output: fail-fast=5 lines, continue=5 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 196: Batch Transitive Hull: ___validate0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.483595/test-193] TEST 197: Sub-test: Walk command tree for '___validate0' (command: validate) [db: /tmp/vpn-switch-arch-test.483595/test-196] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 198: Sub-test: Inject failure at node '___validate0' (node 1/2) [db: /tmp/vpn-switch-arch-test.483595/test-196] ✓ KEEP_GOING affects output: fail-fast=10 lines, continue=10 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 199: Batch Transitive Hull: ___wireguard_create1 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.483595/test-196] TEST 200: Sub-test: Walk command tree for '___wireguard_create1' (command: wireguard_create) [db: /tmp/vpn-switch-arch-test.483595/test-199] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 8 injectable nodes (combinators/batches) in tree Skipped: Could not select target node for injection TEST 201: Batch Transitive Hull: ___wireguard_inspect0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.483595/test-199] TEST 202: Sub-test: Walk command tree for '___wireguard_inspect0' (command: wireguard_inspect) [db: /tmp/vpn-switch-arch-test.483595/test-201] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 203: Sub-test: Inject failure at node '___wireguard_inspect0' (node 1/2) [db: /tmp/vpn-switch-arch-test.483595/test-201] ✓ KEEP_GOING affects output: fail-fast=7 lines, continue=7 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 204: Batch Transitive Hull: ___wireguard_stop0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.483595/test-201] TEST 205: Sub-test: Walk command tree for '___wireguard_stop0' (command: wireguard_stop) [db: /tmp/vpn-switch-arch-test.483595/test-204] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 1 injectable nodes (combinators/batches) in tree TEST 206: Sub-test: Inject failure at node '___wireguard_stop0' (node 1/1) [db: /tmp/vpn-switch-arch-test.483595/test-204] ✓ KEEP_GOING affects output: fail-fast=1 lines, continue=1 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 207: Batch Transitive Hull: ___wireguard_clean0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.483595/test-204] TEST 208: Sub-test: Walk command tree for '___wireguard_clean0' (command: wireguard_clean) [db: /tmp/vpn-switch-arch-test.483595/test-207] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 3 injectable nodes (combinators/batches) in tree Skipped: Could not select target node for injection TEST 209: Batch Transitive Hull: ___wireguard_clean1 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.483595/test-207] TEST 210: Sub-test: Walk command tree for '___wireguard_clean1' (command: wireguard_clean) [db: /tmp/vpn-switch-arch-test.483595/test-209] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 3 injectable nodes (combinators/batches) in tree Skipped: Could not select target node for injection TEST 211: Batch Transitive Hull: ___wireguard_dump0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.483595/test-209] TEST 212: Sub-test: Walk command tree for '___wireguard_dump0' (command: wireguard_dump) [db: /tmp/vpn-switch-arch-test.483595/test-211] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 213: Sub-test: Inject failure at node '___wireguard_dump0' (node 1/2) [db: /tmp/vpn-switch-arch-test.483595/test-211] ✓ KEEP_GOING affects output: fail-fast=42 lines, continue=42 lines Note: No clear error stop indicator in fail-fast mode ✓ KEEP_GOING=1: Execution completed despite injected failure Running Batch Combinator KEEP_GOING Precise Tests ======================================== Testing ALL batch combinators with precise architectural KEEP_GOING validation Found 26 batch combinator functions TEST 214: Batch KEEP_GOING Precise: ___session_prepare3 [db: /tmp/vpn-switch-arch-test.483595/test-211] ✓ Captured 175 command lines from ___session_prepare3 ✓ Selected 65 random line(s) for failure injection Skipped: No functions were injected with failures TEST 215: Batch KEEP_GOING Precise: ___stop0 [db: /tmp/vpn-switch-arch-test.483595/test-214] ✓ Captured 2 command lines from ___stop0 ✓ Selected 2 random line(s) for failure injection ✓ Injected failures into 2 function(s) Note: Not all commands attempted (0/3) Note: This may indicate KEEP_GOING=0 or execution stopped early Skipped: ___phases_sync1 (requires phase template setup) Skipped: ___phases_sync0 (requires phase template setup) TEST 216: Batch KEEP_GOING Precise: ___list0 [db: /tmp/vpn-switch-arch-test.483595/test-215] ✓ Captured 2 command lines from ___list0 ✓ Selected 1 random line(s) for failure injection ✓ Injected failures into 1 function(s) ✓ KEEP_GOING=1: All commands attempted (2/2) TEST 217: Batch KEEP_GOING Precise: ___bootstrap2 [db: /tmp/vpn-switch-arch-test.483595/test-216] ✓ Captured 73 command lines from ___bootstrap2 ✓ Selected 36 random line(s) for failure injection Skipped: No functions were injected with failures Skipped: ___init1 (complex initialization logic) TEST 218: Batch KEEP_GOING Precise: ___dumpenv1 [db: /tmp/vpn-switch-arch-test.483595/test-217] ✓ Captured 175 command lines from ___dumpenv1 ✓ Selected 133 random line(s) for failure injection Skipped: No functions were injected with failures TEST 219: Batch KEEP_GOING Precise: ___dump0 [db: /tmp/vpn-switch-arch-test.483595/test-218] ✓ Captured 5 command lines from ___dump0 ✓ Selected 3 random line(s) for failure injection ✓ Injected failures into 1 function(s) Note: Not all commands attempted (3/5) Note: This may indicate KEEP_GOING=0 or execution stopped early TEST 220: Batch KEEP_GOING Precise: ___batch0 [db: /tmp/vpn-switch-arch-test.483595/test-219] ✓ Captured 2 command lines from ___batch0 ✓ Selected 2 random line(s) for failure injection Skipped: No functions were injected with failures TEST 221: Batch KEEP_GOING Precise: ___environment_inspect0 [db: /tmp/vpn-switch-arch-test.483595/test-220] ✓ Captured 2 command lines from ___environment_inspect0 ✓ Selected 2 random line(s) for failure injection ✓ Injected failures into 2 function(s) Note: Not all commands attempted (2/3) Note: This may indicate KEEP_GOING=0 or execution stopped early TEST 222: Batch KEEP_GOING Precise: ___inspect0 [db: /tmp/vpn-switch-arch-test.483595/test-221] ✓ Captured 12 command lines from ___inspect0 ✓ Selected 6 random line(s) for failure injection ✓ Injected failures into 4 function(s) Note: Not all commands attempted (10/12) Note: This may indicate KEEP_GOING=0 or execution stopped early TEST 223: Batch KEEP_GOING Precise: ___openvpn_create1 [db: /tmp/vpn-switch-arch-test.483595/test-222] ✓ Captured 175 command lines from ___openvpn_create1 ✓ Selected 29 random line(s) for failure injection Skipped: No functions were injected with failures TEST 224: Batch KEEP_GOING Precise: ___openvpn_stop0 [db: /tmp/vpn-switch-arch-test.483595/test-223] ✓ Captured 1 command lines from ___openvpn_stop0 ✓ Selected 1 random line(s) for failure injection Skipped: No functions were injected with failures TEST 225: Batch KEEP_GOING Precise: ___openvpn_inspect0 [db: /tmp/vpn-switch-arch-test.483595/test-224] ✓ Captured 3 command lines from ___openvpn_inspect0 ✓ Selected 3 random line(s) for failure injection Skipped: No functions were injected with failures TEST 226: Batch KEEP_GOING Precise: ___openvpn_clean0 [db: /tmp/vpn-switch-arch-test.483595/test-225] ✓ Captured 3 command lines from ___openvpn_clean0 ✓ Selected 1 random line(s) for failure injection Skipped: No functions were injected with failures TEST 227: Batch KEEP_GOING Precise: ___openvpn_dump0 [db: /tmp/vpn-switch-arch-test.483595/test-226] ✓ Captured 13 command lines from ___openvpn_dump0 ✓ Selected 3 random line(s) for failure injection Skipped: No functions were injected with failures TEST 228: Batch KEEP_GOING Precise: ___session_dump0 [db: /tmp/vpn-switch-arch-test.483595/test-227] ✓ Captured 40 command lines from ___session_dump0 ✓ Selected 23 random line(s) for failure injection Skipped: No functions were injected with failures TEST 229: Batch KEEP_GOING Precise: ___session_inspect0 [db: /tmp/vpn-switch-arch-test.483595/test-228] ✓ Captured 4 command lines from ___session_inspect0 ✓ Selected 2 random line(s) for failure injection ✓ Injected failures into 2 function(s) Note: Not all commands attempted (3/4) Note: This may indicate KEEP_GOING=0 or execution stopped early TEST 230: Batch KEEP_GOING Precise: ___validate0 [db: /tmp/vpn-switch-arch-test.483595/test-229] ✓ Captured 10 command lines from ___validate0 ✓ Selected 2 random line(s) for failure injection ✓ Injected failures into 2 function(s) ✓ KEEP_GOING=1: All commands attempted (10/10) TEST 231: Batch KEEP_GOING Precise: ___wireguard_create1 [db: /tmp/vpn-switch-arch-test.483595/test-230] ✓ Captured 175 command lines from ___wireguard_create1 ✓ Selected 73 random line(s) for failure injection Skipped: No functions were injected with failures TEST 232: Batch KEEP_GOING Precise: ___wireguard_inspect0 [db: /tmp/vpn-switch-arch-test.483595/test-231] ✓ Captured 3 command lines from ___wireguard_inspect0 ✓ Selected 3 random line(s) for failure injection Skipped: No functions were injected with failures TEST 233: Batch KEEP_GOING Precise: ___wireguard_stop0 [db: /tmp/vpn-switch-arch-test.483595/test-232] ✓ Captured 1 command lines from ___wireguard_stop0 ✓ Selected 1 random line(s) for failure injection Skipped: No functions were injected with failures TEST 234: Batch KEEP_GOING Precise: ___wireguard_clean0 [db: /tmp/vpn-switch-arch-test.483595/test-233] ✓ Captured 9 command lines from ___wireguard_clean0 ✓ Selected 8 random line(s) for failure injection Skipped: No functions were injected with failures TEST 235: Batch KEEP_GOING Precise: ___wireguard_clean1 [db: /tmp/vpn-switch-arch-test.483595/test-234] ✓ Captured 9 command lines from ___wireguard_clean1 ✓ Selected 7 random line(s) for failure injection Skipped: No functions were injected with failures TEST 236: Batch KEEP_GOING Precise: ___wireguard_dump0 [db: /tmp/vpn-switch-arch-test.483595/test-235] ✓ Captured 34 command lines from ___wireguard_dump0 ✓ Selected 30 random line(s) for failure injection Skipped: No functions were injected with failures Running Static Analysis Tests ======================================== Testing architecture violation scanner TEST 237: Architecture Violation Scanner [db: /tmp/vpn-switch-arch-test.483595/test-236] ✓ Scanner executed successfully (exit code: 0) Found: 1 total violations ✓ Scanner detection working (violations found as expected) ✓ Scanner detects MODIFY_* variable usage Running Read-Only Database Tests ======================================== Testing that functions don't modify database at generation time TEST 238: Read-Only Database: All functions [db: /tmp/vpn-switch-arch-test.483595/test-236] Testing terminal functions... ✓ _session_create1: No permission errors on read-only database ✓ _interface_destroy1: No permission errors on read-only database ✓ _session_populate3: No permission errors on read-only database ✓ _link2: No permission errors on read-only database ✓ _remove1: No permission errors on read-only database ✓ _error1: No permission errors on read-only database ✓ _error2: No permission errors on read-only database ✓ _error3: No permission errors on read-only database ✓ _fail2: No permission errors on read-only database ✓ _log1: No permission errors on read-only database ✓ _log2: No permission errors on read-only database ✓ _log3: No permission errors on read-only database ✓ _lift1: No permission errors on read-only database ✓ _lift3: No permission errors on read-only database Warning: setenv2: output differs between writable/readonly (but compliant) ✓ _setenv2: No permission errors on read-only database ✓ _getenv1: No permission errors on read-only database ✓ _unsetenv1: No permission errors on read-only database ✓ _printenv0: No permission errors on read-only database Warning: status0: output differs between writable/readonly (but compliant) ✓ _status0: No permission errors on read-only database ✓ _help0: No permission errors on read-only database ✓ _help1: No permission errors on read-only database Warning: database_enumerate0: output differs between writable/readonly (but compliant) ✓ _database_enumerate0: No permission errors on read-only database ✓ _system_inspect0: No permission errors on read-only database Warning: logs_inspect0: output differs between writable/readonly (but compliant) ✓ _logs_inspect0: No permission errors on read-only database ✓ _phases_inspect0: No permission errors on read-only database ✓ _summary_inspect0: No permission errors on read-only database ✓ _prologue_inspect0: No permission errors on read-only database ✓ _openvpn_patch2: No permission errors on read-only database ✓ _openvpn_configure1: No permission errors on read-only database ✓ _openvpn_connect1: No permission errors on read-only database ✓ _openvpn_disconnect1: No permission errors on read-only database ✓ _openvpn_patch1: No permission errors on read-only database Warning: openvpn_enumerate0: output differs between writable/readonly (but compliant) ✓ _openvpn_enumerate0: No permission errors on read-only database ✓ _openvpn_import1: No permission errors on read-only database ✓ _openvpn_list0: No permission errors on read-only database ✓ _openvpn_list1: No permission errors on read-only database ✓ _openvpn_add1: No permission errors on read-only database ✓ _openvpn_add3: No permission errors on read-only database ✓ _openvpn_link2: No permission errors on read-only database ✓ _openvpn_remove1: No permission errors on read-only database ✓ _openvpn_remove2: No permission errors on read-only database ✓ _openvpn_validate0: No permission errors on read-only database ✓ _openvpn_info1: No permission errors on read-only database ✓ _session_list0: No permission errors on read-only database ✓ _session_show1: No permission errors on read-only database ✓ _session_remove1: No permission errors on read-only database ✓ _session_connect1: No permission errors on read-only database ✓ _session_save0: No permission errors on read-only database ✓ _session_save1: No permission errors on read-only database ✓ _session_clean0: No permission errors on read-only database ✓ _session_validate0: No permission errors on read-only database ✓ _session_enumerate0: No permission errors on read-only database ✓ _session_describe0: No permission errors on read-only database ✓ _logs_validate0: No permission errors on read-only database ✓ _logs_clean0: No permission errors on read-only database ✓ _phases_validate0: No permission errors on read-only database ✓ _database_validate0: No permission errors on read-only database ✓ _binaries_validate0: No permission errors on read-only database ✓ _network_validate0: No permission errors on read-only database ✓ _permissions_validate0: No permission errors on read-only database ✓ _environment_validate0: No permission errors on read-only database ✓ _wireguard_patch2: No permission errors on read-only database ✓ _wireguard_configure1: No permission errors on read-only database ✓ _wireguard_connect1: No permission errors on read-only database ✓ _wireguard_disconnect1: No permission errors on read-only database Warning: wireguard_enumerate0: output differs between writable/readonly (but compliant) ✓ _wireguard_enumerate0: No permission errors on read-only database ✓ _wireguard_import1: No permission errors on read-only database ✓ _wireguard_list0: No permission errors on read-only database ✓ _wireguard_list1: No permission errors on read-only database ✓ _wireguard_add1: No permission errors on read-only database ✓ _wireguard_add3: No permission errors on read-only database ✓ _wireguard_link2: No permission errors on read-only database ✓ _wireguard_remove1: No permission errors on read-only database ✓ _wireguard_remove2: No permission errors on read-only database ✓ _wireguard_validate0: No permission errors on read-only database ✓ _wireguard_patch1: No permission errors on read-only database ✓ _wireguard_info1: No permission errors on read-only database Testing combinator functions... ✓ __session_exists1: No permission errors on read-only database ✓ __session_conflicts2: No permission errors on read-only database ✓ __interface_check1: No permission errors on read-only database ✓ __stop1: No permission errors on read-only database ✓ __import1: No permission errors on read-only database ✓ __start1: No permission errors on read-only database ✓ __start0: No permission errors on read-only database ✓ __bootstrap1: No permission errors on read-only database ✓ __environment_cache0: No permission errors on read-only database ✓ __phases_lift1: No permission errors on read-only database ✓ __init0: No permission errors on read-only database ✓ __batch1: No permission errors on read-only database ✓ __restore1: No permission errors on read-only database Warning: openvpn_start0: output differs between writable/readonly (but compliant) ✓ __openvpn_start0: No permission errors on read-only database ✓ __openvpn_start1: No permission errors on read-only database ✓ __openvpn_stop1: No permission errors on read-only database ✓ __openvpn_add2: No permission errors on read-only database ✓ __openvpn_help0: No permission errors on read-only database ✓ __session_disconnect1: No permission errors on read-only database ✓ __session_show0: No permission errors on read-only database ✓ __session_start0: No permission errors on read-only database ✓ __session_start1: No permission errors on read-only database ✓ __session_help0: No permission errors on read-only database ✓ __wireguard_start0: No permission errors on read-only database ✓ __wireguard_start1: No permission errors on read-only database ✓ __wireguard_stop1: No permission errors on read-only database ✓ __wireguard_add2: No permission errors on read-only database ✓ __wireguard_help0: No permission errors on read-only database Testing batch combinator functions... ✓ ___session_prepare3: No permission errors on read-only database ✓ ___stop0: No permission errors on read-only database ✓ ___phases_sync1: No permission errors on read-only database ✓ ___phases_sync0: No permission errors on read-only database ✓ ___list0: No permission errors on read-only database ✓ ___dumpenv1: No permission errors on read-only database ✓ ___dump0: No permission errors on read-only database Warning: batch0: output differs between writable/readonly (but compliant) ✓ ___batch0: No permission errors on read-only database ✓ ___environment_inspect0: No permission errors on read-only database ✓ ___inspect0: No permission errors on read-only database Warning: openvpn_create1: output differs between writable/readonly (but compliant) ✓ ___openvpn_create1: No permission errors on read-only database ✓ ___openvpn_stop0: No permission errors on read-only database ✓ ___openvpn_inspect0: No permission errors on read-only database ✓ ___openvpn_clean0: No permission errors on read-only database ✓ ___openvpn_dump0: No permission errors on read-only database ✓ ___session_dump0: No permission errors on read-only database ✓ ___session_inspect0: No permission errors on read-only database ✓ ___validate0: No permission errors on read-only database Warning: wireguard_create1: output differs between writable/readonly (but compliant) ✓ ___wireguard_create1: No permission errors on read-only database ✓ ___wireguard_inspect0: No permission errors on read-only database ✓ ___wireguard_stop0: No permission errors on read-only database ✓ ___wireguard_clean0: No permission errors on read-only database ✓ ___wireguard_clean1: No permission errors on read-only database ✓ ___wireguard_dump0: No permission errors on read-only database Summary: Tested 129 functions, skipped 8 ======================================== Architecture Test Summary ======================================== Test Functions: 238 Total Assertions: 410 Passed Assertions: 410 Failed Assertions: 0 ALL TESTS PASSED Cleaning up test databases... Done. ======================================== vpn-switch Architecture Test Suite ======================================== Testing architectural rules for combinator functions Profile: minimal Running Combinator Tests ======================================== Found 28 combinator functions TEST 1: Combinator: __session_exists1 - validate syntax with variations ✓ __session_exists1: Valid combinator syntax (all variations) TEST 2: Combinator: __session_conflicts2 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-1] ✓ __session_conflicts2: Valid combinator syntax (all variations) TEST 3: Combinator: __interface_check1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-2] ✓ __interface_check1: Valid combinator syntax (all variations) TEST 4: Combinator: __stop1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-3] ✓ __stop1: Valid combinator syntax (all variations) TEST 5: Combinator: __import1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-4] ✓ __import1: Valid combinator syntax (all variations) TEST 6: Combinator: __start1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-5] ✓ __start1: Valid combinator syntax (all variations) TEST 7: Combinator: __start0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-6] ✓ __start0: Valid combinator syntax (all variations) TEST 8: Combinator: __bootstrap1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-7] ✓ __bootstrap1: Valid combinator syntax (all variations) TEST 9: Combinator: __environment_cache0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-8] ✓ __environment_cache0: Valid combinator syntax (all variations) TEST 10: Combinator: __phases_lift1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-9] ✓ __phases_lift1: Valid combinator syntax (all variations) TEST 11: Combinator: __init0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-10] ✓ __init0: Valid combinator syntax (all variations) TEST 12: Combinator: __batch1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-11] ✓ __batch1: Valid combinator syntax (all variations) TEST 13: Combinator: __restore1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-12] ✓ __restore1: Valid combinator syntax (all variations) TEST 14: Combinator: __openvpn_start0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-13] ✓ __openvpn_start0: Valid combinator syntax (all variations) TEST 15: Combinator: __openvpn_start1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-14] ✓ __openvpn_start1: Valid combinator syntax (all variations) TEST 16: Combinator: __openvpn_stop1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-15] ✓ __openvpn_stop1: Valid combinator syntax (all variations) TEST 17: Combinator: __openvpn_add2 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-16] ✓ __openvpn_add2: Valid combinator syntax (all variations) TEST 18: Combinator: __openvpn_help0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-17] ✓ __openvpn_help0: Valid combinator syntax (all variations) TEST 19: Combinator: __session_disconnect1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-18] ✓ __session_disconnect1: Valid combinator syntax (all variations) TEST 20: Combinator: __session_show0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-19] ✓ __session_show0: Valid combinator syntax (all variations) TEST 21: Combinator: __session_start0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-20] ✓ __session_start0: Valid combinator syntax (all variations) TEST 22: Combinator: __session_start1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-21] ✓ __session_start1: Valid combinator syntax (all variations) TEST 23: Combinator: __session_help0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-22] ✓ __session_help0: Valid combinator syntax (all variations) TEST 24: Combinator: __wireguard_start0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-23] ✓ __wireguard_start0: Valid combinator syntax (all variations) TEST 25: Combinator: __wireguard_start1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-24] ✓ __wireguard_start1: Valid combinator syntax (all variations) TEST 26: Combinator: __wireguard_stop1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-25] ✓ __wireguard_stop1: Valid combinator syntax (all variations) TEST 27: Combinator: __wireguard_add2 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-26] ✓ __wireguard_add2: Valid combinator syntax (all variations) TEST 28: Combinator: __wireguard_help0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-27] ✓ __wireguard_help0: Valid combinator syntax (all variations) Running Batch Combinator Tests ======================================== Found 26 batch combinator functions TEST 29: Batch Combinator: ___session_prepare3 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-28] ✓ ___session_prepare3: Valid batch combinator syntax (all variations) TEST 30: Batch Combinator: ___stop0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-29] ✓ ___stop0: Valid batch combinator syntax (all variations) TEST 31: Batch Combinator: ___phases_sync1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-30] ✓ ___phases_sync1: Valid batch combinator syntax (all variations) TEST 32: Batch Combinator: ___phases_sync0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-31] ✓ ___phases_sync0: Valid batch combinator syntax (all variations) TEST 33: Batch Combinator: ___list0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-32] ✓ ___list0: Valid batch combinator syntax (all variations) TEST 34: Batch Combinator: ___bootstrap2 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-33] ✓ ___bootstrap2: Valid batch combinator syntax (all variations) TEST 35: Batch Combinator: ___init1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-34] ✓ ___init1: Valid batch combinator syntax (all variations) TEST 36: Batch Combinator: ___dumpenv1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-35] ✓ ___dumpenv1: Valid batch combinator syntax (all variations) TEST 37: Batch Combinator: ___dump0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-36] ✓ ___dump0: Valid batch combinator syntax (all variations) TEST 38: Batch Combinator: ___batch0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-37] ✓ ___batch0: Valid batch combinator syntax (all variations) TEST 39: Batch Combinator: ___environment_inspect0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-38] ✓ ___environment_inspect0: Valid batch combinator syntax (all variations) TEST 40: Batch Combinator: ___inspect0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-39] ✓ ___inspect0: Valid batch combinator syntax (all variations) TEST 41: Batch Combinator: ___openvpn_create1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-40] ✓ ___openvpn_create1: Valid batch combinator syntax (all variations) TEST 42: Batch Combinator: ___openvpn_stop0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-41] ✓ ___openvpn_stop0: Valid batch combinator syntax (all variations) TEST 43: Batch Combinator: ___openvpn_inspect0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-42] ✓ ___openvpn_inspect0: Valid batch combinator syntax (all variations) TEST 44: Batch Combinator: ___openvpn_clean0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-43] ✓ ___openvpn_clean0: Valid batch combinator syntax (all variations) TEST 45: Batch Combinator: ___openvpn_dump0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-44] ✓ ___openvpn_dump0: Valid batch combinator syntax (all variations) TEST 46: Batch Combinator: ___session_dump0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-45] ✓ ___session_dump0: Valid batch combinator syntax (all variations) TEST 47: Batch Combinator: ___session_inspect0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-46] ✓ ___session_inspect0: Valid batch combinator syntax (all variations) TEST 48: Batch Combinator: ___validate0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-47] ✓ ___validate0: Valid batch combinator syntax (all variations) TEST 49: Batch Combinator: ___wireguard_create1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-48] ✓ ___wireguard_create1: Valid batch combinator syntax (all variations) TEST 50: Batch Combinator: ___wireguard_inspect0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-49] ✓ ___wireguard_inspect0: Valid batch combinator syntax (all variations) TEST 51: Batch Combinator: ___wireguard_stop0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-50] ✓ ___wireguard_stop0: Valid batch combinator syntax (all variations) TEST 52: Batch Combinator: ___wireguard_clean0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-51] ✓ ___wireguard_clean0: Valid batch combinator syntax (all variations) TEST 53: Batch Combinator: ___wireguard_clean1 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-52] ✓ ___wireguard_clean1: Valid batch combinator syntax (all variations) TEST 54: Batch Combinator: ___wireguard_dump0 - validate syntax with variations [db: /tmp/vpn-switch-arch-test.1257195/test-53] ✓ ___wireguard_dump0: Valid batch combinator syntax (all variations) Running Terminal Function Tests ======================================== Found 83 terminal functions TEST 55: Terminal: _session_create1 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-54] ✓ _session_create1: Valid terminal function output (all variations) TEST 56: Terminal: _interface_destroy1 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-55] ✓ _interface_destroy1: Valid terminal function output (all variations) TEST 57: Terminal: _session_populate3 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-56] ✓ _session_populate3: Valid terminal function output (all variations) TEST 58: Terminal: _phases_copy0 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-57] ✓ _phases_copy0: Valid terminal function output (all variations) TEST 59: Terminal: _link2 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-58] ✓ _link2: Valid terminal function output (all variations) TEST 60: Terminal: _remove1 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-59] ✓ _remove1: Valid terminal function output (all variations) TEST 61: Terminal: _error1 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-60] ✓ _error1: Valid terminal function output (all variations) TEST 62: Terminal: _error2 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-61] ✓ _error2: Valid terminal function output (all variations) TEST 63: Terminal: _error3 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-62] ✓ _error3: Valid terminal function output (all variations) TEST 64: Terminal: _fail2 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-63] ✓ _fail2: Valid terminal function output (all variations) TEST 65: Terminal: _log1 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-64] ✓ _log1: Valid terminal function output (all variations) TEST 66: Terminal: _log2 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-65] ✓ _log2: Valid terminal function output (all variations) TEST 67: Terminal: _log3 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-66] ✓ _log3: Valid terminal function output (all variations) TEST 68: Terminal: _lift1 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-67] ✓ _lift1: Valid terminal function output (all variations) TEST 69: Terminal: _database_init0 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-68] ✓ _database_init0: Valid terminal function output (all variations) TEST 70: Terminal: _environment_init1 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-69] ✓ _environment_init1: Valid terminal function output (all variations) TEST 71: Terminal: _environment_cache1 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-70] ✓ _environment_cache1: Valid terminal function output (all variations) TEST 72: Terminal: _lift3 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-71] ✓ _lift3: Valid terminal function output (all variations) TEST 73: Terminal: _setenv2 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-72] ✓ _setenv2: Valid terminal function output (all variations) TEST 74: Terminal: _getenv1 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-73] ✓ _getenv1: Valid terminal function output (all variations) TEST 75: Terminal: _unsetenv1 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-74] ✓ _unsetenv1: Valid terminal function output (all variations) Skipped: _cat1 (requires special setup) TEST 76: Terminal: _batch2 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-75] ✓ _batch2: Valid terminal function output (all variations) TEST 77: Terminal: _printenv0 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-76] ✓ _printenv0: Valid terminal function output (all variations) TEST 78: Terminal: _status0 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-77] ✓ _status0: Valid terminal function output (all variations) TEST 79: Terminal: _help0 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-78] ✓ _help0: Valid terminal function output (all variations) TEST 80: Terminal: _help1 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-79] ✓ _help1: Valid terminal function output (all variations) TEST 81: Terminal: _database_enumerate0 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-80] ✓ _database_enumerate0: Valid terminal function output (all variations) TEST 82: Terminal: _system_inspect0 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-81] ✓ _system_inspect0: Valid terminal function output (all variations) TEST 83: Terminal: _logs_inspect0 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-82] ✓ _logs_inspect0: Valid terminal function output (all variations) TEST 84: Terminal: _phases_inspect0 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-83] ✓ _phases_inspect0: Valid terminal function output (all variations) TEST 85: Terminal: _summary_inspect0 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-84] ✓ _summary_inspect0: Valid terminal function output (all variations) TEST 86: Terminal: _prologue_inspect0 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-85] ✓ _prologue_inspect0: Valid terminal function output (all variations) TEST 87: Terminal: _openvpn_patch2 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-86] ✓ _openvpn_patch2: Valid terminal function output (all variations) TEST 88: Terminal: _openvpn_configure1 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-87] ✓ _openvpn_configure1: Valid terminal function output (all variations) TEST 89: Terminal: _openvpn_connect1 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-88] ✓ _openvpn_connect1: Valid terminal function output (all variations) TEST 90: Terminal: _openvpn_disconnect1 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-89] ✓ _openvpn_disconnect1: Valid terminal function output (all variations) TEST 91: Terminal: _openvpn_patch1 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-90] ✓ _openvpn_patch1: Valid terminal function output (all variations) TEST 92: Terminal: _openvpn_enumerate0 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-91] ✓ _openvpn_enumerate0: Valid terminal function output (all variations) TEST 93: Terminal: _openvpn_import1 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-92] ✓ _openvpn_import1: Valid terminal function output (all variations) TEST 94: Terminal: _openvpn_list0 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-93] ✓ _openvpn_list0: Valid terminal function output (all variations) TEST 95: Terminal: _openvpn_list1 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-94] ✓ _openvpn_list1: Valid terminal function output (all variations) TEST 96: Terminal: _openvpn_add1 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-95] ✓ _openvpn_add1: Valid terminal function output (all variations) TEST 97: Terminal: _openvpn_add3 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-96] ✓ _openvpn_add3: Valid terminal function output (all variations) TEST 98: Terminal: _openvpn_link2 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-97] ✓ _openvpn_link2: Valid terminal function output (all variations) TEST 99: Terminal: _openvpn_remove1 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-98] ✓ _openvpn_remove1: Valid terminal function output (all variations) TEST 100: Terminal: _openvpn_remove2 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-99] ✓ _openvpn_remove2: Valid terminal function output (all variations) TEST 101: Terminal: _openvpn_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-100] ✓ _openvpn_validate0: Valid terminal function output (all variations) TEST 102: Terminal: _openvpn_info1 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-101] ✓ _openvpn_info1: Valid terminal function output (all variations) TEST 103: Terminal: _session_list0 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-102] ✓ _session_list0: Valid terminal function output (all variations) TEST 104: Terminal: _session_show1 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-103] ✓ _session_show1: Valid terminal function output (all variations) TEST 105: Terminal: _session_remove1 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-104] ✓ _session_remove1: Valid terminal function output (all variations) TEST 106: Terminal: _session_connect1 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-105] ✓ _session_connect1: Valid terminal function output (all variations) TEST 107: Terminal: _session_save0 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-106] ✓ _session_save0: Valid terminal function output (all variations) TEST 108: Terminal: _session_save1 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-107] ✓ _session_save1: Valid terminal function output (all variations) TEST 109: Terminal: _session_clean0 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-108] ✓ _session_clean0: Valid terminal function output (all variations) TEST 110: Terminal: _session_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-109] ✓ _session_validate0: Valid terminal function output (all variations) TEST 111: Terminal: _session_enumerate0 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-110] ✓ _session_enumerate0: Valid terminal function output (all variations) TEST 112: Terminal: _session_describe0 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-111] ✓ _session_describe0: Valid terminal function output (all variations) TEST 113: Terminal: _logs_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-112] ✓ _logs_validate0: Valid terminal function output (all variations) TEST 114: Terminal: _logs_clean0 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-113] ✓ _logs_clean0: Valid terminal function output (all variations) TEST 115: Terminal: _phases_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-114] ✓ _phases_validate0: Valid terminal function output (all variations) TEST 116: Terminal: _database_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-115] ✓ _database_validate0: Valid terminal function output (all variations) TEST 117: Terminal: _binaries_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-116] ✓ _binaries_validate0: Valid terminal function output (all variations) TEST 118: Terminal: _network_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-117] ✓ _network_validate0: Valid terminal function output (all variations) TEST 119: Terminal: _permissions_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-118] ✓ _permissions_validate0: Valid terminal function output (all variations) TEST 120: Terminal: _environment_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-119] ✓ _environment_validate0: Valid terminal function output (all variations) TEST 121: Terminal: _wireguard_patch2 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-120] ✓ _wireguard_patch2: Valid terminal function output (all variations) TEST 122: Terminal: _wireguard_configure1 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-121] ✓ _wireguard_configure1: Valid terminal function output (all variations) TEST 123: Terminal: _wireguard_connect1 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-122] ✓ _wireguard_connect1: Valid terminal function output (all variations) TEST 124: Terminal: _wireguard_disconnect1 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-123] ✓ _wireguard_disconnect1: Valid terminal function output (all variations) TEST 125: Terminal: _wireguard_enumerate0 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-124] ✓ _wireguard_enumerate0: Valid terminal function output (all variations) TEST 126: Terminal: _wireguard_import1 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-125] ✓ _wireguard_import1: Valid terminal function output (all variations) TEST 127: Terminal: _wireguard_list0 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-126] ✓ _wireguard_list0: Valid terminal function output (all variations) TEST 128: Terminal: _wireguard_list1 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-127] ✓ _wireguard_list1: Valid terminal function output (all variations) TEST 129: Terminal: _wireguard_add1 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-128] ✓ _wireguard_add1: Valid terminal function output (all variations) TEST 130: Terminal: _wireguard_add3 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-129] ✓ _wireguard_add3: Valid terminal function output (all variations) TEST 131: Terminal: _wireguard_link2 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-130] ✓ _wireguard_link2: Valid terminal function output (all variations) TEST 132: Terminal: _wireguard_remove1 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-131] ✓ _wireguard_remove1: Valid terminal function output (all variations) TEST 133: Terminal: _wireguard_remove2 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-132] ✓ _wireguard_remove2: Valid terminal function output (all variations) TEST 134: Terminal: _wireguard_validate0 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-133] ✓ _wireguard_validate0: Valid terminal function output (all variations) TEST 135: Terminal: _wireguard_patch1 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-134] ✓ _wireguard_patch1: Valid terminal function output (all variations) TEST 136: Terminal: _wireguard_info1 - validate output rules [db: /tmp/vpn-switch-arch-test.1257195/test-135] ✓ _wireguard_info1: Valid terminal function output (all variations) Running Error Propagation Tests (KEEP_GOING) ======================================== TEST 137: Batch Error Propagation - test _batch2 with failing commands [db: /tmp/vpn-switch-arch-test.1257195/test-136] TEST 138: Sub-test: KEEP_GOING=0 (fail-fast mode) [db: /tmp/vpn-switch-arch-test.1257195/test-137] ✓ KEEP_GOING=0: Batch execution stopped on first error TEST 139: Sub-test: KEEP_GOING=1 (continue mode) [db: /tmp/vpn-switch-arch-test.1257195/test-137] ✓ KEEP_GOING=1: Batch execution completed despite errors ✓ KEEP_GOING=1: All commands were executed (count=3) TEST 140: Recursive Batch Error Propagation - test chained _batch2 calls [db: /tmp/vpn-switch-arch-test.1257195/test-137] ✓ Recursive fail-fast: Command 3 in batch 3 was not executed ✓ Recursive fail-fast: Batch 2 stopped after error in batch 3 ✓ Recursive fail-fast: Batch 1 stopped after error in nested batch ✓ Recursive continue: Batch 2 continued after error in batch 3 ✓ Recursive continue: Batch 1 continued after error in nested batch TEST 141: Batch KEEP_GOING with Realistic Dump File [db: /tmp/vpn-switch-arch-test.1257195/test-140] ✓ Created realistic batch file with 8 commands ✓ Selected command at position 3/8 for failure injection TEST 142: Sub-test: KEEP_GOING=0 at position 3/8 [db: /tmp/vpn-switch-arch-test.1257195/test-141] ✓ KEEP_GOING=0: Stopped at or before position 3 (executed 3 commands) ✓ KEEP_GOING=0: Error stop message present TEST 143: Sub-test: KEEP_GOING=1 at position 3/8 [db: /tmp/vpn-switch-arch-test.1257195/test-141] ✓ KEEP_GOING=1: All commands executed (8/8) ✓ KEEP_GOING=1: Completion message present ✓ KEEP_GOING=1: Failure markers present in output Running Batch Combinator Error Propagation Tests ======================================== Testing ALL batch combinators with error injection and KEEP_GOING validation Found 26 batch combinator functions TEST 144: Batch Transitive Hull: ___session_prepare3 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.1257195/test-141] TEST 145: Sub-test: Walk command tree for '___session_prepare3' (command: session_prepare) [db: /tmp/vpn-switch-arch-test.1257195/test-144] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 8 injectable nodes (combinators/batches) in tree Skipped: Could not select target node for injection TEST 146: Batch Transitive Hull: ___stop0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.1257195/test-144] TEST 147: Sub-test: Walk command tree for '___stop0' (command: stop) [db: /tmp/vpn-switch-arch-test.1257195/test-146] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 148: Sub-test: Inject failure at node '___stop0' (node 1/2) [db: /tmp/vpn-switch-arch-test.1257195/test-146] ✓ KEEP_GOING affects output: fail-fast=4 lines, continue=4 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 149: Batch Transitive Hull: ___phases_sync1 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.1257195/test-146] TEST 150: Sub-test: Walk command tree for '___phases_sync1' (command: phases_sync) [db: /tmp/vpn-switch-arch-test.1257195/test-149] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 151: Sub-test: Inject failure at node '___phases_sync0' (node 1/2) [db: /tmp/vpn-switch-arch-test.1257195/test-149] ✓ KEEP_GOING affects output: fail-fast=3 lines, continue=3 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 152: Batch Transitive Hull: ___phases_sync0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.1257195/test-149] TEST 153: Sub-test: Walk command tree for '___phases_sync0' (command: phases_sync) [db: /tmp/vpn-switch-arch-test.1257195/test-152] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 154: Sub-test: Inject failure at node '___phases_sync0' (node 1/2) [db: /tmp/vpn-switch-arch-test.1257195/test-152] ✓ KEEP_GOING affects output: fail-fast=3 lines, continue=3 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 155: Batch Transitive Hull: ___list0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.1257195/test-152] TEST 156: Sub-test: Walk command tree for '___list0' (command: list) [db: /tmp/vpn-switch-arch-test.1257195/test-155] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 157: Sub-test: Inject failure at node '___list0' (node 1/2) [db: /tmp/vpn-switch-arch-test.1257195/test-155] ✓ KEEP_GOING affects output: fail-fast=2 lines, continue=2 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 158: Batch Transitive Hull: ___bootstrap2 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.1257195/test-155] TEST 159: Sub-test: Walk command tree for '___bootstrap2' (command: bootstrap) [db: /tmp/vpn-switch-arch-test.1257195/test-158] ✓ Command tree collected: 2 nodes in transitive hull ✓ Found 6 injectable nodes (combinators/batches) in tree Skipped: Could not select target node for injection TEST 160: Batch Transitive Hull: ___init1 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.1257195/test-158] TEST 161: Sub-test: Walk command tree for '___init1' (command: init) [db: /tmp/vpn-switch-arch-test.1257195/test-160] ✓ Command tree collected: 2 nodes in transitive hull ✓ Found 1 injectable nodes (combinators/batches) in tree TEST 162: Sub-test: Inject failure at node '__init0' (node 1/1) [db: /tmp/vpn-switch-arch-test.1257195/test-160] ✓ KEEP_GOING affects output: fail-fast=1 lines, continue=1 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 163: Batch Transitive Hull: ___dumpenv1 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.1257195/test-160] TEST 164: Sub-test: Walk command tree for '___dumpenv1' (command: dumpenv) [db: /tmp/vpn-switch-arch-test.1257195/test-163] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 8 injectable nodes (combinators/batches) in tree Skipped: Could not select target node for injection TEST 165: Batch Transitive Hull: ___dump0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.1257195/test-163] TEST 166: Sub-test: Walk command tree for '___dump0' (command: dump) [db: /tmp/vpn-switch-arch-test.1257195/test-165] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 167: Sub-test: Inject failure at node '___dump0' (node 1/2) [db: /tmp/vpn-switch-arch-test.1257195/test-165] ✓ KEEP_GOING affects output: fail-fast=17 lines, continue=17 lines Note: No clear error stop indicator in fail-fast mode ✓ KEEP_GOING=1: Execution completed despite injected failure TEST 168: Batch Transitive Hull: ___batch0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.1257195/test-165] TEST 169: Sub-test: Walk command tree for '___batch0' (command: batch) [db: /tmp/vpn-switch-arch-test.1257195/test-168] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 170: Sub-test: Inject failure at node '___batch0' (node 1/2) [db: /tmp/vpn-switch-arch-test.1257195/test-168] ✓ KEEP_GOING affects output: fail-fast=2 lines, continue=2 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 171: Batch Transitive Hull: ___environment_inspect0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.1257195/test-168] TEST 172: Sub-test: Walk command tree for '___environment_inspect0' (command: environment_inspect) [db: /tmp/vpn-switch-arch-test.1257195/test-171] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 173: Sub-test: Inject failure at node '___environment_inspect0' (node 1/2) [db: /tmp/vpn-switch-arch-test.1257195/test-171] ✓ KEEP_GOING affects output: fail-fast=3 lines, continue=3 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 174: Batch Transitive Hull: ___inspect0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.1257195/test-171] TEST 175: Sub-test: Walk command tree for '___inspect0' (command: inspect) [db: /tmp/vpn-switch-arch-test.1257195/test-174] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 176: Sub-test: Inject failure at node '___inspect0' (node 1/2) [db: /tmp/vpn-switch-arch-test.1257195/test-174] ✓ KEEP_GOING affects output: fail-fast=12 lines, continue=12 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 177: Batch Transitive Hull: ___openvpn_create1 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.1257195/test-174] TEST 178: Sub-test: Walk command tree for '___openvpn_create1' (command: openvpn_create) [db: /tmp/vpn-switch-arch-test.1257195/test-177] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 8 injectable nodes (combinators/batches) in tree Skipped: Could not select target node for injection TEST 179: Batch Transitive Hull: ___openvpn_stop0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.1257195/test-177] TEST 180: Sub-test: Walk command tree for '___openvpn_stop0' (command: openvpn_stop) [db: /tmp/vpn-switch-arch-test.1257195/test-179] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 1 injectable nodes (combinators/batches) in tree TEST 181: Sub-test: Inject failure at node '___openvpn_stop0' (node 1/1) [db: /tmp/vpn-switch-arch-test.1257195/test-179] ✓ KEEP_GOING affects output: fail-fast=1 lines, continue=1 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 182: Batch Transitive Hull: ___openvpn_inspect0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.1257195/test-179] TEST 183: Sub-test: Walk command tree for '___openvpn_inspect0' (command: openvpn_inspect) [db: /tmp/vpn-switch-arch-test.1257195/test-182] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 184: Sub-test: Inject failure at node '___openvpn_inspect0' (node 1/2) [db: /tmp/vpn-switch-arch-test.1257195/test-182] ✓ KEEP_GOING affects output: fail-fast=7 lines, continue=7 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 185: Batch Transitive Hull: ___openvpn_clean0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.1257195/test-182] TEST 186: Sub-test: Walk command tree for '___openvpn_clean0' (command: openvpn_clean) [db: /tmp/vpn-switch-arch-test.1257195/test-185] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 3 injectable nodes (combinators/batches) in tree Skipped: Could not select target node for injection TEST 187: Batch Transitive Hull: ___openvpn_dump0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.1257195/test-185] TEST 188: Sub-test: Walk command tree for '___openvpn_dump0' (command: openvpn_dump) [db: /tmp/vpn-switch-arch-test.1257195/test-187] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 189: Sub-test: Inject failure at node '___openvpn_dump0' (node 1/2) [db: /tmp/vpn-switch-arch-test.1257195/test-187] ✓ KEEP_GOING affects output: fail-fast=20 lines, continue=20 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 190: Batch Transitive Hull: ___session_dump0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.1257195/test-187] TEST 191: Sub-test: Walk command tree for '___session_dump0' (command: session_dump) [db: /tmp/vpn-switch-arch-test.1257195/test-190] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 192: Sub-test: Inject failure at node '___session_dump0' (node 1/2) [db: /tmp/vpn-switch-arch-test.1257195/test-190] ✓ KEEP_GOING affects output: fail-fast=41 lines, continue=41 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 193: Batch Transitive Hull: ___session_inspect0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.1257195/test-190] TEST 194: Sub-test: Walk command tree for '___session_inspect0' (command: session_inspect) [db: /tmp/vpn-switch-arch-test.1257195/test-193] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 195: Sub-test: Inject failure at node '___session_inspect0' (node 1/2) [db: /tmp/vpn-switch-arch-test.1257195/test-193] ✓ KEEP_GOING affects output: fail-fast=5 lines, continue=5 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 196: Batch Transitive Hull: ___validate0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.1257195/test-193] TEST 197: Sub-test: Walk command tree for '___validate0' (command: validate) [db: /tmp/vpn-switch-arch-test.1257195/test-196] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 198: Sub-test: Inject failure at node '___validate0' (node 1/2) [db: /tmp/vpn-switch-arch-test.1257195/test-196] ✓ KEEP_GOING affects output: fail-fast=10 lines, continue=10 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 199: Batch Transitive Hull: ___wireguard_create1 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.1257195/test-196] TEST 200: Sub-test: Walk command tree for '___wireguard_create1' (command: wireguard_create) [db: /tmp/vpn-switch-arch-test.1257195/test-199] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 8 injectable nodes (combinators/batches) in tree Skipped: Could not select target node for injection TEST 201: Batch Transitive Hull: ___wireguard_inspect0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.1257195/test-199] TEST 202: Sub-test: Walk command tree for '___wireguard_inspect0' (command: wireguard_inspect) [db: /tmp/vpn-switch-arch-test.1257195/test-201] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 203: Sub-test: Inject failure at node '___wireguard_inspect0' (node 1/2) [db: /tmp/vpn-switch-arch-test.1257195/test-201] ✓ KEEP_GOING affects output: fail-fast=7 lines, continue=7 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 204: Batch Transitive Hull: ___wireguard_stop0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.1257195/test-201] TEST 205: Sub-test: Walk command tree for '___wireguard_stop0' (command: wireguard_stop) [db: /tmp/vpn-switch-arch-test.1257195/test-204] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 1 injectable nodes (combinators/batches) in tree TEST 206: Sub-test: Inject failure at node '___wireguard_stop0' (node 1/1) [db: /tmp/vpn-switch-arch-test.1257195/test-204] ✓ KEEP_GOING affects output: fail-fast=1 lines, continue=1 lines Note: No clear error stop indicator in fail-fast mode Note: No clear completion indicator in continue mode TEST 207: Batch Transitive Hull: ___wireguard_clean0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.1257195/test-204] TEST 208: Sub-test: Walk command tree for '___wireguard_clean0' (command: wireguard_clean) [db: /tmp/vpn-switch-arch-test.1257195/test-207] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 3 injectable nodes (combinators/batches) in tree Skipped: Could not select target node for injection TEST 209: Batch Transitive Hull: ___wireguard_clean1 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.1257195/test-207] TEST 210: Sub-test: Walk command tree for '___wireguard_clean1' (command: wireguard_clean) [db: /tmp/vpn-switch-arch-test.1257195/test-209] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 3 injectable nodes (combinators/batches) in tree Skipped: Could not select target node for injection TEST 211: Batch Transitive Hull: ___wireguard_dump0 - walkthrough-based error injection [db: /tmp/vpn-switch-arch-test.1257195/test-209] TEST 212: Sub-test: Walk command tree for '___wireguard_dump0' (command: wireguard_dump) [db: /tmp/vpn-switch-arch-test.1257195/test-211] ✓ Command tree collected: 1 nodes in transitive hull ✓ Found 2 injectable nodes (combinators/batches) in tree TEST 213: Sub-test: Inject failure at node '___wireguard_dump0' (node 1/2) [db: /tmp/vpn-switch-arch-test.1257195/test-211] ✓ KEEP_GOING affects output: fail-fast=42 lines, continue=42 lines Note: No clear error stop indicator in fail-fast mode ✓ KEEP_GOING=1: Execution completed despite injected failure Running Batch Combinator KEEP_GOING Precise Tests ======================================== Testing ALL batch combinators with precise architectural KEEP_GOING validation Found 26 batch combinator functions TEST 214: Batch KEEP_GOING Precise: ___session_prepare3 [db: /tmp/vpn-switch-arch-test.1257195/test-211] ✓ Captured 143 command lines from ___session_prepare3 ✓ Selected 59 random line(s) for failure injection Skipped: No functions were injected with failures TEST 215: Batch KEEP_GOING Precise: ___stop0 [db: /tmp/vpn-switch-arch-test.1257195/test-214] ✓ Captured 2 command lines from ___stop0 ✓ Selected 2 random line(s) for failure injection ✓ Injected failures into 2 function(s) Note: Not all commands attempted (2/3) Note: This may indicate KEEP_GOING=0 or execution stopped early Skipped: ___phases_sync1 (requires phase template setup) Skipped: ___phases_sync0 (requires phase template setup) TEST 216: Batch KEEP_GOING Precise: ___list0 [db: /tmp/vpn-switch-arch-test.1257195/test-215] ✓ Captured 2 command lines from ___list0 ✓ Selected 1 random line(s) for failure injection ✓ Injected failures into 1 function(s) ✓ KEEP_GOING=1: All commands attempted (2/2) TEST 217: Batch KEEP_GOING Precise: ___bootstrap2 [db: /tmp/vpn-switch-arch-test.1257195/test-216] ✓ Captured 73 command lines from ___bootstrap2 ✓ Selected 14 random line(s) for failure injection Skipped: No functions were injected with failures Skipped: ___init1 (complex initialization logic) TEST 218: Batch KEEP_GOING Precise: ___dumpenv1 [db: /tmp/vpn-switch-arch-test.1257195/test-217] ✓ Captured 143 command lines from ___dumpenv1 ✓ Selected 43 random line(s) for failure injection Skipped: No functions were injected with failures TEST 219: Batch KEEP_GOING Precise: ___dump0 [db: /tmp/vpn-switch-arch-test.1257195/test-218] ✓ Captured 5 command lines from ___dump0 ✓ Selected 1 random line(s) for failure injection ✓ Injected failures into 1 function(s) Note: Not all commands attempted (3/5) Note: This may indicate KEEP_GOING=0 or execution stopped early TEST 220: Batch KEEP_GOING Precise: ___batch0 [db: /tmp/vpn-switch-arch-test.1257195/test-219] ✓ Captured 2 command lines from ___batch0 ✓ Selected 2 random line(s) for failure injection Skipped: No functions were injected with failures TEST 221: Batch KEEP_GOING Precise: ___environment_inspect0 [db: /tmp/vpn-switch-arch-test.1257195/test-220] ✓ Captured 2 command lines from ___environment_inspect0 ✓ Selected 2 random line(s) for failure injection ✓ Injected failures into 2 function(s) Note: Not all commands attempted (2/3) Note: This may indicate KEEP_GOING=0 or execution stopped early TEST 222: Batch KEEP_GOING Precise: ___inspect0 [db: /tmp/vpn-switch-arch-test.1257195/test-221] ✓ Captured 12 command lines from ___inspect0 ✓ Selected 1 random line(s) for failure injection ✓ Injected failures into 1 function(s) Note: Not all commands attempted (10/12) Note: This may indicate KEEP_GOING=0 or execution stopped early TEST 223: Batch KEEP_GOING Precise: ___openvpn_create1 [db: /tmp/vpn-switch-arch-test.1257195/test-222] ✓ Captured 143 command lines from ___openvpn_create1 ✓ Selected 76 random line(s) for failure injection Skipped: No functions were injected with failures TEST 224: Batch KEEP_GOING Precise: ___openvpn_stop0 [db: /tmp/vpn-switch-arch-test.1257195/test-223] ✓ Captured 1 command lines from ___openvpn_stop0 ✓ Selected 1 random line(s) for failure injection Skipped: No functions were injected with failures TEST 225: Batch KEEP_GOING Precise: ___openvpn_inspect0 [db: /tmp/vpn-switch-arch-test.1257195/test-224] ✓ Captured 3 command lines from ___openvpn_inspect0 ✓ Selected 3 random line(s) for failure injection Skipped: No functions were injected with failures TEST 226: Batch KEEP_GOING Precise: ___openvpn_clean0 [db: /tmp/vpn-switch-arch-test.1257195/test-225] ✓ Captured 3 command lines from ___openvpn_clean0 ✓ Selected 1 random line(s) for failure injection Skipped: No functions were injected with failures TEST 227: Batch KEEP_GOING Precise: ___openvpn_dump0 [db: /tmp/vpn-switch-arch-test.1257195/test-226] ✓ Captured 13 command lines from ___openvpn_dump0 ✓ Selected 3 random line(s) for failure injection Skipped: No functions were injected with failures TEST 228: Batch KEEP_GOING Precise: ___session_dump0 [db: /tmp/vpn-switch-arch-test.1257195/test-227] ✓ Captured 40 command lines from ___session_dump0 ✓ Selected 29 random line(s) for failure injection Skipped: No functions were injected with failures TEST 229: Batch KEEP_GOING Precise: ___session_inspect0 [db: /tmp/vpn-switch-arch-test.1257195/test-228] ✓ Captured 4 command lines from ___session_inspect0 ✓ Selected 1 random line(s) for failure injection ✓ Injected failures into 1 function(s) Note: Not all commands attempted (3/4) Note: This may indicate KEEP_GOING=0 or execution stopped early TEST 230: Batch KEEP_GOING Precise: ___validate0 [db: /tmp/vpn-switch-arch-test.1257195/test-229] ✓ Captured 10 command lines from ___validate0 ✓ Selected 9 random line(s) for failure injection ✓ Injected failures into 9 function(s) ✓ KEEP_GOING=1: All commands attempted (10/10) TEST 231: Batch KEEP_GOING Precise: ___wireguard_create1 [db: /tmp/vpn-switch-arch-test.1257195/test-230] ✓ Captured 143 command lines from ___wireguard_create1 ✓ Selected 113 random line(s) for failure injection Skipped: No functions were injected with failures TEST 232: Batch KEEP_GOING Precise: ___wireguard_inspect0 [db: /tmp/vpn-switch-arch-test.1257195/test-231] ✓ Captured 3 command lines from ___wireguard_inspect0 ✓ Selected 3 random line(s) for failure injection Skipped: No functions were injected with failures TEST 233: Batch KEEP_GOING Precise: ___wireguard_stop0 [db: /tmp/vpn-switch-arch-test.1257195/test-232] ✓ Captured 1 command lines from ___wireguard_stop0 ✓ Selected 1 random line(s) for failure injection Skipped: No functions were injected with failures TEST 234: Batch KEEP_GOING Precise: ___wireguard_clean0 [db: /tmp/vpn-switch-arch-test.1257195/test-233] ✓ Captured 9 command lines from ___wireguard_clean0 ✓ Selected 7 random line(s) for failure injection Skipped: No functions were injected with failures TEST 235: Batch KEEP_GOING Precise: ___wireguard_clean1 [db: /tmp/vpn-switch-arch-test.1257195/test-234] ✓ Captured 9 command lines from ___wireguard_clean1 ✓ Selected 3 random line(s) for failure injection Skipped: No functions were injected with failures TEST 236: Batch KEEP_GOING Precise: ___wireguard_dump0 [db: /tmp/vpn-switch-arch-test.1257195/test-235] ✓ Captured 34 command lines from ___wireguard_dump0 ✓ Selected 27 random line(s) for failure injection Skipped: No functions were injected with failures Running Static Analysis Tests ======================================== Testing architecture violation scanner TEST 237: Architecture Violation Scanner [db: /tmp/vpn-switch-arch-test.1257195/test-236] ✓ Scanner executed successfully (exit code: 0) Found: 1 total violations ✓ Scanner detection working (violations found as expected) ✓ Scanner detects MODIFY_* variable usage Running Read-Only Database Tests ======================================== Testing that functions don't modify database at generation time TEST 238: Read-Only Database: All functions [db: /tmp/vpn-switch-arch-test.1257195/test-236] Testing terminal functions... ✓ _session_create1: No permission errors on read-only database ✓ _interface_destroy1: No permission errors on read-only database ✓ _session_populate3: No permission errors on read-only database ✓ _link2: No permission errors on read-only database ✓ _remove1: No permission errors on read-only database ✓ _error1: No permission errors on read-only database ✓ _error2: No permission errors on read-only database ✓ _error3: No permission errors on read-only database ✓ _fail2: No permission errors on read-only database ✓ _log1: No permission errors on read-only database ✓ _log2: No permission errors on read-only database ✓ _log3: No permission errors on read-only database ✓ _lift1: No permission errors on read-only database ✓ _lift3: No permission errors on read-only database Warning: setenv2: output differs between writable/readonly (but compliant) ✓ _setenv2: No permission errors on read-only database ✓ _getenv1: No permission errors on read-only database ✓ _unsetenv1: No permission errors on read-only database ✓ _printenv0: No permission errors on read-only database Warning: status0: output differs between writable/readonly (but compliant) ✓ _status0: No permission errors on read-only database ✓ _help0: No permission errors on read-only database ✓ _help1: No permission errors on read-only database Warning: database_enumerate0: output differs between writable/readonly (but compliant) ✓ _database_enumerate0: No permission errors on read-only database ✓ _system_inspect0: No permission errors on read-only database Warning: logs_inspect0: output differs between writable/readonly (but compliant) ✓ _logs_inspect0: No permission errors on read-only database ✓ _phases_inspect0: No permission errors on read-only database ✓ _summary_inspect0: No permission errors on read-only database ✓ _prologue_inspect0: No permission errors on read-only database ✓ _openvpn_patch2: No permission errors on read-only database ✓ _openvpn_configure1: No permission errors on read-only database ✓ _openvpn_connect1: No permission errors on read-only database ✓ _openvpn_disconnect1: No permission errors on read-only database ✓ _openvpn_patch1: No permission errors on read-only database Warning: openvpn_enumerate0: output differs between writable/readonly (but compliant) ✓ _openvpn_enumerate0: No permission errors on read-only database ✓ _openvpn_import1: No permission errors on read-only database ✓ _openvpn_list0: No permission errors on read-only database ✓ _openvpn_list1: No permission errors on read-only database ✓ _openvpn_add1: No permission errors on read-only database ✓ _openvpn_add3: No permission errors on read-only database ✓ _openvpn_link2: No permission errors on read-only database ✓ _openvpn_remove1: No permission errors on read-only database ✓ _openvpn_remove2: No permission errors on read-only database ✓ _openvpn_validate0: No permission errors on read-only database ✓ _openvpn_info1: No permission errors on read-only database ✓ _session_list0: No permission errors on read-only database ✓ _session_show1: No permission errors on read-only database ✓ _session_remove1: No permission errors on read-only database ✓ _session_connect1: No permission errors on read-only database ✓ _session_save0: No permission errors on read-only database ✓ _session_save1: No permission errors on read-only database ✓ _session_clean0: No permission errors on read-only database ✓ _session_validate0: No permission errors on read-only database ✓ _session_enumerate0: No permission errors on read-only database ✓ _session_describe0: No permission errors on read-only database ✓ _logs_validate0: No permission errors on read-only database ✓ _logs_clean0: No permission errors on read-only database ✓ _phases_validate0: No permission errors on read-only database ✓ _database_validate0: No permission errors on read-only database ✓ _binaries_validate0: No permission errors on read-only database ✓ _network_validate0: No permission errors on read-only database ✓ _permissions_validate0: No permission errors on read-only database ✓ _environment_validate0: No permission errors on read-only database ✓ _wireguard_patch2: No permission errors on read-only database ✓ _wireguard_configure1: No permission errors on read-only database ✓ _wireguard_connect1: No permission errors on read-only database ✓ _wireguard_disconnect1: No permission errors on read-only database Warning: wireguard_enumerate0: output differs between writable/readonly (but compliant) ✓ _wireguard_enumerate0: No permission errors on read-only database ✓ _wireguard_import1: No permission errors on read-only database ✓ _wireguard_list0: No permission errors on read-only database ✓ _wireguard_list1: No permission errors on read-only database ✓ _wireguard_add1: No permission errors on read-only database ✓ _wireguard_add3: No permission errors on read-only database ✓ _wireguard_link2: No permission errors on read-only database ✓ _wireguard_remove1: No permission errors on read-only database ✓ _wireguard_remove2: No permission errors on read-only database ✓ _wireguard_validate0: No permission errors on read-only database ✓ _wireguard_patch1: No permission errors on read-only database ✓ _wireguard_info1: No permission errors on read-only database Testing combinator functions... ✓ __session_exists1: No permission errors on read-only database ✓ __session_conflicts2: No permission errors on read-only database ✓ __interface_check1: No permission errors on read-only database ✓ __stop1: No permission errors on read-only database ✓ __import1: No permission errors on read-only database ✓ __start1: No permission errors on read-only database ✓ __start0: No permission errors on read-only database ✓ __bootstrap1: No permission errors on read-only database ✓ __environment_cache0: No permission errors on read-only database ✓ __phases_lift1: No permission errors on read-only database ✓ __init0: No permission errors on read-only database ✓ __batch1: No permission errors on read-only database ✓ __restore1: No permission errors on read-only database Warning: openvpn_start0: output differs between writable/readonly (but compliant) ✓ __openvpn_start0: No permission errors on read-only database ✓ __openvpn_start1: No permission errors on read-only database ✓ __openvpn_stop1: No permission errors on read-only database ✓ __openvpn_add2: No permission errors on read-only database ✓ __openvpn_help0: No permission errors on read-only database ✓ __session_disconnect1: No permission errors on read-only database ✓ __session_show0: No permission errors on read-only database ✓ __session_start0: No permission errors on read-only database ✓ __session_start1: No permission errors on read-only database ✓ __session_help0: No permission errors on read-only database ✓ __wireguard_start0: No permission errors on read-only database ✓ __wireguard_start1: No permission errors on read-only database ✓ __wireguard_stop1: No permission errors on read-only database ✓ __wireguard_add2: No permission errors on read-only database ✓ __wireguard_help0: No permission errors on read-only database Testing batch combinator functions... ✓ ___session_prepare3: No permission errors on read-only database ✓ ___stop0: No permission errors on read-only database ✓ ___phases_sync1: No permission errors on read-only database ✓ ___phases_sync0: No permission errors on read-only database ✓ ___list0: No permission errors on read-only database ✓ ___dumpenv1: No permission errors on read-only database ✓ ___dump0: No permission errors on read-only database Warning: batch0: output differs between writable/readonly (but compliant) ✓ ___batch0: No permission errors on read-only database ✓ ___environment_inspect0: No permission errors on read-only database ✓ ___inspect0: No permission errors on read-only database Warning: openvpn_create1: output differs between writable/readonly (but compliant) ✓ ___openvpn_create1: No permission errors on read-only database ✓ ___openvpn_stop0: No permission errors on read-only database ✓ ___openvpn_inspect0: No permission errors on read-only database ✓ ___openvpn_clean0: No permission errors on read-only database ✓ ___openvpn_dump0: No permission errors on read-only database ✓ ___session_dump0: No permission errors on read-only database ✓ ___session_inspect0: No permission errors on read-only database ✓ ___validate0: No permission errors on read-only database Warning: wireguard_create1: output differs between writable/readonly (but compliant) ✓ ___wireguard_create1: No permission errors on read-only database ✓ ___wireguard_inspect0: No permission errors on read-only database ✓ ___wireguard_stop0: No permission errors on read-only database ✓ ___wireguard_clean0: No permission errors on read-only database ✓ ___wireguard_clean1: No permission errors on read-only database ✓ ___wireguard_dump0: No permission errors on read-only database Summary: Tested 129 functions, skipped 8 ======================================== Architecture Test Summary ======================================== Test Functions: 238 Total Assertions: 410 Passed Assertions: 410 Failed Assertions: 0 ALL TESTS PASSED Cleaning up test databases... Done. === vpn-switch Integration Tests === Profile: all ▶ User Story 1: Import → Organize → Dump → Restore → Idempotency (Multi-Protocol) Database: /tmp/vpn-integration-old.EwR4Fg ✓ WG: Imported config 1 ✓ WG: Imported config 2 ✓ WG: Imported config 3 ✓ OVPN: Imported config 1 ✓ OVPN: Imported config 2 ✓ WG: Created category: privacy ✓ WG: Created category: streaming ✓ OVPN: Created group: work ✓ WG: Protocol-level link: quick ✓ WG: Category link: privacy/fast ✓ WG: Category link: privacy/secure ✓ WG: Category link: streaming/hd ✓ OVPN: Protocol-level link: office ✓ OVPN: Group link: work/primary ✓ Dump stderr is clean # ================================ # db: /tmp/vpn-integration-old.EwR4Fg # ================================ ✓ Dump file created ✓ Dump contains WG import ✓ Dump contains OVPN import ✓ Dump contains WG category ✓ Dump contains OVPN group ✓ Dump contains WG link ✓ Dump contains OVPN link Database: /tmp/vpn-integration-new.DRNcVN ✓ NEW WG: Config 1 imported ✓ NEW WG: Config 2 imported ✓ NEW WG: Config 3 imported ✓ NEW WG: Category privacy created ✓ NEW WG: Category streaming created ✓ NEW WG: Protocol-level link ✓ NEW WG: Category link privacy/fast ✓ NEW WG: Category link privacy/secure ✓ NEW WG: Category link streaming/hd ✓ NEW OVPN: Config 1 imported ✓ NEW OVPN: Config 2 imported ✓ NEW OVPN: Group work created ✓ NEW OVPN: Protocol-level link ✓ NEW OVPN: Group link work/primary ✓ Idempotency dump stderr is clean ✓ Idempotency: dump(restore(dump(OLD))) == dump(OLD) [multi-protocol] ✓ Story 1 completed successfully ▶ User Story 2: Session Management: Save → Dump → Restore → Verify (Multi-Protocol) Database: /tmp/vpn-integration-old.cSns7n ✓ WG: Named session created: work -> ../.session/685873 ✓ OVPN: Named session created: home -> ../.session/691939 ✓ Dump stderr is clean ✓ Dump contains WG session patch ✓ Dump contains OVPN session patch ✓ Dump contains WG save command ✓ Dump contains OVPN save command Database: /tmp/vpn-integration-new.0urjrC ✓ NEW: WG config imported ✓ NEW: OVPN config imported ✓ NEW: WG session dump contains patch + save commands ✓ NEW: OVPN session dump contains patch + save commands ✓ Story 2 completed successfully ▶ User Story 3: Config Expiry: Import → Organize → Check Status Database: /tmp/vpn-integration-test.26AStV ✓ Info output contains fresh config ✓ Info output contains old config ✓ Validate command found no issues (acceptable) ✓ Story 3 completed successfully ▶ User Story 4: Multi-Category Organization: Complex Structure (Multi-Protocol) Database: /tmp/vpn-integration-test.A0y7mp ✓ WG: Category: usa ✓ WG: Category: europe ✓ WG: Category: asia ✓ WG: Category: work ✓ WG: Category: personal ✓ OVPN: Group: corporate ✓ OVPN: Group: remote ✓ WG: usa/ny → wg-us-ny.conf ✓ WG: europe/uk → wg-eu-uk.conf ✓ WG: asia/jp → wg-asia-jp.conf ✓ WG: work/office → wg-us-ny.conf ✓ WG: personal/home → wg-us-sf.conf ✓ OVPN: corporate/us → us-office.ovpn ✓ OVPN: corporate/eu → eu-office.ovpn ✓ OVPN: remote/home → home-server.ovpn ✓ WG: default → wg-us-ny.conf ✓ WG: fast → wg-us-sf.conf ✓ OVPN: quick → us-office.ovpn ✓ WG: List shows usa category ✓ WG: List shows europe category ✓ WG: List shows work category ✓ OVPN: List shows corporate group ✓ OVPN: List shows remote group ✓ Story 4 completed successfully ▶ User Story 5: Completeness & Deletion Proof: Comprehensive State Tracking (Multi-Protocol) Database: /tmp/vpn-integration-test.zFQYPi ✓ Dump stderr is clean ✓ Completeness: All 26 operations present in dump (WG: 15, OVPN: 11) ✓ Deletion phase 1 dump stderr is clean ✓ Deletion: WG protocol link 'quick' removed from dump ✓ Deletion: OVPN protocol link 'office' removed from dump ✓ Deletion: WG protocol link 'default' still present ✓ Deletion: WG category 'privacy' still present ✓ Deletion: WG category 'work' still present ✓ Deletion: OVPN group 'corporate' still present ✓ Deletion phase 2 dump stderr is clean ✓ Deletion: WG category link 'privacy/fast' removed from dump ✓ Deletion: WG category link 'work/office' removed from dump ✓ Deletion: OVPN group link 'corporate/primary' removed from dump ✓ Deletion: WG category link 'privacy/secure' still present ✓ Deletion: WG category link 'streaming/hd' still present ✓ Deletion: OVPN group link 'corporate/secondary' still present ✓ Deletion: WG config wg-us-101.conf still present ✓ Deletion: WG config wg-de-303.conf still present ✓ Deletion: OVPN config us-server.ovpn still present ✓ Deletion phase 3 dump stderr is clean ✓ Deletion: WG config wg-jp-404.conf removed from dump ✓ Deletion: WG config wg-au-505.conf removed from dump ✓ Deletion: OVPN config asia-server.ovpn removed from dump ✓ Deletion: WG config wg-us-101.conf still present after removals ✓ Deletion: WG config wg-uk-202.conf still present after removals ✓ Deletion: WG config wg-de-303.conf still present after removals ✓ Deletion: OVPN config us-server.ovpn still present after removals ✓ Deletion: OVPN config eu-server.ovpn still present after removals ✓ Deletion: Empty WG category 'privacy' still present ✓ Deletion: Empty WG category 'work' still present ✓ Deletion: Empty WG category 'streaming' still present ✓ Deletion: OVPN group 'corporate' still present (has link) ✓ Deletion: Empty OVPN group 'remote' still present ✓ Story 5 completed successfully ▶ User Story 6: Dump Quality: Cleanliness, Pipeability, Executability, Transcript Reproducibility Database: /tmp/vpn-quality-test.hjbaD5 ✓ Property 1: Dump stderr is completely empty ✓ Property 2: Dump output is syntactically valid shell script ✓ Property 3: Direct pipe works (exit code 0) ✓ Property 3: Direct pipe produces identical output ✓ Property 4: All informational output is properly commented ✓ Property 5: All transcript commands present in dump (reproducibility) Database: /tmp/vpn-quality-restore.KwOost ✓ Property 6: Dump is restorable (executable) ✓ Property 6: WG config restored ✓ Property 6: OVPN config restored ✓ Property 6: WG category restored ✓ Property 6: OVPN group restored ✓ Property 6: WG link restored ✓ Property 6: OVPN link restored ✓ Property 7: Normalized idempotency verified (dump(restore(dump)) == dump) ✓ Property 8: No duplicate protocol commands in dump (6 unique) ✓ Story 6 completed successfully ▶ User Story 7: Phase-Based Script Generation (WireGuard and OpenVPN) Database: /tmp/vpn-phase-gen.jsazd3 ✓ WG: Extract session ID from start output ✓ WG: connect.sh exists ✓ WG: disconnect.sh exists ✓ WG: connect.sh has correct permissions (0750) ✓ WG: disconnect.sh has correct permissions (0750) ✓ WG: connect.sh is executable ✓ WG: disconnect.sh is executable ✓ WG: connect.sh has shebang ✓ WG: disconnect.sh has shebang ✓ OVPN: Extract session ID from start output ✓ OVPN: connect.sh exists ✓ OVPN: disconnect.sh exists ✓ OVPN: connect.sh has correct permissions (0750) ✓ OVPN: disconnect.sh has correct permissions (0750) ✓ OVPN: connect.sh is executable ✓ OVPN: disconnect.sh is executable ✓ OVPN: connect.sh has shebang ✓ OVPN: disconnect.sh has shebang ✓ WG: Session metadata exists (protocol) ✓ WG: Session metadata exists (interface) ✓ OVPN: Session metadata exists (protocol) ✓ OVPN: Session metadata exists (interface) ✓ WG and OVPN sessions are independent (different PIDs) ✓ Story 7 completed successfully ▶ User Story 8: Phase Script Content Verification (Structure and Commands) Database: /tmp/vpn-phase-content.5cxQMT ✓ WG connect: Has title ✓ WG connect: Has generation timestamp ✓ WG connect: Has session ID ✓ WG connect: Has context documentation ✓ WG connect: Has session_dir variable ✓ WG connect: Has protocol variable ✓ WG connect: Has interface variable ✓ WG connect: Has config_path variable ✓ WG connect: Has dns_server variable ✓ WG connect: Has remote_ips variable ✓ WG connect: Has firewall verify function ✓ WG connect: Has vpn verify function ✓ WG connect: Has dns verify function ✓ WG connect: Firewall prepare phase ✓ WG connect: Firewall execute phase ✓ WG connect: VPN prepare phase ✓ WG connect: VPN execute phase ✓ WG connect: DNS prepare phase ✓ WG connect: DNS execute phase ✓ WG connect: Has wg-quick up command ✓ WG connect: Correct phase order ✓ WG disconnect: Has title ✓ WG disconnect: Has session_dir variable ✓ WG disconnect: Has dns verify function ✓ WG disconnect: Has vpn verify function ✓ WG disconnect: Has firewall verify function ✓ WG disconnect: Has wg-quick down command ✓ WG disconnect: Correct reversed phase order ✓ OVPN connect: Has title ✓ OVPN connect: Has generation timestamp ✓ OVPN connect: Has session_dir variable ✓ OVPN connect: Has protocol variable ✓ OVPN connect: Has interface variable ✓ OVPN connect: Has config_path variable ✓ OVPN connect: Has firewall verify function ✓ OVPN connect: Has vpn verify function ✓ OVPN connect: Has dns verify function ✓ OVPN connect: Has openvpn command ✓ OVPN connect: Has daemon flag ✓ OVPN connect: Correct phase order ✓ OVPN disconnect: Has title ✓ OVPN disconnect: Has session_dir variable ✓ OVPN disconnect: Has process kill command ✓ OVPN disconnect: Correct reversed phase order ✓ WG connect: No OpenVPN commands ✓ WG connect: No OpenVPN daemon flag ✓ OVPN connect: No WireGuard commands ✓ Story 8 completed successfully ▶ User Story 9: Phase Customization (Reorder, Add, Skip) Database: /tmp/vpn-phase-custom.DhXT3Q ✓ Baseline: Default phase order ✓ Reordered: Custom phase order ✓ Custom phase: Has verify function ✓ Custom phase: Has prepare section ✓ Custom phase: Has execute section ✓ Custom phase: Correct order with routing ✓ Minimal: Has vpn verify function ✓ Minimal: No firewall phase ✓ Minimal: No dns phase ✓ Minimal: Only VPN phase ✓ Custom disconnect: Has dns phase ✓ Custom disconnect: Has vpn phase ✓ Custom disconnect: No firewall phase ✓ Custom disconnect: Only dns and vpn ✓ Multi-custom: Has logging phase ✓ Multi-custom: Has monitoring phase ✓ Multi-custom: Correct custom order ✓ Story 9 completed successfully ▶ User Story 10: Multi-Protocol Phase Support (Isolation and Simultaneous Operation) Database: /tmp/vpn-phase-multi.2CFoXI ✓ WG: Default phase order ✓ OVPN: Default phase order ✓ WG: Has WireGuard command ✓ WG: No OpenVPN commands ✓ OVPN: Has OpenVPN command ✓ OVPN: No WireGuard commands ✓ WG: Correct protocol variable ✓ WG: WireGuard interface naming ✓ WG: Has dns_server context ✓ WG: Has remote_ips context ✓ OVPN: Correct protocol variable ✓ OVPN: OpenVPN interface naming ✓ WG custom: Has custom phase ✓ WG custom: Has custom phase in order ✓ OVPN: No WireGuard custom phase ✓ OVPN: Default phases only ✓ WG: No OpenVPN custom phase ✓ WG: Default phases only ✓ OVPN: Protocol-specific phase config not yet supported ✓ OVPN: Uses default phases (protocol-specific config not implemented) ✓ Simultaneous: WG session exists ✓ Simultaneous: OVPN session exists ✓ Simultaneous: Different session IDs ✓ Simultaneous: WG has correct protocol ✓ Simultaneous: OVPN has correct protocol ✓ Story 10 completed successfully ▶ User Story 11: Multi-Protocol Edge Cases (Stress, Switching, Robustness) Database: /tmp/vpn-edge-cases.QLqOFg ✓ Scenario 1.1: Duplicate WG import correctly rejected ✓ Scenario 1.1: Duplicate OVPN import correctly rejected ✓ Scenario 1.1: WG includes wg_custom phase ✓ Scenario 1.1: WG excludes ovpn_custom phase ✓ Scenario 1.1: OVPN includes ovpn_custom phase ✓ Scenario 1.1: OVPN excludes wg_custom phase ✓ Scenario 1.1: Phase order differs between protocols ✓ Scenario 1.2: WireGuard test interface configured ✓ Scenario 1.2: OpenVPN test interface configured ✓ Scenario 1.2: Two sessions active simultaneously ✓ Scenario 1.2: WG session uses wg_test* interface ✓ Scenario 1.2: OVPN session uses tun_test* interface ✓ Scenario 1.2: Unreferenced sessions cleaned, 'latest' preserved ✓ Scenario 1.3: WG session has DNS config ✓ Scenario 1.3: Connect scripts differ despite same DNS ✓ Scenario 2.1: WG session created ✓ Scenario 2.1: WG session stopped, 'latest' preserved ✓ Scenario 2.1: OVPN session created after WG stop ✓ Scenario 2.1: New session is OpenVPN protocol ✓ Scenario 2.2: Both sessions coexist ✓ Scenario 2.2: Both protocols running simultaneously ✓ Scenario 2.3: Cycle 1 - WG started ✓ Scenario 2.3: Cycle 1 - WG stopped, 'latest' preserved ✓ Scenario 2.3: Cycle 2 - OVPN started (old session + new) ✓ Scenario 2.3: Cycle 2 - OVPN stopped, unreferenced cleaned ✓ Scenario 2.3: Cycle 3 - WG started (old session + new) ✓ Scenario 2.3: Both sessions present (unreferenced + latest) ✓ Scenario 3.1: WG session saved as wg_work ✓ Scenario 3.1: Both sessions active after resume ✓ Scenario 3.1: Correct protocols after resume ✓ Scenario 3.2: Session 'work' points to WG session ✓ Scenario 3.2: Session 'work' now points to OVPN (overwrite) ✓ Scenario 3.2: Only one 'work' session exists (no duplicates) ✓ Scenario 4.1: Two active sessions before dump ✓ Scenario 4.1: Dump file created with active sessions ✓ Scenario 4.1: Dump excludes .session directory (transient) ✓ Scenario 4.1: Dump includes WG configs ✓ Scenario 4.1: Dump includes OVPN configs Database: /tmp/vpn-restore-a.cnZpBh Database: /tmp/vpn-restore-b.ani40q ✓ Scenario 4.2: Restored database has WG config ✓ Scenario 4.2: Restored database has no active sessions ✓ Scenario 5.1: Only 'latest' WG session after 10 cycles ✓ Scenario 5.1: Only 'latest' OVPN session after 10 cycles ✓ Scenario 5.1: Only latest session directory remains ✓ Story 11 completed successfully ▶ User Story 12: Phase Backend Selection (Strategy 7 - Automatic Template Lifting) Database: /tmp/vpn-backend-selection.YfFEMj ✓ Backend template lifted: firewall/pf.sh ✓ Backend template lifted: firewall/ipfw.sh ✓ Backend template lifted: dns/resolvconf.sh ✓ Backend template lifted: dns/unbound.sh ✓ Scenario 1: Connect script generated ✓ Scenario 1: PF firewall backend used (contains pfctl) ✓ Scenario 1: Resolvconf DNS backend used ✓ Scenario 2: IPFW firewall backend used (contains ipfw) ✓ Scenario 2: Unbound DNS backend used ✓ Scenario 2: PF firewall phase not used (backend isolated) ✓ Scenario 3: Backward compat - connect script generated ✓ Scenario 3: Backward compat - script not empty ✓ Scenario 3: Uses protocol-specific phases (wireguard/) ✓ Scenario 4: Both backends from @base profile used ✓ Scenario 5: Variant-only syntax works (uses default profile) ✓ Scenario 6: Mixed syntax - ipfw backend used ✓ Scenario 6: Mixed syntax - vpn phase executed ✓ Scenario 6: Mixed syntax - traditional dns phase used ✓ Story 12 completed successfully ======================================== Test Summary ======================================== User Stories: 12 Passed: 12 Failed: 0 Assertions: 296 Passed: 296 Failed: 0 ALL STORIES PASSED === vpn-switch Integration Tests === Profile: minimal ▶ User Story 1: Import → Organize → Dump → Restore → Idempotency (Multi-Protocol) Database: /tmp/vpn-integration-old.DAQXfU ✓ WG: Imported config 1 ✓ WG: Imported config 2 ✓ WG: Imported config 3 ✓ OVPN: Imported config 1 ✓ OVPN: Imported config 2 ✓ WG: Created category: privacy ✓ WG: Created category: streaming ✓ OVPN: Created group: work ✓ WG: Protocol-level link: quick ✓ WG: Category link: privacy/fast ✓ WG: Category link: privacy/secure ✓ WG: Category link: streaming/hd ✓ OVPN: Protocol-level link: office ✓ OVPN: Group link: work/primary ✓ Dump stderr is clean # ================================ # db: /tmp/vpn-integration-old.DAQXfU # ================================ ✓ Dump file created ✓ Dump contains WG import ✓ Dump contains OVPN import ✓ Dump contains WG category ✓ Dump contains OVPN group ✓ Dump contains WG link ✓ Dump contains OVPN link Database: /tmp/vpn-integration-new.bcrmNn ✓ NEW WG: Config 1 imported ✓ NEW WG: Config 2 imported ✓ NEW WG: Config 3 imported ✓ NEW WG: Category privacy created ✓ NEW WG: Category streaming created ✓ NEW WG: Protocol-level link ✓ NEW WG: Category link privacy/fast ✓ NEW WG: Category link privacy/secure ✓ NEW WG: Category link streaming/hd ✓ NEW OVPN: Config 1 imported ✓ NEW OVPN: Config 2 imported ✓ NEW OVPN: Group work created ✓ NEW OVPN: Protocol-level link ✓ NEW OVPN: Group link work/primary ✓ Idempotency dump stderr is clean ✓ Idempotency: dump(restore(dump(OLD))) == dump(OLD) [multi-protocol] ✓ Story 1 completed successfully ▶ User Story 2: Session Management: Save → Dump → Restore → Verify (Multi-Protocol) Database: /tmp/vpn-integration-old.5Mb1iw ✓ WG: Named session created: work -> ../.session/175260 ✓ OVPN: Named session created: home -> ../.session/179743 ✓ Dump stderr is clean ✓ Dump contains WG session patch ✓ Dump contains OVPN session patch ✓ Dump contains WG save command ✓ Dump contains OVPN save command Database: /tmp/vpn-integration-new.gkqpff ✓ NEW: WG config imported ✓ NEW: OVPN config imported ✓ NEW: WG session dump contains patch + save commands ✓ NEW: OVPN session dump contains patch + save commands ✓ Story 2 completed successfully ▶ User Story 3: Config Expiry: Import → Organize → Check Status Database: /tmp/vpn-integration-test.iw61qP ✓ Info output contains fresh config ✓ Info output contains old config ✓ Validate command found no issues (acceptable) ✓ Story 3 completed successfully ▶ User Story 4: Multi-Category Organization: Complex Structure (Multi-Protocol) Database: /tmp/vpn-integration-test.qGVcgU ✓ WG: Category: usa ✓ WG: Category: europe ✓ WG: Category: asia ✓ WG: Category: work ✓ WG: Category: personal ✓ OVPN: Group: corporate ✓ OVPN: Group: remote ✓ WG: usa/ny → wg-us-ny.conf ✓ WG: europe/uk → wg-eu-uk.conf ✓ WG: asia/jp → wg-asia-jp.conf ✓ WG: work/office → wg-us-ny.conf ✓ WG: personal/home → wg-us-sf.conf ✓ OVPN: corporate/us → us-office.ovpn ✓ OVPN: corporate/eu → eu-office.ovpn ✓ OVPN: remote/home → home-server.ovpn ✓ WG: default → wg-us-ny.conf ✓ WG: fast → wg-us-sf.conf ✓ OVPN: quick → us-office.ovpn ✓ WG: List shows usa category ✓ WG: List shows europe category ✓ WG: List shows work category ✓ OVPN: List shows corporate group ✓ OVPN: List shows remote group ✓ Story 4 completed successfully ▶ User Story 5: Completeness & Deletion Proof: Comprehensive State Tracking (Multi-Protocol) Database: /tmp/vpn-integration-test.wfmoq2 ✓ Dump stderr is clean ✓ Completeness: All 26 operations present in dump (WG: 15, OVPN: 11) ✓ Deletion phase 1 dump stderr is clean ✓ Deletion: WG protocol link 'quick' removed from dump ✓ Deletion: OVPN protocol link 'office' removed from dump ✓ Deletion: WG protocol link 'default' still present ✓ Deletion: WG category 'privacy' still present ✓ Deletion: WG category 'work' still present ✓ Deletion: OVPN group 'corporate' still present ✓ Deletion phase 2 dump stderr is clean ✓ Deletion: WG category link 'privacy/fast' removed from dump ✓ Deletion: WG category link 'work/office' removed from dump ✓ Deletion: OVPN group link 'corporate/primary' removed from dump ✓ Deletion: WG category link 'privacy/secure' still present ✓ Deletion: WG category link 'streaming/hd' still present ✓ Deletion: OVPN group link 'corporate/secondary' still present ✓ Deletion: WG config wg-us-101.conf still present ✓ Deletion: WG config wg-de-303.conf still present ✓ Deletion: OVPN config us-server.ovpn still present ✓ Deletion phase 3 dump stderr is clean ✓ Deletion: WG config wg-jp-404.conf removed from dump ✓ Deletion: WG config wg-au-505.conf removed from dump ✓ Deletion: OVPN config asia-server.ovpn removed from dump ✓ Deletion: WG config wg-us-101.conf still present after removals ✓ Deletion: WG config wg-uk-202.conf still present after removals ✓ Deletion: WG config wg-de-303.conf still present after removals ✓ Deletion: OVPN config us-server.ovpn still present after removals ✓ Deletion: OVPN config eu-server.ovpn still present after removals ✓ Deletion: Empty WG category 'privacy' still present ✓ Deletion: Empty WG category 'work' still present ✓ Deletion: Empty WG category 'streaming' still present ✓ Deletion: OVPN group 'corporate' still present (has link) ✓ Deletion: Empty OVPN group 'remote' still present ✓ Story 5 completed successfully ▶ User Story 6: Dump Quality: Cleanliness, Pipeability, Executability, Transcript Reproducibility Database: /tmp/vpn-quality-test.YKevGE ✓ Property 1: Dump stderr is completely empty ✓ Property 2: Dump output is syntactically valid shell script ✓ Property 3: Direct pipe works (exit code 0) ✓ Property 3: Direct pipe produces identical output ✓ Property 4: All informational output is properly commented ✓ Property 5: All transcript commands present in dump (reproducibility) Database: /tmp/vpn-quality-restore.G4TsGd ✓ Property 6: Dump is restorable (executable) ✓ Property 6: WG config restored ✓ Property 6: OVPN config restored ✓ Property 6: WG category restored ✓ Property 6: OVPN group restored ✓ Property 6: WG link restored ✓ Property 6: OVPN link restored ✓ Property 7: Normalized idempotency verified (dump(restore(dump)) == dump) ✓ Property 8: No duplicate protocol commands in dump (6 unique) ✓ Story 6 completed successfully ▶ User Story 7: Phase-Based Script Generation (WireGuard and OpenVPN) Database: /tmp/vpn-phase-gen.7qmAHp ✓ WG: Extract session ID from start output ✓ WG: connect.sh exists ✓ WG: disconnect.sh exists ✓ WG: connect.sh has correct permissions (0750) ✓ WG: disconnect.sh has correct permissions (0750) ✓ WG: connect.sh is executable ✓ WG: disconnect.sh is executable ✓ WG: connect.sh has shebang ✓ WG: disconnect.sh has shebang ✓ OVPN: Extract session ID from start output ✓ OVPN: connect.sh exists ✓ OVPN: disconnect.sh exists ✓ OVPN: connect.sh has correct permissions (0750) ✓ OVPN: disconnect.sh has correct permissions (0750) ✓ OVPN: connect.sh is executable ✓ OVPN: disconnect.sh is executable ✓ OVPN: connect.sh has shebang ✓ OVPN: disconnect.sh has shebang ✓ WG: Session metadata exists (protocol) ✓ WG: Session metadata exists (interface) ✓ OVPN: Session metadata exists (protocol) ✓ OVPN: Session metadata exists (interface) ✓ WG and OVPN sessions are independent (different PIDs) ✓ Story 7 completed successfully ▶ User Story 8: Phase Script Content Verification (Structure and Commands) Database: /tmp/vpn-phase-content.BCZuWF ✓ WG connect: Has title ✓ WG connect: Has generation timestamp ✓ WG connect: Has session ID ✓ WG connect: Has context documentation ✓ WG connect: Has session_dir variable ✓ WG connect: Has protocol variable ✓ WG connect: Has interface variable ✓ WG connect: Has config_path variable ✓ WG connect: Has dns_server variable ✓ WG connect: Has remote_ips variable ✓ WG connect: Has firewall verify function ✓ WG connect: Has vpn verify function ✓ WG connect: Has dns verify function ✓ WG connect: Firewall prepare phase ✓ WG connect: Firewall execute phase ✓ WG connect: VPN prepare phase ✓ WG connect: VPN execute phase ✓ WG connect: DNS prepare phase ✓ WG connect: DNS execute phase ✓ WG connect: Has wg-quick up command ✓ WG connect: Correct phase order ✓ WG disconnect: Has title ✓ WG disconnect: Has session_dir variable ✓ WG disconnect: Has dns verify function ✓ WG disconnect: Has vpn verify function ✓ WG disconnect: Has firewall verify function ✓ WG disconnect: Has wg-quick down command ✓ WG disconnect: Correct reversed phase order ✓ OVPN connect: Has title ✓ OVPN connect: Has generation timestamp ✓ OVPN connect: Has session_dir variable ✓ OVPN connect: Has protocol variable ✓ OVPN connect: Has interface variable ✓ OVPN connect: Has config_path variable ✓ OVPN connect: Has firewall verify function ✓ OVPN connect: Has vpn verify function ✓ OVPN connect: Has dns verify function ✓ OVPN connect: Has openvpn command ✓ OVPN connect: Has daemon flag ✓ OVPN connect: Correct phase order ✓ OVPN disconnect: Has title ✓ OVPN disconnect: Has session_dir variable ✓ OVPN disconnect: Has process kill command ✓ OVPN disconnect: Correct reversed phase order ✓ WG connect: No OpenVPN commands ✓ WG connect: No OpenVPN daemon flag ✓ OVPN connect: No WireGuard commands ✓ Story 8 completed successfully ▶ User Story 9: Phase Customization (Reorder, Add, Skip) Database: /tmp/vpn-phase-custom.Yn7hlG ✓ Baseline: Default phase order ✓ Reordered: Custom phase order ✓ Custom phase: Has verify function ✓ Custom phase: Has prepare section ✓ Custom phase: Has execute section ✓ Custom phase: Correct order with routing ✓ Minimal: Has vpn verify function ✓ Minimal: No firewall phase ✓ Minimal: No dns phase ✓ Minimal: Only VPN phase ✓ Custom disconnect: Has dns phase ✓ Custom disconnect: Has vpn phase ✓ Custom disconnect: No firewall phase ✓ Custom disconnect: Only dns and vpn ✓ Multi-custom: Has logging phase ✓ Multi-custom: Has monitoring phase ✓ Multi-custom: Correct custom order ✓ Story 9 completed successfully ▶ User Story 10: Multi-Protocol Phase Support (Isolation and Simultaneous Operation) Database: /tmp/vpn-phase-multi.nlhKDy ✓ WG: Default phase order ✓ OVPN: Default phase order ✓ WG: Has WireGuard command ✓ WG: No OpenVPN commands ✓ OVPN: Has OpenVPN command ✓ OVPN: No WireGuard commands ✓ WG: Correct protocol variable ✓ WG: WireGuard interface naming ✓ WG: Has dns_server context ✓ WG: Has remote_ips context ✓ OVPN: Correct protocol variable ✓ OVPN: OpenVPN interface naming ✓ WG custom: Has custom phase ✓ WG custom: Has custom phase in order ✓ OVPN: No WireGuard custom phase ✓ OVPN: Default phases only ✓ WG: No OpenVPN custom phase ✓ WG: Default phases only ✓ OVPN: Protocol-specific phase config not yet supported ✓ OVPN: Uses default phases (protocol-specific config not implemented) ✓ Simultaneous: WG session exists ✓ Simultaneous: OVPN session exists ✓ Simultaneous: Different session IDs ✓ Simultaneous: WG has correct protocol ✓ Simultaneous: OVPN has correct protocol ✓ Story 10 completed successfully ▶ User Story 11: Multi-Protocol Edge Cases (Stress, Switching, Robustness) Database: /tmp/vpn-edge-cases.C8owMz ✓ Scenario 1.1: Duplicate WG import correctly rejected ✓ Scenario 1.1: Duplicate OVPN import correctly rejected ✓ Scenario 1.1: WG includes wg_custom phase ✓ Scenario 1.1: WG excludes ovpn_custom phase ✓ Scenario 1.1: OVPN includes ovpn_custom phase ✓ Scenario 1.1: OVPN excludes wg_custom phase ✓ Scenario 1.1: Phase order differs between protocols ✓ Scenario 1.2: WireGuard test interface configured ✓ Scenario 1.2: OpenVPN test interface configured ✓ Scenario 1.2: Two sessions active simultaneously ✓ Scenario 1.2: WG session uses wg_test* interface ✓ Scenario 1.2: OVPN session uses tun_test* interface ✓ Scenario 1.2: Unreferenced sessions cleaned, 'latest' preserved ✓ Scenario 1.3: WG session has DNS config ✓ Scenario 1.3: Connect scripts differ despite same DNS ✓ Scenario 2.1: WG session created ✓ Scenario 2.1: WG session stopped, 'latest' preserved ✓ Scenario 2.1: OVPN session created after WG stop ✓ Scenario 2.1: New session is OpenVPN protocol ✓ Scenario 2.2: Both sessions coexist ✓ Scenario 2.2: Both protocols running simultaneously ✓ Scenario 2.3: Cycle 1 - WG started ✓ Scenario 2.3: Cycle 1 - WG stopped, 'latest' preserved ✓ Scenario 2.3: Cycle 2 - OVPN started (old session + new) ✓ Scenario 2.3: Cycle 2 - OVPN stopped, unreferenced cleaned ✓ Scenario 2.3: Cycle 3 - WG started (old session + new) ✓ Scenario 2.3: Both sessions present (unreferenced + latest) ✓ Scenario 3.1: WG session saved as wg_work ✓ Scenario 3.1: Both sessions active after resume ✓ Scenario 3.1: Correct protocols after resume ✓ Scenario 3.2: Session 'work' points to WG session ✓ Scenario 3.2: Session 'work' now points to OVPN (overwrite) ✓ Scenario 3.2: Only one 'work' session exists (no duplicates) ✓ Scenario 4.1: Two active sessions before dump ✓ Scenario 4.1: Dump file created with active sessions ✓ Scenario 4.1: Dump excludes .session directory (transient) ✓ Scenario 4.1: Dump includes WG configs ✓ Scenario 4.1: Dump includes OVPN configs Database: /tmp/vpn-restore-a.JhGoAt Database: /tmp/vpn-restore-b.R7n007 ✓ Scenario 4.2: Restored database has WG config ✓ Scenario 4.2: Restored database has no active sessions ✓ Scenario 5.1: Only 'latest' WG session after 10 cycles ✓ Scenario 5.1: Only 'latest' OVPN session after 10 cycles ✓ Scenario 5.1: Only latest session directory remains ✓ Story 11 completed successfully ▶ User Story 12: Phase Backend Selection (Strategy 7 - Automatic Template Lifting) Database: /tmp/vpn-backend-selection.39SCS1 ✓ Backend template lifted: firewall/pf.sh ✓ Backend template lifted: firewall/ipfw.sh ✓ Backend template lifted: dns/resolvconf.sh ✓ Backend template lifted: dns/unbound.sh ✓ Scenario 1: Connect script generated ✓ Scenario 1: PF firewall backend used (contains pfctl) ✓ Scenario 1: Resolvconf DNS backend used ✓ Scenario 2: IPFW firewall backend used (contains ipfw) ✓ Scenario 2: Unbound DNS backend used ✓ Scenario 2: PF firewall phase not used (backend isolated) ✓ Scenario 3: Backward compat - connect script generated ✓ Scenario 3: Backward compat - script not empty ✓ Scenario 3: Uses protocol-specific phases (wireguard/) ✓ Scenario 4: Both backends from @base profile used ✓ Scenario 5: Variant-only syntax works (uses default profile) ✓ Scenario 6: Mixed syntax - ipfw backend used ✓ Scenario 6: Mixed syntax - vpn phase executed ✓ Scenario 6: Mixed syntax - traditional dns phase used ✓ Story 12 completed successfully ======================================== Test Summary ======================================== User Stories: 12 Passed: 12 Failed: 0 Assertions: 296 Passed: 296 Failed: 0 ALL STORIES PASSED ======================================== vpn-switch Unit Test Suite (Formalized) ======================================== Running Tests ======================================== Filter active - running only:test_header test_summary test_setup test_printenv_command test_status_command test_wireguard_import_valid test_wireguard_add_category test_wireguard_link_create test_wireguard_list test_wireguard_validate test_wireguard_info test_wireguard_start_basic test_wireguard_connect_resume test_wireguard_stop_basic test_session_list test_session_show test_session_remove test_session_save_default test_session_save_named test_session_start_default test_session_start_named test_session_start_bypid test_session_stop_named test_session_stop_bypid test_session_stop_inactive test_wireguard_remove_config_in_use test_wireguard_remove_config_with_refs test_wireguard_remove_symlink test_wireguard_remove_category_link test_wireguard_clean_no_broken test_wireguard_clean_broken_protocol_link test_wireguard_clean_broken_category_link test_wireguard_clean_category_no_broken test_wireguard_clean_category_with_broken test_wireguard_validate_broken_symlink test_wireguard_validate_broken_category_symlink test_wireguard_validate_naming_conflict test_wireguard_validate_invalid_config test_stop_no_sessions test_stop_specific_interface test_wireguard_disconnect_interface test_stop_nonexistent_interface test_disconnect_without_session test_stop_twice_idempotent test_wireguard_import_nonexistent test_wireguard_import_duplicate test_wireguard_add_category_conflict test_wireguard_add_link_conflict test_wireguard_link_conflict test_error_invalid_category test_error_broken_symlink test_error_invalid_command test_edge_duplicate_instance_prevention test_edge_stale_session_cleanup test_wireguard_patch_valid test_wireguard_patch_nonexistent test_wireguard_patch_absolute test_wireguard_info_category test_session_save_default test_session_save_named test_session_start_default test_session_start_named test_session_start_by_pid test_protocol_agnostic_import_wireguard test_protocol_agnostic_list test_protocol_agnostic_link test_protocol_agnostic_remove test_protocol_agnostic_validate test_network_validate test_permissions_validate test_environment_validate test_batch_validate_includes_system test_interpreter_single_underscore test_interpreter_double_underscore test_interpreter_triple_underscore test_interpreter_resolution_priority test_start_wireguard_only test_start_openvpn_only test_start_not_found test_start_no_default test_start_with_default_wireguard test_start_with_default_openvpn test_start_default_invalid_target test_init_extension_links test_database_init test_environment_init test_phases_copy test_phases_lift test_phases_sync_single test_phases_sync_all test_init_batch_combinator test_init_combinator test_start_extension_link_fast_path test_start_multiple_matches test_openvpn_import_valid test_openvpn_list test_openvpn_add_group test_openvpn_link test_openvpn_remove test_openvpn_validate test_openvpn_info test_openvpn_dump test_openvpn_patch_valid test_openvpn_patch_nonexistent test_openvpn_patch_absolute test_openvpn_patch_credentials_bare test_openvpn_patch_credentials_existing test_openvpn_patch_credentials_missing test_openvpn_start_basic test_openvpn_stop_basic test_openvpn_disconnect_interface test_openvpn_clean test_setenv_basic test_setenv_invalid_name test_getenv_local_override test_getenv_fallback_chain test_unsetenv_existing test_unsetenv_not_set test_dumpenv_prologue test_dumpenv_epilogue test_dumpenv_profile_filtering test_environment_cache_on test_environment_cache_off test_environment_cache_status test_environment_cache_no_args test_cache_invalidation_setenv test_cache_invalidation_unsetenv test_cache_invalidation_environment_init test_dumpenv_cache_preservation test_dumpenv_cache_not_included_when_disabled test_cache_no_recursion test_inspect_batch_complete test_environment_inspect test_system_inspect test_batch_syntax_wireguard_clean test_combinators_literal_variable test_function_classification_correct test_no_terminal_output_vpnswitch_commands test_metadata_function_lists test_combinator_syntax_validation test_error_command_single_line test_error_command_two_lines test_error_command_three_lines test_error_command_ansi_colors test_batch_id_sequential test_store_batch_exits_basic test_store_batch_exits_references test_free_batch_id test_batch_infrastructure_lifecycle TEST 1 (test_batch_id_sequential): get_batch_id - sequential allocation Database: /tmp/vpn-switch-test.2582056/test_1 ✓ First batch ID is 0 ✓ Second batch ID is 1 ✓ Third batch ID is 2 ✓ Counter file has correct value (3) TEST 2 (test_store_batch_exits_basic): store_batch_exits - stores exit codes to file Database: /tmp/vpn-switch-test.2582056/test_2 ✓ Batch file created ✓ Batch file has correct content TEST 3 (test_store_batch_exits_references): store_batch_exits - stores exit codes with batch references Database: /tmp/vpn-switch-test.2582056/test_3 ✓ Batch file stores references correctly TEST 4 (test_free_batch_id): free_batch_id - deletes batch file Database: /tmp/vpn-switch-test.2582056/test_4 ✓ Batch file exists before cleanup ✓ Batch file deleted after cleanup TEST 5 (test_batch_infrastructure_lifecycle): Batch infrastructure - full allocation/store/free lifecycle Database: /tmp/vpn-switch-test.2582056/test_5 ✓ Allocated batch ID: 0 ✓ Batch results stored ✓ Batch results readable ✓ Batch cleaned up successfully TEST 6 (test_printenv_command): printenv - basic environment display Database: /tmp/vpn-switch-test.2582056/test_6 ✓ Printenv command executed and shows header ✓ Printenv shows VPN_SWITCH_BASE variable TEST 7 (test_status_command): status - VPN status display Database: /tmp/vpn-switch-test.2582056/test_7 ✓ Status command shows header ✓ Status shows disconnected state ✓ Status checks network interfaces TEST 8 (test_error_command_single_line): error command - single line message Database: /tmp/vpn-switch-test.2582056/test_8 ✓ error command outputs printf with 'Error:' prefix ✓ error command outputs exit 1 ✓ error command redirects to stderr TEST 9 (test_error_command_two_lines): error command - two line message Database: /tmp/vpn-switch-test.2582056/test_9 ✓ error command first line has 'Error:' prefix ✓ error command second line is indented without 'Error:' prefix ✓ error command outputs exit 1 TEST 10 (test_error_command_three_lines): error command - three line message Database: /tmp/vpn-switch-test.2582056/test_10 ✓ error command first line has 'Error:' prefix ✓ error command has properly indented continuation lines ✓ error command includes all three message lines ✓ error command outputs exit 1 TEST 11 (test_error_command_ansi_colors): error command - ANSI color support Database: /tmp/vpn-switch-test.2582056/test_11 ✓ error command includes ANSI escape codes when enabled ✓ error command includes ANSI reset code TEST 12 (test_wireguard_list): wireguard list - display configurations Database: /tmp/vpn-switch-test.2582056/test_12 ✓ Configuration section header displayed ✓ Config files section displayed ✓ Imported config file listed TEST 13 (test_wireguard_validate): wireguard validate - validate clean configuration Database: /tmp/vpn-switch-test.2582056/test_13 ✓ Validation header displayed ✓ No issues found in clean configuration TEST 14 (test_wireguard_info): wireguard info - display category information Database: /tmp/vpn-switch-test.2582056/test_14 ✓ Category header displayed ✓ Category path displayed ✓ Contents section displayed ✓ Category contents listed with symlink arrows TEST 15 (test_wireguard_import_valid): wireguard import - import valid config Database: /tmp/vpn-switch-test.2582056/test_15 ✓ Config file imported to database ✓ Permissions set to 0400 (read-only) TEST 16 (test_wireguard_add_category): wireguard add - create category with permissions Database: /tmp/vpn-switch-test.2582056/test_16 ✓ Category directory created ✓ Permissions set to 0755 TEST 17 (test_wireguard_link_create): wireguard link - create symlink in protocol directory Database: /tmp/vpn-switch-test.2582056/test_17 ✓ Symlink created ✓ Symlink points to correct relative path (./wg-TEST-RS-1.conf) TEST 18 (test_wireguard_start_basic): wireguard start - create session and connect to VPN Database: /tmp/vpn-switch-test.2582056/test_18 ✓ Session creation logged ✓ wg-quick command in connect.sh ✓ Session directory created in .session/ ✓ Session metadata files created ✓ connect.sh script generated ✓ connect.sh is executable ✓ connect.sh documents original config with relative path ✓ Patched config (wg_test13.conf) created ✓ Patched config correctly strips PostUp hook (phase-based DNS) ✓ Patched config correctly strips PostDown hook (phase-based DNS) TEST 19 (test_wireguard_connect_resume): wireguard connect - resume existing session by ID Database: /tmp/vpn-switch-test.2582056/test_19 ✓ wireguard connect generated wg-quick command in connect.sh ✓ wireguard connect generated pfctl command in connect.sh ✓ wireguard connect used session configuration ✓ connect.sh preserved after connect TEST 20 (test_wireguard_stop_basic): stop - disconnect active VPN session Database: /tmp/vpn-switch-test.2582056/test_20 ✓ Session exists before stop ✓ disconnect.sh contains wg-quick down command ✓ Stop command executed ✓ Session preserved after stop (has 'latest' link) TEST 21 (test_session_list): session list - display active and stale sessions Database: /tmp/vpn-switch-test.2582056/test_21 ✓ Session list header displayed ✓ Active session (PID 2839183) listed ✓ Stale session (PID 99997) listed ✓ Stale session (dead process) marked as stopped TEST 22 (test_session_show): session show - display connect script Database: /tmp/vpn-switch-test.2582056/test_22 ✓ Extracted session ID (2868124) from start command output ✓ Session ID displayed in header ✓ Session protocol displayed ✓ Connect script contents displayed TEST 23 (test_session_remove): session remove - remove stale, refuse active Database: /tmp/vpn-switch-test.2582056/test_23 ✓ Stale session created for removal test ✓ Removal operation logged for stale session ✓ Active session (PID 2582056) created for refusal test ✓ Refuses to remove active session (PID 2582056) TEST 24 (test_session_save_default): session save - save current session as default Database: /tmp/vpn-switch-test.2582056/test_24 ✓ Default session symlink created ✓ Default symlink points to correct session TEST 25 (test_session_save_named): session save work - save with custom name Database: /tmp/vpn-switch-test.2582056/test_25 ✓ Named session symlink created ✓ Named symlink points to correct session TEST 26 (test_session_start_default): session start - resume default session Database: /tmp/vpn-switch-test.2582056/test_26 ✓ Connect script created before stopping ✓ Session directory kept for resumption (referenced) ✓ Default symlink persists after stop ✓ Session start executed successfully TEST 27 (test_session_start_named): session start work - resume named session Database: /tmp/vpn-switch-test.2582056/test_27 ✓ Named symlink persists after stop ✓ Named session start executed successfully TEST 28 (test_session_start_bypid): session start - resume session by PID Database: /tmp/vpn-switch-test.2582056/test_28 ✓ Mock session (PID 11111) created for PID resume test ✓ Session start resumes by explicit PID (11111) TEST 29 (test_session_stop_named): session stop work - stop active named session Database: /tmp/vpn-switch-test.2582056/test_29 ✓ Session stop resolves named session 'work' TEST 30 (test_session_stop_bypid): session stop - stop active session by PID Database: /tmp/vpn-switch-test.2582056/test_30 ✓ Session stop handles PID (88888) TEST 31 (test_session_stop_inactive): session stop - inactive session should log (not error) Database: /tmp/vpn-switch-test.2582056/test_31 ✓ Session stop handles inactive session gracefully TEST 32 (test_wireguard_remove_config_in_use): wireguard remove - refuse removal when config in use Database: /tmp/vpn-switch-test.2582056/test_32 ✓ Active session (PID 2582056) created using config ✓ Error message when config in use by session ✓ Error suggests removing session first TEST 33 (test_wireguard_remove_config_with_refs): wireguard remove - refuse removal when config has symlink refs Database: /tmp/vpn-switch-test.2582056/test_33 ✓ Category symlink created (privacy/rm2) ✓ Error message when config has symlink references ✓ Error lists symlink references TEST 34 (test_wireguard_remove_symlink): wireguard remove - remove symlink (no safety checks) Database: /tmp/vpn-switch-test.2582056/test_34 ✓ Test symlink created ✓ Symlink removal operation logged ✓ Symlink was removed TEST 35 (test_wireguard_remove_category_link): wireguard remove - remove link from category Database: /tmp/vpn-switch-test.2582056/test_35 ✓ Category link (privacy/rm4) created ✓ Category link removal operation logged ✓ Category link was removed TEST 36 (test_wireguard_clean_no_broken): wireguard clean - no broken links found Database: /tmp/vpn-switch-test.2582056/test_36 ✓ Clean header displayed ✓ No broken symlinks message displayed ✓ Usage hint displayed TEST 37 (test_wireguard_clean_broken_protocol_link): wireguard clean - detect and generate remove for broken protocol link Database: /tmp/vpn-switch-test.2582056/test_37 ✓ Broken protocol symlink created for testing ✓ Remove command generated for broken protocol link ✓ Command includes link name TEST 38 (test_wireguard_clean_broken_category_link): wireguard clean - detect and generate remove for broken category link Database: /tmp/vpn-switch-test.2582056/test_38 ✓ Broken category symlink created for testing ✓ Remove command generated for broken category link ✓ Command includes category name TEST 39 (test_wireguard_clean_category_no_broken): wireguard clean privacy - category with no broken links Database: /tmp/vpn-switch-test.2582056/test_39 ✓ Category-specific header displayed ✓ No broken symlinks message for category TEST 40 (test_wireguard_clean_category_with_broken): wireguard clean privacy - category with broken links Database: /tmp/vpn-switch-test.2582056/test_40 ✓ Broken symlink created in privacy category ✓ Remove command generated for category link ✓ Category-specific clean (not global) TEST 41 (test_wireguard_validate_broken_symlink): wireguard validate - detect broken symlinks Database: /tmp/vpn-switch-test.2582056/test_41 ✓ Broken symlink created for validation test ✓ Broken symlink detected in protocol directory ✓ Error status reported TEST 42 (test_wireguard_validate_broken_category_symlink): wireguard validate - detect broken symlinks in categories Database: /tmp/vpn-switch-test.2582056/test_42 ✓ Broken category symlink created for validation test ✓ Broken symlink detected in category TEST 43 (test_wireguard_validate_naming_conflict): wireguard validate - detect naming conflicts Database: /tmp/vpn-switch-test.2582056/test_43 ✓ Naming conflict created (file + directory) ✓ Naming conflict detected TEST 44 (test_wireguard_validate_invalid_config): wireguard validate - detect invalid config files Database: /tmp/vpn-switch-test.2582056/test_44 ✓ Empty config file created for validation test ✓ Empty config file detected ✓ Missing [Interface] section detected TEST 45 (test_stop_no_sessions): stop - no sessions exist (empty output) Database: /tmp/vpn-switch-test.2582056/test_45 ✓ No output or log message when no sessions exist TEST 46 (test_stop_specific_interface): stop wg_test_safe - stop specific interface by name Database: /tmp/vpn-switch-test.2582056/test_46 ✓ Active session (PID 2582056, interface wg_test_safe) created ✓ Stopped specific interface wg_test_safe ✓ Interface wg_test_safe disconnect command generated TEST 47 (test_wireguard_disconnect_interface): wireguard disconnect wg_test_safe - direct disconnect command Database: /tmp/vpn-switch-test.2582056/test_47 ✓ Active session (PID 2582056) created for disconnect test ✓ Disconnect command executed for wg_test_safe ✓ Session PID displayed correctly TEST 48 (test_stop_nonexistent_interface): stop wg_test_other - error when interface not found Database: /tmp/vpn-switch-test.2582056/test_48 ✓ Active session with wg_test_safe interface created ✓ Error message for nonexistent interface TEST 49 (test_disconnect_without_session): disconnect without session - error handling Database: /tmp/vpn-switch-test.2582056/test_49 ✓ Error message when no session exists TEST 50 (test_stop_twice_idempotent): stop twice - idempotent (safe to call multiple times) Database: /tmp/vpn-switch-test.2582056/test_50 ✓ First stop: handles no sessions gracefully ✓ Second stop: still handles no sessions (idempotent) TEST 51 (test_wireguard_import_nonexistent): wireguard import - error when file doesn't exist Database: /tmp/vpn-switch-test.2582056/test_51 ✓ Error message for non-existent file TEST 52 (test_wireguard_import_duplicate): wireguard import - error when config already exists Database: /tmp/vpn-switch-test.2582056/test_52 ✓ First import succeeded ✓ Error message when config already exists TEST 53 (test_wireguard_add_category_conflict): wireguard add - error when category already exists Database: /tmp/vpn-switch-test.2582056/test_53 ✓ First add succeeded (privacy category created) ✓ Error message when category already exists TEST 54 (test_wireguard_add_link_conflict): wireguard add - error when link already exists Database: /tmp/vpn-switch-test.2582056/test_54 ✓ First link created successfully ✓ Error message when link already exists TEST 55 (test_wireguard_link_conflict): wireguard link - error when alias already exists Database: /tmp/vpn-switch-test.2582056/test_55 ✓ Config imported successfully ✓ Error message when alias already exists TEST 56 (test_error_invalid_category): error handling - invalid category shows error Database: /tmp/vpn-switch-test.2582056/test_56 ✓ Error message for invalid category TEST 57 (test_error_broken_symlink): error handling - broken symlink handled gracefully Database: /tmp/vpn-switch-test.2582056/test_57 ✓ Broken symlink created for testing ✓ Handled broken symlink (error or skipped) TEST 58 (test_error_invalid_command): error handling - invalid command shows usage Database: /tmp/vpn-switch-test.2582056/test_58 ✓ Usage/help shown for invalid command TEST 59 (test_edge_duplicate_instance_prevention): edge case - prevent duplicate VPN instances Database: /tmp/vpn-switch-test.2582056/test_59 ✓ First VPN session created (PID 2582056) ✓ Detected existing VPN instance ✓ No duplicate session created TEST 60 (test_edge_stale_session_cleanup): edge case - stale sessions don't block new sessions Database: /tmp/vpn-switch-test.2582056/test_60 ✓ Stale session created for testing ✓ Proceeded with new session (stale session didn't block) ✓ Stale session preserved (manual cleanup via 'session clean' required) TEST 61 (test_wireguard_patch_valid): wireguard patch - displays patched configuration Database: /tmp/vpn-switch-test.2582056/test_61 ✓ Patch output correctly strips PostUp hook (phase-based DNS) ✓ Patch output correctly strips PostDown hook (phase-based DNS) ✓ Patch output preserves [Interface] section ✓ Patch output preserves [Peer] section TEST 62 (test_wireguard_patch_nonexistent): wireguard patch - handles nonexistent config Database: /tmp/vpn-switch-test.2582056/test_62 ✓ Patch rejects nonexistent config with error TEST 63 (test_wireguard_patch_absolute): wireguard patch - handles absolute path Database: /tmp/vpn-switch-test.2582056/test_63 ✓ Patch works with absolute path (strips DNS hooks) TEST 64 (test_wireguard_info_category): wireguard info - displays category information Database: /tmp/vpn-switch-test.2582056/test_64 ✓ Category header displayed ✓ Config count displayed ✓ Link count displayed ✓ Category path displayed ✓ Contents section header displayed ✓ Category contents listed with symlink arrows TEST 65 (test_session_save_default): session save - save current session as default Database: /tmp/vpn-switch-test.2582056/test_65 ✓ Default session symlink created ✓ Default symlink points to correct session TEST 66 (test_session_save_named): session save work - save with custom name Database: /tmp/vpn-switch-test.2582056/test_66 ✓ Named session symlink created ✓ Named symlink points to correct session TEST 67 (test_session_start_default): session start - resume default session Database: /tmp/vpn-switch-test.2582056/test_67 ✓ Connect script created before stopping ✓ Session directory kept for resumption (referenced) ✓ Default symlink persists after stop ✓ Session start executed successfully TEST 68 (test_session_start_named): session start work - resume named session Database: /tmp/vpn-switch-test.2582056/test_68 ✓ Named symlink persists after stop ✓ Named session start executed successfully TEST 69 (test_session_start_by_pid): session start - resume by PID Database: /tmp/vpn-switch-test.2582056/test_69 ✓ Session start by PID executed successfully TEST 70 (test_openvpn_import_valid): openvpn import - import valid .ovpn config Database: /tmp/vpn-switch-test.2582056/test_70 ✓ Config imported to openvpn/ ✓ Permissions set to 0400 TEST 71 (test_openvpn_list): openvpn list - list configs and groups Database: /tmp/vpn-switch-test.2582056/test_71 ✓ Lists config: us-server.ovpn ✓ Lists group: work/ ✓ Lists group link with arity-1: work/office TEST 72 (test_openvpn_add_group): openvpn add - create group Database: /tmp/vpn-switch-test.2582056/test_72 ✓ Group directory created ✓ Group permissions correct (0700) TEST 73 (test_openvpn_link): openvpn link - create protocol-level link Database: /tmp/vpn-switch-test.2582056/test_73 ✓ Protocol-level link created ✓ Link target correct TEST 74 (test_openvpn_remove): openvpn remove - remove config safely Database: /tmp/vpn-switch-test.2582056/test_74 ✓ Config removed ✓ Other config preserved TEST 75 (test_openvpn_validate): openvpn validate - detect broken links Database: /tmp/vpn-switch-test.2582056/test_75 ✓ Broken symlink detected ✓ Valid database passes validation TEST 76 (test_openvpn_info): openvpn info - show group information Database: /tmp/vpn-switch-test.2582056/test_76 ✓ Shows group name ✓ Shows correct link count ✓ Shows link: office TEST 77 (test_openvpn_dump): openvpn dump - export database Database: /tmp/vpn-switch-test.2582056/test_77 ✓ Dump includes import command ✓ Dump includes group creation ✓ Dump includes protocol link ✓ Dump includes group link TEST 78 (test_openvpn_patch_valid): openvpn patch - displays patched configuration Database: /tmp/vpn-switch-test.2582056/test_78 ✓ Patch output correctly strips up script (phase-based DNS) ✓ Patch output correctly strips down script (phase-based DNS) ✓ Patch output contains daemon mode ✓ Patch output contains device interface ✓ Patch output contains writepid directive ✓ Patch output preserves client directive ✓ Patch output preserves remote server TEST 79 (test_openvpn_patch_nonexistent): openvpn patch - handles nonexistent config Database: /tmp/vpn-switch-test.2582056/test_79 ✓ Error message for nonexistent config TEST 80 (test_openvpn_patch_absolute): openvpn patch - handles absolute path Database: /tmp/vpn-switch-test.2582056/test_80 ✓ Absolute path patch works TEST 81 (test_openvpn_patch_credentials_bare): openvpn patch - patches bare auth-user-pass with credentials Database: /tmp/vpn-switch-test.2582056/test_81 ✓ Bare auth-user-pass patched with credentials path ✓ Bare auth-user-pass preserved when no credentials set TEST 82 (test_openvpn_patch_credentials_existing): openvpn patch - preserves existing auth-user-pass path Database: /tmp/vpn-switch-test.2582056/test_82 ✓ Existing auth-user-pass path preserved (not overridden) TEST 83 (test_openvpn_patch_credentials_missing): openvpn patch - handles config without auth-user-pass Database: /tmp/vpn-switch-test.2582056/test_83 ✓ Config without auth-user-pass remains unchanged TEST 84 (test_openvpn_start_basic): openvpn start - create session and connect to VPN Database: /tmp/vpn-switch-test.2582056/test_84 ✓ Session creation logged ✓ openvpn command in connect.sh ✓ Session directory created in .session/ ✓ Session metadata files created ✓ connect.sh script generated ✓ connect.sh is executable ✓ Patched config (tun_test80.ovpn) created ✓ Patched config contains daemon mode ✓ Patched config correctly strips up script (phase-based DNS) ✓ Patched config correctly strips down script (phase-based DNS) TEST 85 (test_openvpn_stop_basic): openvpn stop - cleanup commands for session Database: /tmp/vpn-switch-test.2582056/test_85 ✓ Session created via user interface ✓ Disconnect commands reference correct interface (tun_test85) ✓ Disconnect generates process kill commands TEST 86 (test_openvpn_disconnect_interface): openvpn disconnect - tear down OpenVPN interface Database: /tmp/vpn-switch-test.2582056/test_86 ✓ Disconnect generates process termination commands TEST 87 (test_openvpn_clean): openvpn clean - generate cleanup commands for broken links Database: /tmp/vpn-switch-test.2582056/test_87 ✓ Clean generates remove commands ✓ Clean detected broken symlink TEST 88 (test_protocol_agnostic_import_wireguard): import (protocol-agnostic) - detects WireGuard .conf file Database: /tmp/vpn-switch-test.2582056/test_88 ✓ Protocol-agnostic import detected .conf and delegated to wireguard import ✓ Protocol-agnostic import generates correct cp command TEST 89 (test_protocol_agnostic_list): list (protocol-agnostic) - delegates to all protocols Database: /tmp/vpn-switch-test.2582056/test_89 ✓ Protocol-agnostic list delegated to wireguard list ✓ Protocol-agnostic list shows wireguard config sections ✓ Protocol-agnostic list has no duplicate lines (3 unique) TEST 90 (test_protocol_agnostic_link): link (protocol-agnostic) - creates protocol-level alias Database: /tmp/vpn-switch-test.2582056/test_90 ✓ Protocol-agnostic link generates ln command ✓ Protocol-agnostic link uses correct relative path (./wireguard) ✓ Protocol-agnostic link includes correct alias name TEST 91 (test_protocol_agnostic_remove): remove (protocol-agnostic) - removes protocol-level link Database: /tmp/vpn-switch-test.2582056/test_91 ✓ Protocol-agnostic remove generates rm command ✓ Protocol-agnostic remove includes descriptive comment ✓ Protocol-agnostic remove errors on non-existent link TEST 92 (test_protocol_agnostic_validate): validate (protocol-agnostic) - delegates to all protocols Database: /tmp/vpn-switch-test.2582056/test_92 ✓ Protocol-agnostic validate delegated to wireguard validate ✓ Protocol-agnostic validate shows validation output TEST 93 (test_network_validate): network validate - check network prerequisites Database: /tmp/vpn-switch-test.2582056/test_93 ✓ Network validation header displayed ✓ Network validate passed on clean configuration TEST 94 (test_permissions_validate): permissions validate - check filesystem permissions Database: /tmp/vpn-switch-test.2582056/test_94 ✓ Permissions validation header displayed ✓ Permissions validate passed on clean configuration TEST 95 (test_environment_validate): environment validate - check environment variables Database: /tmp/vpn-switch-test.2582056/test_95 ✓ Environment validation header displayed ✓ Environment validate passed on clean configuration TEST 96 (test_batch_validate_includes_system): validate (batch) - includes system validators Database: /tmp/vpn-switch-test.2582056/test_96 ✓ Batch validate includes database validator ✓ Batch validate includes binaries validator ✓ Batch validate includes phases validator ✓ Batch validate includes network validator ✓ Batch validate includes permissions validator ✓ Batch validate includes environment validator TEST 97 (test_start_wireguard_only): start - auto-detect WireGuard config Database: /tmp/vpn-switch-test.2582056/test_97 ✓ Delegates to wireguard commands for WireGuard-only config TEST 98 (test_start_openvpn_only): start - auto-detect OpenVPN config Database: /tmp/vpn-switch-test.2582056/test_98 ✓ Delegates to openvpn commands for OpenVPN-only config TEST 99 (test_start_not_found): start - error on nonexistent config Database: /tmp/vpn-switch-test.2582056/test_99 ✓ Error message for nonexistent config ✓ Error shows both search locations TEST 100 (test_start_no_default): start - error when no configs exist (Phase 3.4.1) Database: /tmp/vpn-switch-test.2582056/test_100 ✓ Error message when no configs available ✓ Error provides hint to import configs TEST 101 (test_start_with_default_wireguard): start - use default link (WireGuard) via API Database: /tmp/vpn-switch-test.2582056/test_101 ✓ Default session link created via API ✓ Start with no args resolves to default session TEST 102 (test_start_with_default_openvpn): start - use default link (OpenVPN) via API Database: /tmp/vpn-switch-test.2582056/test_102 ✓ Default session link created via API ✓ Start with no args resolves to default session TEST 103 (test_start_default_invalid_target): start - error on invalid default link target Database: /tmp/vpn-switch-test.2582056/test_103 ✓ Error detected for invalid default session target TEST 104 (test_init_extension_links): init - creates protocol extension links (Phase 3.4.1) Database: /tmp/vpn-switch-test.2582056/test_104 ✓ conf link created ✓ ovpn link created ✓ conf → wireguard ✓ ovpn → openvpn TEST 105 (test_start_extension_link_fast_path): start - uses extension link for protocol resolution (Phase 3.4.1) Database: /tmp/vpn-switch-test.2582056/test_105 ✓ Extension link used for fast protocol resolution (wireguard commands found) TEST 106 (test_start_multiple_matches): start - error on multiple protocol matches (Phase 3.4.1) Database: /tmp/vpn-switch-test.2582056/test_106 ✓ Multiple matches error shown ✓ Both matches listed TEST 107 (test_database_init): database init - creates directory structure (Phase 4.4) Database: /tmp/vpn-switch-test.2582056/test_107 ✓ wireguard/ created ✓ openvpn/ created ✓ .session/ created ✓ session/ created ✓ .env/default/ created ✓ .env/local/ created ✓ .include/phase/ created TEST 108 (test_environment_init): environment init - copies profile templates (Phase 4.4) Database: /tmp/vpn-switch-test.2582056/test_108 ✓ minimal profile copied ✓ profile has correct permissions (0600) TEST 109 (test_phases_copy): phases copy - copies phase templates (Phase 4.4) Database: /tmp/vpn-switch-test.2582056/test_109 ✓ wireguard phases copied ✓ openvpn phases copied ✓ wireguard phase subdirs exist TEST 110 (test_phases_lift): phases lift - lifts phase:backend templates (Phase 4.4) Database: /tmp/vpn-switch-test.2582056/test_110 ✓ generates lift command ✓ output file is executable TEST 111 (test_phases_sync_single): phases sync - discovers and lifts backends (Phase 4.4) Database: /tmp/vpn-switch-test.2582056/test_111 ✓ delegates to phases lift TEST 112 (test_phases_sync_all): phases sync - syncs all phases (Phase 4.4) Database: /tmp/vpn-switch-test.2582056/test_112 ✓ delegates to single-phase sync TEST 113 (test_init_batch_combinator): init - orchestrates full initialization (Phase 4.4) Database: /tmp/vpn-switch-test.2582056/test_113 ✓ database init executed ✓ environment init executed ✓ phases copy executed TEST 114 (test_init_combinator): init combinator - delegates to batch combinator (Phase 4.4) Database: /tmp/vpn-switch-test.2582056/test_114 ✓ database created ✓ profile installed TEST 115 (test_setenv_basic): setenv - basic variable setting Database: /tmp/vpn-switch-test.2582056/test_115 ✓ .env/local directory created ✓ Variable file created ✓ Variable has correct value ✓ File has correct permissions (0600 or 0640 for cross-user support) ✓ Shows confirmation message TEST 116 (test_setenv_invalid_name): setenv - invalid variable name Database: /tmp/vpn-switch-test.2582056/test_116 ✓ Rejects invalid variable name ✓ No file created for invalid name TEST 117 (test_getenv_local_override): getenv - shows local override Database: /tmp/vpn-switch-test.2582056/test_117 ✓ Shows local override source ✓ Outputs correct value from local TEST 118 (test_getenv_fallback_chain): getenv - fallback chain (local > default > template) Database: /tmp/vpn-switch-test.2582056/test_118 ✓ Shows error if variable not found ✓ Falls back to .env/default ✓ Falls back to template/environment TEST 119 (test_unsetenv_existing): unsetenv - remove existing variable Database: /tmp/vpn-switch-test.2582056/test_119 ✓ Variable file was removed ✓ Shows confirmation message TEST 120 (test_unsetenv_not_set): unsetenv - variable not set in local Database: /tmp/vpn-switch-test.2582056/test_120 ✓ Shows informative message when not set TEST 121 (test_dumpenv_prologue): dumpenv prologue - outputs safe minimal set Database: /tmp/vpn-switch-test.2582056/test_121 ✓ Prologue includes VPN_SWITCH_TERMINAL_INTERPRETER ✓ Prologue includes VPN_SWITCH_DISPLAY_ANSI ✓ Prologue excludes VPN_SWITCH_INTERPRETER_wireguard_list (epilogue-only) ✓ Prologue excludes VPN_SWITCH_INTERPRETER_wireguard_import1 (epilogue-only) TEST 122 (test_dumpenv_epilogue): dumpenv epilogue - outputs complete set Database: /tmp/vpn-switch-test.2582056/test_122 ✓ Epilogue includes VPN_SWITCH_TERMINAL_INTERPRETER ✓ Epilogue includes VPN_SWITCH_DISPLAY_ANSI ✓ Epilogue includes VPN_SWITCH_INTERPRETER_wireguard_list ✓ Epilogue includes VPN_SWITCH_INTERPRETER_wireguard_import1 TEST 123 (test_dumpenv_profile_filtering): dumpenv - profile filtering prevents restore breakage Database: /tmp/vpn-switch-test.2582056/test_123 ✓ Prologue correctly excludes function-specific interpreter ✓ Epilogue correctly includes function-specific interpreter TEST 124 (test_environment_cache_on): environment cache on - creates cache file with correct permissions Database: /tmp/vpn-switch-test.2582056/test_124 ✓ Cache file created ✓ Cache file has correct permissions (0600) ✓ Shows cache enabled message ✓ Cache file has content TEST 125 (test_environment_cache_off): environment cache off - removes cache file Database: /tmp/vpn-switch-test.2582056/test_125 ✓ Cache file removed ✓ Shows cache disabled message TEST 126 (test_environment_cache_status): environment cache status - shows correct status Database: /tmp/vpn-switch-test.2582056/test_126 ✓ Shows DISABLED status when cache off ✓ Shows ENABLED status when cache on ✓ Shows cached variable count TEST 127 (test_environment_cache_no_args): environment cache (no args) - defaults to status Database: /tmp/vpn-switch-test.2582056/test_127 ✓ Shows status with no arguments TEST 128 (test_cache_invalidation_setenv): setenv - rebuilds cache automatically Database: /tmp/vpn-switch-test.2582056/test_128 ✓ Cache rebuilt automatically after setenv ✓ Rebuilt cache contains new variable TEST_VAR TEST 129 (test_cache_invalidation_unsetenv): unsetenv - rebuilds cache automatically Database: /tmp/vpn-switch-test.2582056/test_129 ✓ Cache rebuilt automatically after unsetenv ✓ Rebuilt cache no longer contains TEST_VAR TEST 130 (test_cache_invalidation_environment_init): environment init - invalidates cache automatically Database: /tmp/vpn-switch-test.2582056/test_130 ✓ Cache file removed after environment init ✓ Shows cache invalidation warning TEST 131 (test_dumpenv_cache_preservation): dumpenv epilogue - includes cache if enabled Database: /tmp/vpn-switch-test.2582056/test_131 ✓ Epilogue includes cache content ✓ Epilogue includes cache restore comment TEST 132 (test_dumpenv_cache_not_included_when_disabled): dumpenv epilogue - excludes cache when disabled Database: /tmp/vpn-switch-test.2582056/test_132 ✓ Epilogue correctly excludes cache when disabled TEST 133 (test_cache_no_recursion): environment cache on - excludes cache file from scan Database: /tmp/vpn-switch-test.2582056/test_133 ✓ Cache correctly excludes itself TEST 134 (test_interpreter_single_underscore): interpreter resolution - single underscore uses TERMINAL_INTERPRETER Database: /tmp/vpn-switch-test.2582056/test_134 # Set VPN_SWITCH_TERMINAL_INTERPRETER (effective next command) ✓ Single underscore function used TERMINAL_INTERPRETER TEST 135 (test_interpreter_double_underscore): interpreter resolution - double underscore uses COMBINATOR_INTERPRETER Database: /tmp/vpn-switch-test.2582056/test_135 # Set VPN_SWITCH_COMBINATOR_INTERPRETER (effective next command) ✓ Double underscore function used COMBINATOR_INTERPRETER TEST 136 (test_interpreter_triple_underscore): interpreter resolution - triple underscore uses BATCH_COMBINATOR_INTERPRETER Database: /tmp/vpn-switch-test.2582056/test_136 # Set VPN_SWITCH_BATCH_COMBINATOR_INTERPRETER (effective next command) ✓ Triple underscore function used BATCH_COMBINATOR_INTERPRETER TEST 137 (test_interpreter_resolution_priority): interpreter resolution - function-specific override beats intrinsic classification Database: /tmp/vpn-switch-test.2582056/test_137 # Set VPN_SWITCH_TERMINAL_INTERPRETER (effective next command) ✓ Function-specific override takes priority over intrinsic classification ✓ Intrinsic classification was correctly bypassed TEST 138 (test_inspect_batch_complete): inspect (batch) - includes all inspection sections Database: /tmp/vpn-switch-test.2582056/test_138 ✓ Batch inspect includes environment section ✓ Batch inspect includes system section ✓ Batch inspect includes WireGuard section ✓ Batch inspect includes OpenVPN section ✓ Batch inspect includes session section ✓ Batch inspect includes phases section TEST 139 (test_environment_inspect): environment inspect - displays environment variables Database: /tmp/vpn-switch-test.2582056/test_139 ✓ Environment inspect shows header ✓ Environment inspect shows VPN_SWITCH_BASE ✓ Environment inspect shows database structure TEST 140 (test_system_inspect): system inspect - displays system configuration Database: /tmp/vpn-switch-test.2582056/test_140 ✓ System inspect shows header ✓ System inspect shows system info section ✓ System inspect shows network interfaces section TEST 141 (test_batch_syntax_wireguard_clean): wireguard clean - validates batch syntax Database: /tmp/vpn-switch-test.2582056/test_141 ✓ wireguard clean outputs valid batch syntax ✓ wireguard clean uses literal $VPN_SWITCH_CONTEXT_SCRIPT TEST 142 (test_combinators_literal_variable): combinators - use literal $VPN_SWITCH_CONTEXT_SCRIPT Database: /tmp/vpn-switch-test.2582056/test_142 ✓ wireguard start uses literal variable ✓ wireguard start variable not expanded TEST 143 (test_combinator_syntax_validation): combinators - validate single-command output syntax Database: /tmp/vpn-switch-test.2582056/test_143 ✓ wireguard start outputs exactly one command ✓ wireguard start uses literal variable ✓ wireguard start variable not expanded ✓ openvpn start outputs exactly one command ✓ start (protocol-agnostic) outputs exactly one command TEST 144 (test_function_classification_correct): function classification - naming matches behavior ✓ wireguard add2 correctly classified as combinator (__) ✓ wireguard clean0 correctly classified as batch (___) ✓ openvpn clean0 correctly classified as batch (___) TEST 145 (test_no_terminal_output_vpnswitch_commands): terminal functions - must not output vpn-switch commands ✓ No terminal functions output vpn-switch commands TEST 146 (test_metadata_function_lists): metadata - function lists accurate after renames ✓ Metadata includes __wireguard_add2 in combinators ✓ Metadata includes ___wireguard_clean0 in batch combinators ✓ Metadata includes ___openvpn_clean0 in batch combinators ======================================== Test Summary ======================================== Test Functions: 146 Total Assertions: 371 Passed Assertions: 371 Failed Assertions: 0 ALL TESTS PASSED ======================================== vpn-switch Unit Test Suite (Formalized) ======================================== Running Tests ======================================== Filter active - running only:test_header test_summary test_setup test_printenv_command test_status_command test_wireguard_import_valid test_wireguard_add_category test_wireguard_link_create test_wireguard_list test_wireguard_validate test_wireguard_info test_wireguard_start_basic test_wireguard_connect_resume test_wireguard_stop_basic test_session_list test_session_show test_session_remove test_session_save_default test_session_save_named test_session_start_default test_session_start_named test_session_start_bypid test_session_stop_named test_session_stop_bypid test_session_stop_inactive test_wireguard_remove_config_in_use test_wireguard_remove_config_with_refs test_wireguard_remove_symlink test_wireguard_remove_category_link test_wireguard_clean_no_broken test_wireguard_clean_broken_protocol_link test_wireguard_clean_broken_category_link test_wireguard_clean_category_no_broken test_wireguard_clean_category_with_broken test_wireguard_validate_broken_symlink test_wireguard_validate_broken_category_symlink test_wireguard_validate_naming_conflict test_wireguard_validate_invalid_config test_stop_no_sessions test_stop_specific_interface test_wireguard_disconnect_interface test_stop_nonexistent_interface test_disconnect_without_session test_stop_twice_idempotent test_wireguard_import_nonexistent test_wireguard_import_duplicate test_wireguard_add_category_conflict test_wireguard_add_link_conflict test_wireguard_link_conflict test_error_invalid_category test_error_broken_symlink test_error_invalid_command test_edge_duplicate_instance_prevention test_edge_stale_session_cleanup test_wireguard_patch_valid test_wireguard_patch_nonexistent test_wireguard_patch_absolute test_wireguard_info_category test_session_save_default test_session_save_named test_session_start_default test_session_start_named test_session_start_by_pid test_protocol_agnostic_import_wireguard test_protocol_agnostic_list test_protocol_agnostic_link test_protocol_agnostic_remove test_protocol_agnostic_validate test_network_validate test_permissions_validate test_environment_validate test_batch_validate_includes_system test_interpreter_single_underscore test_interpreter_double_underscore test_interpreter_triple_underscore test_interpreter_resolution_priority test_start_wireguard_only test_start_openvpn_only test_start_not_found test_start_no_default test_start_with_default_wireguard test_start_with_default_openvpn test_start_default_invalid_target test_init_extension_links test_database_init test_environment_init test_phases_copy test_phases_lift test_phases_sync_single test_phases_sync_all test_init_batch_combinator test_init_combinator test_start_extension_link_fast_path test_start_multiple_matches test_openvpn_import_valid test_openvpn_list test_openvpn_add_group test_openvpn_link test_openvpn_remove test_openvpn_validate test_openvpn_info test_openvpn_dump test_openvpn_patch_valid test_openvpn_patch_nonexistent test_openvpn_patch_absolute test_openvpn_patch_credentials_bare test_openvpn_patch_credentials_existing test_openvpn_patch_credentials_missing test_openvpn_start_basic test_openvpn_stop_basic test_openvpn_disconnect_interface test_openvpn_clean test_setenv_basic test_setenv_invalid_name test_getenv_local_override test_getenv_fallback_chain test_unsetenv_existing test_unsetenv_not_set test_dumpenv_prologue test_dumpenv_epilogue test_dumpenv_profile_filtering test_environment_cache_on test_environment_cache_off test_environment_cache_status test_environment_cache_no_args test_cache_invalidation_setenv test_cache_invalidation_unsetenv test_cache_invalidation_environment_init test_dumpenv_cache_preservation test_dumpenv_cache_not_included_when_disabled test_cache_no_recursion test_inspect_batch_complete test_environment_inspect test_system_inspect test_batch_syntax_wireguard_clean test_combinators_literal_variable test_function_classification_correct test_no_terminal_output_vpnswitch_commands test_metadata_function_lists test_combinator_syntax_validation test_error_command_single_line test_error_command_two_lines test_error_command_three_lines test_error_command_ansi_colors test_batch_id_sequential test_store_batch_exits_basic test_store_batch_exits_references test_free_batch_id test_batch_infrastructure_lifecycle TEST 1 (test_batch_id_sequential): get_batch_id - sequential allocation Database: /tmp/vpn-switch-test.1263985/test_1 ✓ First batch ID is 0 ✓ Second batch ID is 1 ✓ Third batch ID is 2 ✓ Counter file has correct value (3) TEST 2 (test_store_batch_exits_basic): store_batch_exits - stores exit codes to file Database: /tmp/vpn-switch-test.1263985/test_2 ✓ Batch file created ✓ Batch file has correct content TEST 3 (test_store_batch_exits_references): store_batch_exits - stores exit codes with batch references Database: /tmp/vpn-switch-test.1263985/test_3 ✓ Batch file stores references correctly TEST 4 (test_free_batch_id): free_batch_id - deletes batch file Database: /tmp/vpn-switch-test.1263985/test_4 ✓ Batch file exists before cleanup ✓ Batch file deleted after cleanup TEST 5 (test_batch_infrastructure_lifecycle): Batch infrastructure - full allocation/store/free lifecycle Database: /tmp/vpn-switch-test.1263985/test_5 ✓ Allocated batch ID: 0 ✓ Batch results stored ✓ Batch results readable ✓ Batch cleaned up successfully TEST 6 (test_printenv_command): printenv - basic environment display Database: /tmp/vpn-switch-test.1263985/test_6 ✓ Printenv command executed and shows header ✓ Printenv shows VPN_SWITCH_BASE variable TEST 7 (test_status_command): status - VPN status display Database: /tmp/vpn-switch-test.1263985/test_7 ✓ Status command shows header ✓ Status shows disconnected state ✓ Status checks network interfaces TEST 8 (test_error_command_single_line): error command - single line message Database: /tmp/vpn-switch-test.1263985/test_8 ✓ error command outputs printf with 'Error:' prefix ✓ error command outputs exit 1 ✓ error command redirects to stderr TEST 9 (test_error_command_two_lines): error command - two line message Database: /tmp/vpn-switch-test.1263985/test_9 ✓ error command first line has 'Error:' prefix ✓ error command second line is indented without 'Error:' prefix ✓ error command outputs exit 1 TEST 10 (test_error_command_three_lines): error command - three line message Database: /tmp/vpn-switch-test.1263985/test_10 ✓ error command first line has 'Error:' prefix ✓ error command has properly indented continuation lines ✓ error command includes all three message lines ✓ error command outputs exit 1 TEST 11 (test_error_command_ansi_colors): error command - ANSI color support Database: /tmp/vpn-switch-test.1263985/test_11 ✓ error command includes ANSI escape codes when enabled ✓ error command includes ANSI reset code TEST 12 (test_wireguard_list): wireguard list - display configurations Database: /tmp/vpn-switch-test.1263985/test_12 ✓ Configuration section header displayed ✓ Config files section displayed ✓ Imported config file listed TEST 13 (test_wireguard_validate): wireguard validate - validate clean configuration Database: /tmp/vpn-switch-test.1263985/test_13 ✓ Validation header displayed ✓ No issues found in clean configuration TEST 14 (test_wireguard_info): wireguard info - display category information Database: /tmp/vpn-switch-test.1263985/test_14 ✓ Category header displayed ✓ Category path displayed ✓ Contents section displayed ✓ Category contents listed with symlink arrows TEST 15 (test_wireguard_import_valid): wireguard import - import valid config Database: /tmp/vpn-switch-test.1263985/test_15 ✓ Config file imported to database ✓ Permissions set to 0400 (read-only) TEST 16 (test_wireguard_add_category): wireguard add - create category with permissions Database: /tmp/vpn-switch-test.1263985/test_16 ✓ Category directory created ✓ Permissions set to 0755 TEST 17 (test_wireguard_link_create): wireguard link - create symlink in protocol directory Database: /tmp/vpn-switch-test.1263985/test_17 ✓ Symlink created ✓ Symlink points to correct relative path (./wg-TEST-RS-1.conf) TEST 18 (test_wireguard_start_basic): wireguard start - create session and connect to VPN Database: /tmp/vpn-switch-test.1263985/test_18 ✓ Session creation logged ✓ wg-quick command in connect.sh ✓ Session directory created in .session/ ✓ Session metadata files created ✓ connect.sh script generated ✓ connect.sh is executable ✓ connect.sh documents original config with relative path ✓ Patched config (wg_test13.conf) created ✓ Patched config correctly strips PostUp hook (phase-based DNS) ✓ Patched config correctly strips PostDown hook (phase-based DNS) TEST 19 (test_wireguard_connect_resume): wireguard connect - resume existing session by ID Database: /tmp/vpn-switch-test.1263985/test_19 ✓ wireguard connect generated wg-quick command in connect.sh ✓ wireguard connect generated pfctl command in connect.sh ✓ wireguard connect used session configuration ✓ connect.sh preserved after connect TEST 20 (test_wireguard_stop_basic): stop - disconnect active VPN session Database: /tmp/vpn-switch-test.1263985/test_20 ✓ Session exists before stop ✓ disconnect.sh contains wg-quick down command ✓ Stop command executed ✓ Session preserved after stop (has 'latest' link) TEST 21 (test_session_list): session list - display active and stale sessions Database: /tmp/vpn-switch-test.1263985/test_21 ✓ Session list header displayed ✓ Active session (PID 1458038) listed ✓ Stale session (PID 99997) listed ✓ Stale session (dead process) marked as stopped TEST 22 (test_session_show): session show - display connect script Database: /tmp/vpn-switch-test.1263985/test_22 ✓ Extracted session ID (1479261) from start command output ✓ Session ID displayed in header ✓ Session protocol displayed ✓ Connect script contents displayed TEST 23 (test_session_remove): session remove - remove stale, refuse active Database: /tmp/vpn-switch-test.1263985/test_23 ✓ Stale session created for removal test ✓ Removal operation logged for stale session ✓ Active session (PID 1263985) created for refusal test ✓ Refuses to remove active session (PID 1263985) TEST 24 (test_session_save_default): session save - save current session as default Database: /tmp/vpn-switch-test.1263985/test_24 ✓ Default session symlink created ✓ Default symlink points to correct session TEST 25 (test_session_save_named): session save work - save with custom name Database: /tmp/vpn-switch-test.1263985/test_25 ✓ Named session symlink created ✓ Named symlink points to correct session TEST 26 (test_session_start_default): session start - resume default session Database: /tmp/vpn-switch-test.1263985/test_26 ✓ Connect script created before stopping ✓ Session directory kept for resumption (referenced) ✓ Default symlink persists after stop ✓ Session start executed successfully TEST 27 (test_session_start_named): session start work - resume named session Database: /tmp/vpn-switch-test.1263985/test_27 ✓ Named symlink persists after stop ✓ Named session start executed successfully TEST 28 (test_session_start_bypid): session start - resume session by PID Database: /tmp/vpn-switch-test.1263985/test_28 ✓ Mock session (PID 11111) created for PID resume test ✓ Session start resumes by explicit PID (11111) TEST 29 (test_session_stop_named): session stop work - stop active named session Database: /tmp/vpn-switch-test.1263985/test_29 ✓ Session stop resolves named session 'work' TEST 30 (test_session_stop_bypid): session stop - stop active session by PID Database: /tmp/vpn-switch-test.1263985/test_30 ✓ Session stop handles PID (88888) TEST 31 (test_session_stop_inactive): session stop - inactive session should log (not error) Database: /tmp/vpn-switch-test.1263985/test_31 ✓ Session stop handles inactive session gracefully TEST 32 (test_wireguard_remove_config_in_use): wireguard remove - refuse removal when config in use Database: /tmp/vpn-switch-test.1263985/test_32 ✓ Active session (PID 1263985) created using config ✓ Error message when config in use by session ✓ Error suggests removing session first TEST 33 (test_wireguard_remove_config_with_refs): wireguard remove - refuse removal when config has symlink refs Database: /tmp/vpn-switch-test.1263985/test_33 ✓ Category symlink created (privacy/rm2) ✓ Error message when config has symlink references ✓ Error lists symlink references TEST 34 (test_wireguard_remove_symlink): wireguard remove - remove symlink (no safety checks) Database: /tmp/vpn-switch-test.1263985/test_34 ✓ Test symlink created ✓ Symlink removal operation logged ✓ Symlink was removed TEST 35 (test_wireguard_remove_category_link): wireguard remove - remove link from category Database: /tmp/vpn-switch-test.1263985/test_35 ✓ Category link (privacy/rm4) created ✓ Category link removal operation logged ✓ Category link was removed TEST 36 (test_wireguard_clean_no_broken): wireguard clean - no broken links found Database: /tmp/vpn-switch-test.1263985/test_36 ✓ Clean header displayed ✓ No broken symlinks message displayed ✓ Usage hint displayed TEST 37 (test_wireguard_clean_broken_protocol_link): wireguard clean - detect and generate remove for broken protocol link Database: /tmp/vpn-switch-test.1263985/test_37 ✓ Broken protocol symlink created for testing ✓ Remove command generated for broken protocol link ✓ Command includes link name TEST 38 (test_wireguard_clean_broken_category_link): wireguard clean - detect and generate remove for broken category link Database: /tmp/vpn-switch-test.1263985/test_38 ✓ Broken category symlink created for testing ✓ Remove command generated for broken category link ✓ Command includes category name TEST 39 (test_wireguard_clean_category_no_broken): wireguard clean privacy - category with no broken links Database: /tmp/vpn-switch-test.1263985/test_39 ✓ Category-specific header displayed ✓ No broken symlinks message for category TEST 40 (test_wireguard_clean_category_with_broken): wireguard clean privacy - category with broken links Database: /tmp/vpn-switch-test.1263985/test_40 ✓ Broken symlink created in privacy category ✓ Remove command generated for category link ✓ Category-specific clean (not global) TEST 41 (test_wireguard_validate_broken_symlink): wireguard validate - detect broken symlinks Database: /tmp/vpn-switch-test.1263985/test_41 ✓ Broken symlink created for validation test ✓ Broken symlink detected in protocol directory ✓ Error status reported TEST 42 (test_wireguard_validate_broken_category_symlink): wireguard validate - detect broken symlinks in categories Database: /tmp/vpn-switch-test.1263985/test_42 ✓ Broken category symlink created for validation test ✓ Broken symlink detected in category TEST 43 (test_wireguard_validate_naming_conflict): wireguard validate - detect naming conflicts Database: /tmp/vpn-switch-test.1263985/test_43 ✓ Naming conflict created (file + directory) ✓ Naming conflict detected TEST 44 (test_wireguard_validate_invalid_config): wireguard validate - detect invalid config files Database: /tmp/vpn-switch-test.1263985/test_44 ✓ Empty config file created for validation test ✓ Empty config file detected ✓ Missing [Interface] section detected TEST 45 (test_stop_no_sessions): stop - no sessions exist (empty output) Database: /tmp/vpn-switch-test.1263985/test_45 ✓ No output or log message when no sessions exist TEST 46 (test_stop_specific_interface): stop wg_test_safe - stop specific interface by name Database: /tmp/vpn-switch-test.1263985/test_46 ✓ Active session (PID 1263985, interface wg_test_safe) created ✓ Stopped specific interface wg_test_safe ✓ Interface wg_test_safe disconnect command generated TEST 47 (test_wireguard_disconnect_interface): wireguard disconnect wg_test_safe - direct disconnect command Database: /tmp/vpn-switch-test.1263985/test_47 ✓ Active session (PID 1263985) created for disconnect test ✓ Disconnect command executed for wg_test_safe ✓ Session PID displayed correctly TEST 48 (test_stop_nonexistent_interface): stop wg_test_other - error when interface not found Database: /tmp/vpn-switch-test.1263985/test_48 ✓ Active session with wg_test_safe interface created ✓ Error message for nonexistent interface TEST 49 (test_disconnect_without_session): disconnect without session - error handling Database: /tmp/vpn-switch-test.1263985/test_49 ✓ Error message when no session exists TEST 50 (test_stop_twice_idempotent): stop twice - idempotent (safe to call multiple times) Database: /tmp/vpn-switch-test.1263985/test_50 ✓ First stop: handles no sessions gracefully ✓ Second stop: still handles no sessions (idempotent) TEST 51 (test_wireguard_import_nonexistent): wireguard import - error when file doesn't exist Database: /tmp/vpn-switch-test.1263985/test_51 ✓ Error message for non-existent file TEST 52 (test_wireguard_import_duplicate): wireguard import - error when config already exists Database: /tmp/vpn-switch-test.1263985/test_52 ✓ First import succeeded ✓ Error message when config already exists TEST 53 (test_wireguard_add_category_conflict): wireguard add - error when category already exists Database: /tmp/vpn-switch-test.1263985/test_53 ✓ First add succeeded (privacy category created) ✓ Error message when category already exists TEST 54 (test_wireguard_add_link_conflict): wireguard add - error when link already exists Database: /tmp/vpn-switch-test.1263985/test_54 ✓ First link created successfully ✓ Error message when link already exists TEST 55 (test_wireguard_link_conflict): wireguard link - error when alias already exists Database: /tmp/vpn-switch-test.1263985/test_55 ✓ Config imported successfully ✓ Error message when alias already exists TEST 56 (test_error_invalid_category): error handling - invalid category shows error Database: /tmp/vpn-switch-test.1263985/test_56 ✓ Error message for invalid category TEST 57 (test_error_broken_symlink): error handling - broken symlink handled gracefully Database: /tmp/vpn-switch-test.1263985/test_57 ✓ Broken symlink created for testing ✓ Handled broken symlink (error or skipped) TEST 58 (test_error_invalid_command): error handling - invalid command shows usage Database: /tmp/vpn-switch-test.1263985/test_58 ✓ Usage/help shown for invalid command TEST 59 (test_edge_duplicate_instance_prevention): edge case - prevent duplicate VPN instances Database: /tmp/vpn-switch-test.1263985/test_59 ✓ First VPN session created (PID 1263985) ✓ Detected existing VPN instance ✓ No duplicate session created TEST 60 (test_edge_stale_session_cleanup): edge case - stale sessions don't block new sessions Database: /tmp/vpn-switch-test.1263985/test_60 ✓ Stale session created for testing ✓ Proceeded with new session (stale session didn't block) ✓ Stale session preserved (manual cleanup via 'session clean' required) TEST 61 (test_wireguard_patch_valid): wireguard patch - displays patched configuration Database: /tmp/vpn-switch-test.1263985/test_61 ✓ Patch output correctly strips PostUp hook (phase-based DNS) ✓ Patch output correctly strips PostDown hook (phase-based DNS) ✓ Patch output preserves [Interface] section ✓ Patch output preserves [Peer] section TEST 62 (test_wireguard_patch_nonexistent): wireguard patch - handles nonexistent config Database: /tmp/vpn-switch-test.1263985/test_62 ✓ Patch rejects nonexistent config with error TEST 63 (test_wireguard_patch_absolute): wireguard patch - handles absolute path Database: /tmp/vpn-switch-test.1263985/test_63 ✓ Patch works with absolute path (strips DNS hooks) TEST 64 (test_wireguard_info_category): wireguard info - displays category information Database: /tmp/vpn-switch-test.1263985/test_64 ✓ Category header displayed ✓ Config count displayed ✓ Link count displayed ✓ Category path displayed ✓ Contents section header displayed ✓ Category contents listed with symlink arrows TEST 65 (test_session_save_default): session save - save current session as default Database: /tmp/vpn-switch-test.1263985/test_65 ✓ Default session symlink created ✓ Default symlink points to correct session TEST 66 (test_session_save_named): session save work - save with custom name Database: /tmp/vpn-switch-test.1263985/test_66 ✓ Named session symlink created ✓ Named symlink points to correct session TEST 67 (test_session_start_default): session start - resume default session Database: /tmp/vpn-switch-test.1263985/test_67 ✓ Connect script created before stopping ✓ Session directory kept for resumption (referenced) ✓ Default symlink persists after stop ✓ Session start executed successfully TEST 68 (test_session_start_named): session start work - resume named session Database: /tmp/vpn-switch-test.1263985/test_68 ✓ Named symlink persists after stop ✓ Named session start executed successfully TEST 69 (test_session_start_by_pid): session start - resume by PID Database: /tmp/vpn-switch-test.1263985/test_69 ✓ Session start by PID executed successfully TEST 70 (test_openvpn_import_valid): openvpn import - import valid .ovpn config Database: /tmp/vpn-switch-test.1263985/test_70 ✓ Config imported to openvpn/ ✓ Permissions set to 0400 TEST 71 (test_openvpn_list): openvpn list - list configs and groups Database: /tmp/vpn-switch-test.1263985/test_71 ✓ Lists config: us-server.ovpn ✓ Lists group: work/ ✓ Lists group link with arity-1: work/office TEST 72 (test_openvpn_add_group): openvpn add - create group Database: /tmp/vpn-switch-test.1263985/test_72 ✓ Group directory created ✓ Group permissions correct (0700) TEST 73 (test_openvpn_link): openvpn link - create protocol-level link Database: /tmp/vpn-switch-test.1263985/test_73 ✓ Protocol-level link created ✓ Link target correct TEST 74 (test_openvpn_remove): openvpn remove - remove config safely Database: /tmp/vpn-switch-test.1263985/test_74 ✓ Config removed ✓ Other config preserved TEST 75 (test_openvpn_validate): openvpn validate - detect broken links Database: /tmp/vpn-switch-test.1263985/test_75 ✓ Broken symlink detected ✓ Valid database passes validation TEST 76 (test_openvpn_info): openvpn info - show group information Database: /tmp/vpn-switch-test.1263985/test_76 ✓ Shows group name ✓ Shows correct link count ✓ Shows link: office TEST 77 (test_openvpn_dump): openvpn dump - export database Database: /tmp/vpn-switch-test.1263985/test_77 ✓ Dump includes import command ✓ Dump includes group creation ✓ Dump includes protocol link ✓ Dump includes group link TEST 78 (test_openvpn_patch_valid): openvpn patch - displays patched configuration Database: /tmp/vpn-switch-test.1263985/test_78 ✓ Patch output correctly strips up script (phase-based DNS) ✓ Patch output correctly strips down script (phase-based DNS) ✓ Patch output contains daemon mode ✓ Patch output contains device interface ✓ Patch output contains writepid directive ✓ Patch output preserves client directive ✓ Patch output preserves remote server TEST 79 (test_openvpn_patch_nonexistent): openvpn patch - handles nonexistent config Database: /tmp/vpn-switch-test.1263985/test_79 ✓ Error message for nonexistent config TEST 80 (test_openvpn_patch_absolute): openvpn patch - handles absolute path Database: /tmp/vpn-switch-test.1263985/test_80 ✓ Absolute path patch works TEST 81 (test_openvpn_patch_credentials_bare): openvpn patch - patches bare auth-user-pass with credentials Database: /tmp/vpn-switch-test.1263985/test_81 ✓ Bare auth-user-pass patched with credentials path ✓ Bare auth-user-pass preserved when no credentials set TEST 82 (test_openvpn_patch_credentials_existing): openvpn patch - preserves existing auth-user-pass path Database: /tmp/vpn-switch-test.1263985/test_82 ✓ Existing auth-user-pass path preserved (not overridden) TEST 83 (test_openvpn_patch_credentials_missing): openvpn patch - handles config without auth-user-pass Database: /tmp/vpn-switch-test.1263985/test_83 ✓ Config without auth-user-pass remains unchanged TEST 84 (test_openvpn_start_basic): openvpn start - create session and connect to VPN Database: /tmp/vpn-switch-test.1263985/test_84 ✓ Session creation logged ✓ openvpn command in connect.sh ✓ Session directory created in .session/ ✓ Session metadata files created ✓ connect.sh script generated ✓ connect.sh is executable ✓ Patched config (tun_test80.ovpn) created ✓ Patched config contains daemon mode ✓ Patched config correctly strips up script (phase-based DNS) ✓ Patched config correctly strips down script (phase-based DNS) TEST 85 (test_openvpn_stop_basic): openvpn stop - cleanup commands for session Database: /tmp/vpn-switch-test.1263985/test_85 ✓ Session created via user interface ✓ Disconnect commands reference correct interface (tun_test85) ✓ Disconnect generates process kill commands TEST 86 (test_openvpn_disconnect_interface): openvpn disconnect - tear down OpenVPN interface Database: /tmp/vpn-switch-test.1263985/test_86 ✓ Disconnect generates process termination commands TEST 87 (test_openvpn_clean): openvpn clean - generate cleanup commands for broken links Database: /tmp/vpn-switch-test.1263985/test_87 ✓ Clean generates remove commands ✓ Clean detected broken symlink TEST 88 (test_protocol_agnostic_import_wireguard): import (protocol-agnostic) - detects WireGuard .conf file Database: /tmp/vpn-switch-test.1263985/test_88 ✓ Protocol-agnostic import detected .conf and delegated to wireguard import ✓ Protocol-agnostic import generates correct cp command TEST 89 (test_protocol_agnostic_list): list (protocol-agnostic) - delegates to all protocols Database: /tmp/vpn-switch-test.1263985/test_89 ✓ Protocol-agnostic list delegated to wireguard list ✓ Protocol-agnostic list shows wireguard config sections ✓ Protocol-agnostic list has no duplicate lines (3 unique) TEST 90 (test_protocol_agnostic_link): link (protocol-agnostic) - creates protocol-level alias Database: /tmp/vpn-switch-test.1263985/test_90 ✓ Protocol-agnostic link generates ln command ✓ Protocol-agnostic link uses correct relative path (./wireguard) ✓ Protocol-agnostic link includes correct alias name TEST 91 (test_protocol_agnostic_remove): remove (protocol-agnostic) - removes protocol-level link Database: /tmp/vpn-switch-test.1263985/test_91 ✓ Protocol-agnostic remove generates rm command ✓ Protocol-agnostic remove includes descriptive comment ✓ Protocol-agnostic remove errors on non-existent link TEST 92 (test_protocol_agnostic_validate): validate (protocol-agnostic) - delegates to all protocols Database: /tmp/vpn-switch-test.1263985/test_92 ✓ Protocol-agnostic validate delegated to wireguard validate ✓ Protocol-agnostic validate shows validation output TEST 93 (test_network_validate): network validate - check network prerequisites Database: /tmp/vpn-switch-test.1263985/test_93 ✓ Network validation header displayed ✓ Network validate passed on clean configuration TEST 94 (test_permissions_validate): permissions validate - check filesystem permissions Database: /tmp/vpn-switch-test.1263985/test_94 ✓ Permissions validation header displayed ✓ Permissions validate passed on clean configuration TEST 95 (test_environment_validate): environment validate - check environment variables Database: /tmp/vpn-switch-test.1263985/test_95 ✓ Environment validation header displayed ✓ Environment validate passed on clean configuration TEST 96 (test_batch_validate_includes_system): validate (batch) - includes system validators Database: /tmp/vpn-switch-test.1263985/test_96 ✓ Batch validate includes database validator ✓ Batch validate includes binaries validator ✓ Batch validate includes phases validator ✓ Batch validate includes network validator ✓ Batch validate includes permissions validator ✓ Batch validate includes environment validator TEST 97 (test_start_wireguard_only): start - auto-detect WireGuard config Database: /tmp/vpn-switch-test.1263985/test_97 ✓ Delegates to wireguard commands for WireGuard-only config TEST 98 (test_start_openvpn_only): start - auto-detect OpenVPN config Database: /tmp/vpn-switch-test.1263985/test_98 ✓ Delegates to openvpn commands for OpenVPN-only config TEST 99 (test_start_not_found): start - error on nonexistent config Database: /tmp/vpn-switch-test.1263985/test_99 ✓ Error message for nonexistent config ✓ Error shows both search locations TEST 100 (test_start_no_default): start - error when no configs exist (Phase 3.4.1) Database: /tmp/vpn-switch-test.1263985/test_100 ✓ Error message when no configs available ✓ Error provides hint to import configs TEST 101 (test_start_with_default_wireguard): start - use default link (WireGuard) via API Database: /tmp/vpn-switch-test.1263985/test_101 ✓ Default session link created via API ✓ Start with no args resolves to default session TEST 102 (test_start_with_default_openvpn): start - use default link (OpenVPN) via API Database: /tmp/vpn-switch-test.1263985/test_102 ✓ Default session link created via API ✓ Start with no args resolves to default session TEST 103 (test_start_default_invalid_target): start - error on invalid default link target Database: /tmp/vpn-switch-test.1263985/test_103 ✓ Error detected for invalid default session target TEST 104 (test_init_extension_links): init - creates protocol extension links (Phase 3.4.1) Database: /tmp/vpn-switch-test.1263985/test_104 ✓ conf link created ✓ ovpn link created ✓ conf → wireguard ✓ ovpn → openvpn TEST 105 (test_start_extension_link_fast_path): start - uses extension link for protocol resolution (Phase 3.4.1) Database: /tmp/vpn-switch-test.1263985/test_105 ✓ Extension link used for fast protocol resolution (wireguard commands found) TEST 106 (test_start_multiple_matches): start - error on multiple protocol matches (Phase 3.4.1) Database: /tmp/vpn-switch-test.1263985/test_106 ✓ Multiple matches error shown ✓ Both matches listed TEST 107 (test_database_init): database init - creates directory structure (Phase 4.4) Database: /tmp/vpn-switch-test.1263985/test_107 ✓ wireguard/ created ✓ openvpn/ created ✓ .session/ created ✓ session/ created ✓ .env/default/ created ✓ .env/local/ created ✓ .include/phase/ created TEST 108 (test_environment_init): environment init - copies profile templates (Phase 4.4) Database: /tmp/vpn-switch-test.1263985/test_108 ✓ minimal profile copied ✓ profile has correct permissions (0600) TEST 109 (test_phases_copy): phases copy - copies phase templates (Phase 4.4) Database: /tmp/vpn-switch-test.1263985/test_109 ✓ wireguard phases copied ✓ openvpn phases copied ✓ wireguard phase subdirs exist TEST 110 (test_phases_lift): phases lift - lifts phase:backend templates (Phase 4.4) Database: /tmp/vpn-switch-test.1263985/test_110 ✓ generates lift command ✓ output file is executable TEST 111 (test_phases_sync_single): phases sync - discovers and lifts backends (Phase 4.4) Database: /tmp/vpn-switch-test.1263985/test_111 ✓ delegates to phases lift TEST 112 (test_phases_sync_all): phases sync - syncs all phases (Phase 4.4) Database: /tmp/vpn-switch-test.1263985/test_112 ✓ delegates to single-phase sync TEST 113 (test_init_batch_combinator): init - orchestrates full initialization (Phase 4.4) Database: /tmp/vpn-switch-test.1263985/test_113 ✓ database init executed ✓ environment init executed ✓ phases copy executed TEST 114 (test_init_combinator): init combinator - delegates to batch combinator (Phase 4.4) Database: /tmp/vpn-switch-test.1263985/test_114 ✓ database created ✓ profile installed TEST 115 (test_setenv_basic): setenv - basic variable setting Database: /tmp/vpn-switch-test.1263985/test_115 ✓ .env/local directory created ✓ Variable file created ✓ Variable has correct value ✓ File has correct permissions (0600 or 0640 for cross-user support) ✓ Shows confirmation message TEST 116 (test_setenv_invalid_name): setenv - invalid variable name Database: /tmp/vpn-switch-test.1263985/test_116 ✓ Rejects invalid variable name ✓ No file created for invalid name TEST 117 (test_getenv_local_override): getenv - shows local override Database: /tmp/vpn-switch-test.1263985/test_117 ✓ Shows local override source ✓ Outputs correct value from local TEST 118 (test_getenv_fallback_chain): getenv - fallback chain (local > default > template) Database: /tmp/vpn-switch-test.1263985/test_118 ✓ Shows error if variable not found ✓ Falls back to .env/default ✓ Falls back to template/environment TEST 119 (test_unsetenv_existing): unsetenv - remove existing variable Database: /tmp/vpn-switch-test.1263985/test_119 ✓ Variable file was removed ✓ Shows confirmation message TEST 120 (test_unsetenv_not_set): unsetenv - variable not set in local Database: /tmp/vpn-switch-test.1263985/test_120 ✓ Shows informative message when not set TEST 121 (test_dumpenv_prologue): dumpenv prologue - outputs safe minimal set Database: /tmp/vpn-switch-test.1263985/test_121 ✓ Prologue includes VPN_SWITCH_TERMINAL_INTERPRETER ✓ Prologue includes VPN_SWITCH_DISPLAY_ANSI ✓ Prologue excludes VPN_SWITCH_INTERPRETER_wireguard_list (epilogue-only) ✓ Prologue excludes VPN_SWITCH_INTERPRETER_wireguard_import1 (epilogue-only) TEST 122 (test_dumpenv_epilogue): dumpenv epilogue - outputs complete set Database: /tmp/vpn-switch-test.1263985/test_122 ✓ Epilogue includes VPN_SWITCH_TERMINAL_INTERPRETER ✓ Epilogue includes VPN_SWITCH_DISPLAY_ANSI ✓ Epilogue includes VPN_SWITCH_INTERPRETER_wireguard_list ✓ Epilogue includes VPN_SWITCH_INTERPRETER_wireguard_import1 TEST 123 (test_dumpenv_profile_filtering): dumpenv - profile filtering prevents restore breakage Database: /tmp/vpn-switch-test.1263985/test_123 ✓ Prologue correctly excludes function-specific interpreter ✓ Epilogue correctly includes function-specific interpreter TEST 124 (test_environment_cache_on): environment cache on - creates cache file with correct permissions Database: /tmp/vpn-switch-test.1263985/test_124 ✓ Cache file created ✓ Cache file has correct permissions (0600) ✓ Shows cache enabled message ✓ Cache file has content TEST 125 (test_environment_cache_off): environment cache off - removes cache file Database: /tmp/vpn-switch-test.1263985/test_125 ✓ Cache file removed ✓ Shows cache disabled message TEST 126 (test_environment_cache_status): environment cache status - shows correct status Database: /tmp/vpn-switch-test.1263985/test_126 ✓ Shows DISABLED status when cache off ✓ Shows ENABLED status when cache on ✓ Shows cached variable count TEST 127 (test_environment_cache_no_args): environment cache (no args) - defaults to status Database: /tmp/vpn-switch-test.1263985/test_127 ✓ Shows status with no arguments TEST 128 (test_cache_invalidation_setenv): setenv - rebuilds cache automatically Database: /tmp/vpn-switch-test.1263985/test_128 ✓ Cache rebuilt automatically after setenv ✓ Rebuilt cache contains new variable TEST_VAR TEST 129 (test_cache_invalidation_unsetenv): unsetenv - rebuilds cache automatically Database: /tmp/vpn-switch-test.1263985/test_129 ✓ Cache rebuilt automatically after unsetenv ✓ Rebuilt cache no longer contains TEST_VAR TEST 130 (test_cache_invalidation_environment_init): environment init - invalidates cache automatically Database: /tmp/vpn-switch-test.1263985/test_130 ✓ Cache file removed after environment init ✓ Shows cache invalidation warning TEST 131 (test_dumpenv_cache_preservation): dumpenv epilogue - includes cache if enabled Database: /tmp/vpn-switch-test.1263985/test_131 ✓ Epilogue includes cache content ✓ Epilogue includes cache restore comment TEST 132 (test_dumpenv_cache_not_included_when_disabled): dumpenv epilogue - excludes cache when disabled Database: /tmp/vpn-switch-test.1263985/test_132 ✓ Epilogue correctly excludes cache when disabled TEST 133 (test_cache_no_recursion): environment cache on - excludes cache file from scan Database: /tmp/vpn-switch-test.1263985/test_133 ✓ Cache correctly excludes itself TEST 134 (test_interpreter_single_underscore): interpreter resolution - single underscore uses TERMINAL_INTERPRETER Database: /tmp/vpn-switch-test.1263985/test_134 # Set VPN_SWITCH_TERMINAL_INTERPRETER (effective next command) ✓ Single underscore function used TERMINAL_INTERPRETER TEST 135 (test_interpreter_double_underscore): interpreter resolution - double underscore uses COMBINATOR_INTERPRETER Database: /tmp/vpn-switch-test.1263985/test_135 # Set VPN_SWITCH_COMBINATOR_INTERPRETER (effective next command) ✓ Double underscore function used COMBINATOR_INTERPRETER TEST 136 (test_interpreter_triple_underscore): interpreter resolution - triple underscore uses BATCH_COMBINATOR_INTERPRETER Database: /tmp/vpn-switch-test.1263985/test_136 # Set VPN_SWITCH_BATCH_COMBINATOR_INTERPRETER (effective next command) ✓ Triple underscore function used BATCH_COMBINATOR_INTERPRETER TEST 137 (test_interpreter_resolution_priority): interpreter resolution - function-specific override beats intrinsic classification Database: /tmp/vpn-switch-test.1263985/test_137 # Set VPN_SWITCH_TERMINAL_INTERPRETER (effective next command) ✓ Function-specific override takes priority over intrinsic classification ✓ Intrinsic classification was correctly bypassed TEST 138 (test_inspect_batch_complete): inspect (batch) - includes all inspection sections Database: /tmp/vpn-switch-test.1263985/test_138 ✓ Batch inspect includes environment section ✓ Batch inspect includes system section ✓ Batch inspect includes WireGuard section ✓ Batch inspect includes OpenVPN section ✓ Batch inspect includes session section ✓ Batch inspect includes phases section TEST 139 (test_environment_inspect): environment inspect - displays environment variables Database: /tmp/vpn-switch-test.1263985/test_139 ✓ Environment inspect shows header ✓ Environment inspect shows VPN_SWITCH_BASE ✓ Environment inspect shows database structure TEST 140 (test_system_inspect): system inspect - displays system configuration Database: /tmp/vpn-switch-test.1263985/test_140 ✓ System inspect shows header ✓ System inspect shows system info section ✓ System inspect shows network interfaces section TEST 141 (test_batch_syntax_wireguard_clean): wireguard clean - validates batch syntax Database: /tmp/vpn-switch-test.1263985/test_141 ✓ wireguard clean outputs valid batch syntax ✓ wireguard clean uses literal $VPN_SWITCH_CONTEXT_SCRIPT TEST 142 (test_combinators_literal_variable): combinators - use literal $VPN_SWITCH_CONTEXT_SCRIPT Database: /tmp/vpn-switch-test.1263985/test_142 ✓ wireguard start uses literal variable ✓ wireguard start variable not expanded TEST 143 (test_combinator_syntax_validation): combinators - validate single-command output syntax Database: /tmp/vpn-switch-test.1263985/test_143 ✓ wireguard start outputs exactly one command ✓ wireguard start uses literal variable ✓ wireguard start variable not expanded ✓ openvpn start outputs exactly one command ✓ start (protocol-agnostic) outputs exactly one command TEST 144 (test_function_classification_correct): function classification - naming matches behavior ✓ wireguard add2 correctly classified as combinator (__) ✓ wireguard clean0 correctly classified as batch (___) ✓ openvpn clean0 correctly classified as batch (___) TEST 145 (test_no_terminal_output_vpnswitch_commands): terminal functions - must not output vpn-switch commands ✓ No terminal functions output vpn-switch commands TEST 146 (test_metadata_function_lists): metadata - function lists accurate after renames ✓ Metadata includes __wireguard_add2 in combinators ✓ Metadata includes ___wireguard_clean0 in batch combinators ✓ Metadata includes ___openvpn_clean0 in batch combinators ======================================== Test Summary ======================================== Test Functions: 146 Total Assertions: 371 Passed Assertions: 371 Failed Assertions: 0 ALL TESTS PASSED Already on 'main' M template/platform/default Your branch is up to date with 'origin/main'. X11 forwarding request failed From github-repo-vpn-switch:johannes-bruegmann/vpn-switch 1ff9189..08cbe2d main -> origin/main Updating 1ff9189..08cbe2d Fast-forward scripts/run-all-tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)