Fix: Install the whole Codex package so codex-code-mode-host sits beside bin/codex

Codex 0.165.0 ships as a package tree and runs bin/codex-code-mode-host,
codex-path/ and codex-resources/ relative to itself. The installer verified
the full archive but kept only bin/codex, so code mode failed. Keep the whole
verified tree, link ~/.local/bin/codex to its bin/codex, and replace the
receipted flat install earlier runs left behind once the new tree verifies.
This commit is contained in:
Gabriel Brown committed 2026-11-05 15:14:47 -05:00
1 parent 86f6e391b7
commit 6c8db4e845
3 files changed
+57 -16

No files matched your search

+4 -1
View File
@@ -77,7 +77,10 @@ matched the `digest` GitHub publishes for that release asset. The installer
accepts a Codex archive only when `tar -tzf` prints exactly the entries in
`codex-package.listing`. Both architectures share that listing. 0.165.0 dropped
the bundled `codex-resources/zsh/` and added `codex-resources/voice/`, and the
archives grew past 128 MiB, so `CODEX_*_MAX_BYTES` is 256 MiB. To bump Codex,
archives grew past 128 MiB, so `CODEX_*_MAX_BYTES` is 256 MiB. The installer keeps the
whole verified tree as the version directory and links `~/.local/bin/codex` to
its `bin/codex`, because Codex runs `bin/codex-code-mode-host` and reads
`codex-path/` and `codex-resources/` relative to itself. To bump Codex,
update `installers.conf`, regenerate the listing with `tar -tzf ARTIFACT`, and
run `tests/setup/package-provenance-contract`.
+25 -12
View File
@@ -417,20 +417,33 @@ _codex_version_matches() {
[[ "$output" =~ (^|[^0-9])${version_pattern}([^0-9]|$) ]]
}
# Codex ships as a package tree: bin/codex finds bin/codex-code-mode-host,
# codex-path/ and codex-resources/ beside itself, so the version directory keeps
# the whole verified tree and the active link points at its bin/codex.
_install_codex() (
local artifact_arch version_dir target bin_link parent expected_listing member
local stage archive listing staged_binary artifact_digest binary_digest
local retire_flat=0
stage=""
trap '[[ -z "$stage" ]] || rm -rf -- "$stage"' EXIT
# A retired flat install goes back if activation never happened.
trap '[[ -z "$stage" ]] || { [[ -d "$stage/retired" && ! -e "$version_dir" ]] \
&& mv -Tn -- "$stage/retired" "$version_dir"; rm -rf -- "$stage"; }' EXIT
trap 'exit 130' INT
trap 'exit 143' TERM
_set_artifact_arch || return 1
version_dir="$HOME/.local/lib/panama/codex/${INSTALLER_PROVENANCE[CODEX_VERSION]}"
target="$version_dir/codex"
target="$version_dir/bin/codex"
bin_link="$HOME/.local/bin/codex"
artifact_digest="${INSTALLER_PROVENANCE[CODEX_${artifact_arch}_SHA256]}"
binary_digest="${INSTALLER_PROVENANCE[CODEX_${artifact_arch}_BINARY_SHA256]}"
if [[ -e "$version_dir" || -L "$version_dir" ]]; then
# Earlier installs of this same reviewed artifact kept only the codex binary
# at the top of the version directory, without the helpers it needs. That
# directory carries our receipt, so it is replaced once the full tree verifies.
if [[ ! -e "$version_dir/bin" && ! -L "$version_dir/bin" ]] \
&& _runtime_receipt_matches "$version_dir" "$version_dir/codex" \
"$artifact_digest" "$binary_digest"; then
retire_flat=1
elif [[ -e "$version_dir" || -L "$version_dir" ]]; then
_runtime_receipt_matches "$version_dir" "$target" \
"$artifact_digest" "$binary_digest" || return 1
[[ -x "$target" ]] || return 1
@@ -459,24 +472,24 @@ _install_codex() (
while IFS= read -r member; do
_archive_path_is_safe "$member" || { rm -rf -- "$stage"; return 1; }
done <<<"$listing"
mkdir -m 0700 "$stage/extract" "$stage/version" \
mkdir -m 0700 "$stage/version" \
|| { rm -rf -- "$stage"; return 1; }
tar -xzf "$archive" --no-same-owner --no-same-permissions -C "$stage/extract" \
tar -xzf "$archive" --no-same-owner --no-same-permissions -C "$stage/version" \
|| { rm -rf -- "$stage"; return 1; }
_tree_links_stay_inside "$stage/extract" || { rm -rf -- "$stage"; return 1; }
_tree_hardlinks_stay_inside "$stage/extract" || { rm -rf -- "$stage"; return 1; }
staged_binary="$stage/extract/bin/codex"
_tree_links_stay_inside "$stage/version" || { rm -rf -- "$stage"; return 1; }
_tree_hardlinks_stay_inside "$stage/version" || { rm -rf -- "$stage"; return 1; }
staged_binary="$stage/version/bin/codex"
[[ -f "$staged_binary" && ! -L "$staged_binary" && -x "$staged_binary"
&& "$(sha256sum "$staged_binary" | awk '{ print $1 }')" == "$binary_digest" ]] \
|| { rm -rf -- "$stage"; return 1; }
_codex_version_matches "$staged_binary" \
|| { rm -rf -- "$stage"; return 1; }
mv -- "$staged_binary" "$stage/version/codex" \
|| { rm -rf -- "$stage"; return 1; }
_write_runtime_receipt "$stage/version" "$artifact_digest" "$binary_digest" \
|| { rm -rf -- "$stage"; return 1; }
_activate_directory_no_replace "$stage/version" "$version_dir" \
|| { rm -rf -- "$stage"; return 1; }
if (( retire_flat )); then
mv -Tn -- "$version_dir" "$stage/retired" || return 1
fi
_activate_directory_no_replace "$stage/version" "$version_dir" || return 1
_runtime_receipt_matches "$version_dir" "$target" \
"$artifact_digest" "$binary_digest" || { rm -rf -- "$stage"; return 1; }
_codex_version_matches "$target" || { rm -rf -- "$stage"; return 1; }