Exec the harness through a pre-exec driver - #55
Open
CrypticSwarm wants to merge 3 commits into
Open
Conversation
The harness binary is exec'd through a user-phase driver, swarmforge.harness.execute: it sets HOME to the anvil home, drops the variables its own launch adds (PYTHONPATH for the import root, and PYTHONCOERCECLOCALE, pinned to 0 so interpreter startup cannot edit LC_CTYPE into the environment the binary inherits), hands argv and environment to the harness's pre_exec hook, and replaces itself with the binary through execve. The default hook is the identity, so a harness that declares nothing is exec'd byte-identically to a direct exec. Claude's hook shapes both halves: the settings file rides the command line ahead of the session's arguments with --setting-sources user,project,local, the wrapper directory leads PATH exactly when the root phase left an executable wrapper standing there, and the environment names the merged config destination and the credential store in the shared home. The behavior suite runs the driver per harness with a recording execve and compares argv and the whole environment: claude gets exactly its deltas, every other harness passes through untouched, and the launch variables reach no harness at all.
The entrypoint's exec drops privileges into swarmforge.harness.execute rather than the binary itself, handing over the harness name, the anvil home, and the session's arguments behind a separator. The claude shell blocks -- the settings-flag splice, the config-dir and credential-store exports, and the wrapper PATH shim -- are gone from the entrypoint; claude's pre_exec hook is what shapes that exec now, and the entrypoint names no harness. The launch sets exactly the variables the driver scrubs back out: PYTHONPATH for the import root, and PYTHONCOERCECLOCALE=0 so interpreter startup cannot edit LC_CTYPE into the environment the binary inherits. The text assertions that pinned the deleted shell move to the behavior they guarded: the settings build and delivery are followed through the module constant that ties them, the config home and credential store are read out of the hook's environment, the wrapper switch-on is observed as the PATH prefix itself, and a new agreement test parses the exec line against execute.main's argv shape and the driver's scrub list.
The interpreter sets SIGPIPE and SIGXFSZ to ignore at startup, and an ignored disposition survives exec -- so the harness, and every process it spawns, would see EPIPE write errors where a direct exec died silently on a closed pipe. The driver defaults both back just before execve, and the recording-execve tests restore them afterwards so the suite does not keep running with the process's own dispositions defaulted. The passthrough invariant now runs with claude's settings file and wrapper staged, so the whole-environment comparison proves the other harnesses stay untouched by artifacts standing where claude's hook would find them; a claude test exercises every delta at once, argv and environment compared whole; and the selector the entrypoint guards is pinned to the binary the driver execs -- one path only while every harness's name is its binary.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The exec line was the last place the entrypoint knew a harness by name: claude got a
--settings/--setting-sourcessplice, two config-dir exports, and a PATH prefix for the git wrapper. That shaping now lives in claude'spre_exechook, run bypython3 -P -m swarmforge.harness.execute, which sets HOME, applies the hook, scrubs the launch-only variables (PYTHONPATH,PYTHONCOERCECLOCALE), resets the signal dispositions Python ignores, and execs the binary.An invariant suite runs the driver per harness against a fake execve and pins the exact final argv and environment: claude gets precisely its settings flags, exports, and PATH prefix under the same guards the shell applied; the other three harnesses are byte-identical passthrough even with claude's artifacts staged; the launch variables appear nowhere. The entrypoint is down to timezone, user setup, the binary check, one init invocation, and one harness-agnostic exec — no harness names.