feat(plugin-exec): deterministic default tool set instead of blind /usr/bin PATH - #297
Open
raphaelvigee wants to merge 1 commit into
Open
feat(plugin-exec): deterministic default tool set instead of blind /usr/bin PATH#297raphaelvigee wants to merge 1 commit into
raphaelvigee wants to merge 1 commit into
Conversation
…sr/bin PATH The exec/bash/sh drivers fell back to a hardcoded PATH=/usr/local/bin:/usr/bin:/bin whenever .hephconfig didn't set `path` — exposing whatever happened to be installed there, differing across hosts/distros/CI images even though the target's cache key never saw it. Replace the fallback with a curated `default_tools` list, each name turned into an implicit, hashed //@heph/bin:<name> tool dependency — the same tested/hashed/deduped machinery an explicit `tools = [...]` target declaration already goes through, rather than a bespoke PATH-directory trust. Inclusion is gated by a fixed-directory probe (not heph's own ambient $PATH), so the curated *set* is identical across shell setups on a given host; the concrete binary is still resolved (and hashed) for real by the existing `hostbin` driver at run time. `default_tools` is mutually exclusive with the existing raw-directory `path` escape hatch. An explicitly configured list errors loudly on a name that can't be probed (a user statement, not best-effort); the built-in curated default silently skips a missing name (an implicit default must never fail a target that never calls it). Scoped to Driver::from_options_exec/bash/sh (the .hephconfig-driven entry point, where `hostbin` is already registered) — the bare new_exec/new_bash/new_sh constructors and the interactive --shell fallback keep the old ambient fallback, since ~40 existing test call sites don't register `hostbin`. Went through product-vision/feature-quality/hermeticity design review before implementation, and a code-quality pass on the diff after. Keeping ambient-$PATH resolution via hostbin (rather than a fixed-dir resolver for the actual binary, only for the inclusion gate) was an explicit call by the repo owner, accepting env -i / minimal-PATH hosts and per-shell-setup binary divergence as a known, documented limitation. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0173dXh8yqPq5FYV6bBuXRnY
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.
Summary
exec/bash/shno longer fall back to a hardcodedPATH=/usr/local/bin:/usr/bin:/binwhen.hephconfigdoesn't setpath— that blindly trusted whatever happened to be installed in those 3 directories, differing across hosts/distros/CI images (even thoughPATHwas never part of the target's cache key).default_toolsdriver option: a curated list of common POSIX tools (sh,bash,cat,grep,sed,tar,sleep, ...), each turned into an implicit, hashed//@heph/bin:<name>tool dependency — reusing the existinghostbin/tool_group_inputs/bin_dir-symlink machinery an explicit target-leveltools = [...]dependency already goes through, rather than a bespoke PATH-directory trust./usr/local/bin:/usr/bin:/bin), not heph's own ambient$PATH— so the curated set is identical across shell setups on a given host. The concrete binary is still resolved (and hashed into the target's input hash) for real by the existinghostbindriver's ownwhichat run time.default_toolsand the existing raw-directorypathescape hatch are mutually exclusive. A user-configureddefault_toolslist errors loudly on a name that can't be probed (a statement, not best-effort); the built-in curated default silently skips a missing name (an implicit default must never fail a target that never calls it).Driver::from_options_exec/bash/sh(the real.hephconfig-driven entry point, wherehostbinis already registered inbootstrap.rs) — the barenew_exec/new_bash/new_shconstructors and the interactive--shellfallback keep the old ambient-PATH fallback, since ~40 existing test call sites across the engine/e2e suites don't registerhostbin.EXEC_DEF_FORMAT_VERSIONbumped 1→2 (a new hashed field,default_tool_inputs, was added to the per-target def hash — invalidates every exec/bash/sh cache entry deliberately, not by coincidence).Process
This went through the standing review board before and after implementation, per this repo's
CLAUDE.md://@heph/bin:<name>+tool_group_inputspipeline instead of a bespokewhich+symlink-directory mechanism — reuses tested, already-hashed infra and closes the cache-correctness gap for free.sleepmissing from the curated list brokecrates/bin-e2e/tests/tui_pty.rsandshell_pty.rs, plus theexample/workspaces) and several MAJOR/MINOR findings, all fixed — see commit body and diff for detail (staging annotations for cheaper per-sandbox cost, explicit-vs-curated error semantics, dedup, a more accurate spawn-failure diagnostic, etc).One design fork came up mid-review that this repo's own conventions say isn't an agent's call to make alone (per-platform/per-environment behavior): default tools are resolved via
hostbin'swhich, which reads heph's own invoking process's$PATH, not a fixed list — so (a)env -i heph run ...(empty/minimal PATH — CI, systemd, sandboxed hosts) breaks every exec/bash/sh target where the old hardcoded PATH always worked, and (b) two devs on the same host/arch with different shell setups can get a different concrete binary for the same curated name. Raised this directly; the call was to keep ambient-$PATHresolution viahostbinas-is and document it as a known limitation rather than build a more invasive fixed-directory resolver for this PR. See the doc comment onDEFAULT_TOOLS_PROBE_PATHincrates/plugin-exec/src/pluginexec/mod.rs.Test plan
cargo test -p plugin-exec— 99 unit tests, including new coverage for config decode/validation (mutual exclusion, dedup, explicit-vs-curated probe error semantics, invalid tool names),parse()wiring (hashed//@heph/bin:<name>inputs, hash changes ondefault_toolschange), and the existing suite unaffected.cargo test -p e2e --test pluginexec_default_tools— new e2e test file against a realEnginewithhostbinregistered: default tool resolves without an explicittools=dep, a tool outside the list fails clearly, an overlapping explicittools=dep doesn't conflict with a same-named default, and the actual shipped curated list (no config override) runs something real.cargo clippy --all-targets -- -D warnings/cargo fmt --checkclean on touched crates.e2e(releasebin-e2esuite, all test binaries) green after thesleepfix — confirmedctrl_c_interrupts_foreground_child_not_the_sessionandtui_renders_the_run_and_restores_the_terminal(the two tests the missing-sleepBLOCKER broke) both pass.🤖 Generated with Claude Code
https://claude.ai/code/session_0173dXh8yqPq5FYV6bBuXRnY