fix(ci): prevent recursive standalone cleanup

Merged
KH
2mo ago
+126-0

Summary\n\n- prevent the standalone smoke EXIT handler from recursively invoking node down through its cleanup subshell\n- retain the exact three-shutdown assertion and document the intentional sequence\n- unblock the publish gate without loosening or skipping coverage\n\n## Root cause\n\nThis is behavior bug option 2 from the incident brief: the fourth shutdown is wrong.\n\nThe commit that introduced the failing lifecycle is 59106aa93 (fix(ci): reuse standalone smoke workspace, #1567). The main history ends at that squash commit. Its PR branch was based at 61da735c1; the intervening #1568 commit 4e41767c1 changes Rust broker handshake code only, and #1572 commit 00f21bb78 changes fleet attach code only. Neither touches this smoke lifecycle.\n\nThe failed publish run recorded shutdown indexes [1, 4, 6, 7]. The first three represent preflight cleanup, deadline teardown, and EXIT cleanup. The adjacent fourth call occurs when the EXIT handler enters its own subshell while the trap remains armed. The fix makes cleanup once-only and disarms EXIT before creating that subshell.\n\nFailing run: https://github.com/AgentWorkforce/relay/actions/runs/32185433777\n\n## Verification\n\n- targeted smoke suite passed with Bash 3.2 and Bash 5.3 against Vitest 4.1.11\n- bash syntax, ShellCheck, Prettier, diff check, and staged secrets scan passed\n- publish-equivalent Node 22.14/Linux fresh-install run passed: 144 test files, 2,075 tests passed, 3 files and 25 tests skipped (2,100 total)\n