P-59's trial tests bring their own timeout, and leave HOME empty on macOS

Merged
DO
5d ago
+26-5

Closes #544.

Since #532, three ReadConfinementTrial tests failed on macOS under PATH=/usr/bin:/bin. Two things caused it, and a third came from review:

  • No timeout on macOS's own PATH. tools/trial_p59_read_confinement.sh refuses to start without one. The stand-in folder now holds a bin/timeout that runs its command after the duration (exec after shift), as NarrowedToken's stand-in curl and openssl do, and environment(folder) puts that bin/ first on PATH.
  • Bytecode in the empty HOME. Once the script ran, macOS's own python3 cached the stand-in CLI's bytecode under HOME/Library/Caches/com.apple.python, which test_the_engine_configuration_is_judged_by_the_condition holds empty. The stand-in's claude wrapper now runs python3 -B.
  • The stand-in checks its duration, as GNU's does. On Linux CI the stand-in now replaces the real timeout in these tests, so it takes what GNU timeout takes (a number with an optional s, m, h or d) and refuses anything else, or no command, with 125. test_the_stand_in_timeout_runs_what_gnu_timeout_runs holds it on eleven durations, and runs the real timeout in /usr/bin or /bin beside it where there is one, so on CI the two must agree; on this Mac all eleven agree with Homebrew's coreutils 9.12. With line 212's 180 made 18O, test_each_configuration_is_given_the_read_tools_and_its_own_flags fails.

The script is unchanged: a real trial still needs a real timeout. Because the stand-in execs, the /proc/<parent>/environ a leaking call reads on Linux is now the CLI's own rather than a separate timeout's; both start with the same environment and marker, so no assertion changes.

No record, no rule changed: a test-only change.

Verify

  • PATH=/usr/bin:/bin python3 -m unittest tests.test_tools.ReadConfinementTrial: 5 tests OK (3 failed before).
  • PATH=/usr/bin:/bin SIM_SEEDS=40 make verify on an export of 5b01bd7: 1569 tests OK (8 expected failures).
  • The P-59 mutants (tools/mutants.py, the P59 block), run alone on b9f6ef5: 18 of 18 killed. 5b01bd7 changes only the stand-in and adds its test.

Reviews

ReviewerHeadUnread partsBlockingMajorMinorInfo
astra88c7e2enone0100
museb9f6ef5none0010
claude-review88c7e2enone0011
claude-security88c7e2enone0000
FindingSeverityCriterionWhereWhatDisposition
astra#1majorPR-3tests/test_tools.py:8087The timeout double hides invalid duration argumentsFixed in b9f6ef5: the stand-in refuses a malformed duration with 125; line 212's 180 made 18O now fails the tests
muse#1minorPR-3tests/test_tools.py:8088Stand-in timeout's refusal rule is untested and rejects valid GNU durationsFixed in 5b01bd7: it takes GNU's durations (1.5, 90s, 3m) and a new test holds it, beside the real timeout where there is one
claude-review#1minorPR-3tests/test_tools.py:8087The stand-in timeout accepts any first argument, so Linux CI no longer checks how the script calls timeoutFixed in b9f6ef5, as astra#1; the reviewer's 18O mutant is killed
claude-review#2infononethe changeThe PR body says the stand-in CLI reads no parent's environ, but on Linux it does when a call leaksFixed in the PR body: the parent environ a leaking call reads is now the CLI's own, with the same environment

Bots: Codex reviewed b9f6ef5 with no findings; SonarCloud's gate passed on 5b01bd7; CodeRabbit skipped (auto reviews off).

Argon: not run (quota), owed; Astra read 88c7e2e as its stand-in.

šŸ¤– Generated with Claude Code