From 410aa6d1b429c71a6a48bfbdd4c0b745d609724d Mon Sep 17 00:00:00 2001 From: "Can H. Tartanoglu" Date: Sat, 7 Nov 2026 20:02:29 +0100 Subject: [PATCH] test(runner): resolve provider fixture signals through PATH (#14476) ## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Its native runner tests verify exact provider shutdown and recovery. > - Four fixture call sites invoke `/bin/kill` directly. > - NixOS supplies `kill` through PATH, so those tests fail before checking process state. > - This pull request resolves `kill` through PATH, as the neighboring runner tests already do. > - The same stop, probe, and resume assertions can run on non-FHS hosts. ## Linked Issues or Issue Description **What happened?** Four Codex provider tests fail with `No such file or directory` on NixOS. Each failure comes from a test-owned `/bin/kill` invocation. The executable is installed on PATH. **Expected behavior** Tests should probe and signal their disposable provider processes with the installed `kill` command. **Steps to reproduce** On a NixOS host with `kill` on PATH and no `/bin/kill`, run the `codex_provider` Rust integration target. Three `durable_stop_*` cases and `structured_question_round_trips_through_the_normalized_backend` fail. All four failures were reproduced separately on unmodified `e9debd3eac328e6abe87ab89e9ff40ee2bb56b73`. Related: these failures also blocked the broader local qualification of #14474. This fixture fix has no dependency on that runtime change. ## What Changed - Replace four test-only `/bin/kill` executable paths with `kill`. - Retain every signal, PID/process-group operand, assertion, and unwind cleanup. - Match existing PATH lookup in this file and `tests/process_supervisor.rs`. ## Verification Rebased onto master `820c458465` (single commit `ad1fb1043`). - `cd packages/paperclip-runner/runner && cargo test -p paperclip-runner-core --test codex_provider --locked -j4 -- --test-threads=2`: 94 passed, 0 failed, 2 ignored (subprocess helper entries that their parent tests run). The four tests that used `/bin/kill` pass on a host without `/bin/kill`. - No production code or documentation changes. - Hosted CI: `General tests (workspaces-b)` timed out in `packages/db/src/backup-lib.test.ts` and `e2e shard (1/8)` hit `ERR_STREAM_UNABLE_TO_PIPE`. Neither area is touched by this test-only diff. Master pushes currently run the "CI profile skipped" workflow, so there is no master run of those jobs to compare against. ## Risks Low risk. Tests require a working `kill` on their test PATH. Fixture PIDs and arguments stay unchanged. ## Model Used - Anthropic Claude Sonnet 5.5 (`claude-sonnet-5-5`) through Claude Code with tool use and code execution, for the rebase and verification. Original change: OpenAI `gpt-6-astra` through OpenCode. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --- .../runner/crates/runner-core/tests/codex_provider.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/paperclip-runner/runner/crates/runner-core/tests/codex_provider.rs b/packages/paperclip-runner/runner/crates/runner-core/tests/codex_provider.rs index d3bcf147e86..a2b46380201 100644 --- a/packages/paperclip-runner/runner/crates/runner-core/tests/codex_provider.rs +++ b/packages/paperclip-runner/runner/crates/runner-core/tests/codex_provider.rs @@ -5783,7 +5783,7 @@ fn durable_stop_does_not_wait_for_a_repeated_interrupt_acknowledgement() { assert_eq!(stopped.result["providerExitConfirmed"], true); for id in [provider_pid.to_string(), format!("-{provider_pid}")] { assert!( - !std::process::Command::new("/bin/kill") + !std::process::Command::new("kill") .args(["-0", "--", &id]) .output() .unwrap() @@ -5915,7 +5915,7 @@ fn assert_durable_stop_prepares_resumed_provider(ended_before_resume: bool) { .expect("durably record renewed provider ownership"); let resumed_pid = resumed_event["payload"]["processId"].as_u64().unwrap(); let process_exists = |group: bool| { - std::process::Command::new("/bin/kill") + std::process::Command::new("kill") .arg("-0") .arg("--") .arg(if group { @@ -7340,7 +7340,7 @@ fn structured_question_round_trips_through_the_normalized_backend() { #[cfg(unix)] impl Drop for PausedTestProvider { fn drop(&mut self) { - let _ = std::process::Command::new("/bin/kill") + let _ = std::process::Command::new("kill") .args(["-CONT", "--", &self.0.to_string()]) .output(); } @@ -7350,7 +7350,7 @@ fn structured_question_round_trips_through_the_normalized_backend() { #[cfg(unix)] let paused_provider = { let pid = _opened.result["processId"].as_u64().unwrap(); - assert!(std::process::Command::new("/bin/kill") + assert!(std::process::Command::new("kill") .args(["-STOP", "--", &pid.to_string()]) .output() .unwrap()