Files
zeekay 67411192cd Programs by full path only, a home read from the environment alone
exe.rs is the one way Gen finds a program: by full path, from absolute
PATH entries only, so a session that starts in a repository cannot be
handed that repository's ./grok, ./hanzo-mcp or ./git. Agents, the
toolset, version probes and machine probes all go through it, the MCP
config names hanzo-mcp by full path, a probe's child gets the same PATH,
`--version` is given three seconds, and spawn refuses a bare name.

Root reads $HOME itself and Gen no longer links `dirs`: an unset, empty
or relative home is no home, never the passwd entry's. Only a binary's
main asks for the user's root (the __mcp proxy is handed it), and
root_is_the_one_resolver holds all of that structurally.

While an agent runs, SIGINT, SIGTERM and SIGHUP keep Gen up (TERM and
HUP pass to the agent), so a session always closes out and removes its
run homes; those are now run-<pid>-*, mode 0700, and a SIGKILLed one is
swept by the next run once its pid is gone. Crush on its own account
keeps its own data directory and history; only a routed run gets a home.

The host's profile is a moment's wait, so a host can read it under the
lock its refresh writes under, and the meter is asked for the session's
brand (gen refuses another brand's rather than read it wrong).

release: builds hold no secret and restore no cache, report each
archive's sha256 as a job output, and publish downloads each artifact by
exact name and refuses one whose digest is not its build's. cicd pins
hanzoai/ci by commit.
2026-10-16 07:42:47 -07:00

44 lines
2.0 KiB
YAML

# hanzoai/gen — the `gen` binary, and the `hanzo-gen` library `hanzo dev` runs.
#
# Gate only: no image, nothing to deploy. The release — five per-platform
# binaries on a GitHub release, named as hanzo.sh installs them — is
# .github/workflows/release.yml, from a tag set by hand.
#
# --locked so Cargo.lock is a fact rather than a suggestion. Rust comes from
# rustup when the runner has none; rust-toolchain.toml names the version.
test:
- name: build
run: |
set -euo pipefail
command -v cargo >/dev/null 2>&1 || curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain none
export PATH="$HOME/.cargo/bin:$PATH"
cargo build --locked
./target/debug/gen --version
./target/debug/gen --help >/dev/null
# The suite never touches a home. It runs twice, neither time in the runner's
# own: against an empty HOME it cannot write, and against an empty one it can,
# which must still be empty after. The runner is a person's machine (evo runs
# as its user), and a test that wrote there rewrote that person's agent
# configs. Cargo and rustup keep their own homes, named before HOME moves.
- name: test
run: |
set -euo pipefail
export CARGO_HOME="${CARGO_HOME:-$HOME/.cargo}" RUSTUP_HOME="${RUSTUP_HOME:-$HOME/.rustup}"
export PATH="$CARGO_HOME/bin:$PATH" RUSTC_WRAPPER=
unset XDG_DATA_HOME XDG_CONFIG_HOME XDG_CACHE_HOME XDG_STATE_HOME
ro=$(mktemp -d); tmp=$(mktemp -d)
trap 'chmod u+w "$ro"; rm -rf "$ro" "$tmp"' EXIT
chmod 0555 "$ro"
HOME="$ro" cargo test --locked
env -u HOME cargo test --locked
HOME="$tmp" cargo test --locked
left=$(find "$tmp" -mindepth 1 | head -20)
[ -z "$left" ] || { echo "::error::the test suite wrote into HOME:"; echo "$left"; exit 1; }
- name: clippy
run: |
set -euo pipefail
export PATH="$HOME/.cargo/bin:$PATH"
cargo clippy --locked --all-targets -- -D warnings