Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
2074931
Update GPU Inference and Model Qualification
PSchmiedmayer Jul 21, 2026
f54e45c
Address Pull Request Review Feedback
PSchmiedmayer Jul 21, 2026
fd28aa5
Enable Commit-Scoped GPU Candidate Testing
PSchmiedmayer Jul 21, 2026
1ede85e
Make T4 GPU Inference Memory-Safe
PSchmiedmayer Jul 21, 2026
027b712
Allow Platform-Bounded GPU Contexts
PSchmiedmayer Jul 21, 2026
7fc481b
Cache GPU Environment Discovery
PSchmiedmayer Jul 21, 2026
1a8c5c5
Validate GPU Execution Mode Metadata
PSchmiedmayer Jul 21, 2026
ff11c82
Harden Terra GPU Qualification
PSchmiedmayer Jul 21, 2026
7e02f0c
Format Qualification Contract Tests
PSchmiedmayer Jul 21, 2026
b2c4402
Use OpenHands Tool Conversion for Managed Models
PSchmiedmayer Jul 21, 2026
b71657a
Align Runtime Smoke Tests With OpenHands Tool Conversion
PSchmiedmayer Jul 21, 2026
9cc0ea5
Qualify The Terra T4 Model Configuration
PSchmiedmayer Jul 21, 2026
1badbaf
Record The Terra Qualification Evidence
PSchmiedmayer Jul 21, 2026
6054501
Reuse GPU Images Across Qualification Profiles
PSchmiedmayer Jul 21, 2026
ddd3e69
Record Terra Model Qualification Results
PSchmiedmayer Jul 21, 2026
62fe0ff
Format Terra Qualification Tests
PSchmiedmayer Jul 21, 2026
14e6adf
Resolve Sharp Security Advisories
PSchmiedmayer Jul 21, 2026
dcf93bd
Add Reusable GPU Qualification Profiles
PSchmiedmayer Jul 22, 2026
4387f95
Align External Qualification Evidence
PSchmiedmayer Jul 22, 2026
3cafe76
Format Qualification Matrix Tests
PSchmiedmayer Jul 22, 2026
56ace23
Tighten GPU Qualification Contracts
PSchmiedmayer Jul 22, 2026
2139e11
Qualify Capable GPU Model Profiles
PSchmiedmayer Jul 22, 2026
e76969a
Cover FlashInfer Sampler Opt-In
PSchmiedmayer Jul 22, 2026
d4867fd
Restore Native Tool Browser Expectations
PSchmiedmayer Jul 22, 2026
b79343d
Select OpenHands Tool Mode By Model
PSchmiedmayer Jul 22, 2026
5a380f9
Refine Terra Model Qualification Catalog
PSchmiedmayer Jul 22, 2026
c4adc66
Add GPU Capability Preflight Checks
PSchmiedmayer Jul 22, 2026
98221ac
Correct Terra Tensor Parallel Configuration
PSchmiedmayer Jul 22, 2026
8049684
Format GPU Qualification Tests
PSchmiedmayer Jul 22, 2026
3bccbe7
Fit Terra Context To T4 Memory
PSchmiedmayer Jul 22, 2026
df7c333
Expose All GPU Qualification Profiles
PSchmiedmayer Jul 22, 2026
eeca731
Simplify GPU Capability Aggregation
PSchmiedmayer Jul 22, 2026
c50a3c7
Use Eager Inference For Terra T4
PSchmiedmayer Jul 22, 2026
b664f2f
Qualify Qwen3 Coder On Terra
PSchmiedmayer Jul 22, 2026
41b6679
Tighten GPU And Model Metadata Contracts
PSchmiedmayer Jul 22, 2026
617c8c9
Bound GPU Qualification Cleanup
PSchmiedmayer Jul 22, 2026
6dd9521
Clarify Carina Allocation Limits
PSchmiedmayer Jul 22, 2026
e2c3318
Prepare 0.2.0 Beta 6 Release
PSchmiedmayer Jul 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion .github/workflows/container-smoke.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ jobs:

capable-model:
name: Capable Model OpenHands Acceptance (linux/amd64)
if: github.event_name == 'workflow_dispatch' && inputs.run_capable_model
if: inputs.run_capable_model
runs-on: ubuntu-24.04
timeout-minutes: 45
steps:
Expand Down Expand Up @@ -139,6 +139,20 @@ jobs:
--env HEARTWOOD_LOCAL_MODEL_PATH=/models/qwen25-7b-instruct-q4_k_m/Qwen2.5-7B-Instruct-Q4_K_M.gguf
heartwood-capable:local
bash /opt/heartwood/images/generic/scripts/capable_model_e2e.sh
- name: Prepare coding-agent qualification evidence
if: always()
run: sudo chown -R "$(id -u):$(id -g)" /tmp/heartwood-project
- name: Upload coding-agent qualification evidence
if: always()
uses: actions/upload-artifact@v7
with:
name: capable-model-qualification-${{ github.sha }}
path: |
/tmp/heartwood-project/heartwood-qualification.json
/tmp/heartwood-project/heartwood-replay.txt
/tmp/heartwood-project/heartwood-transcript.txt
if-no-files-found: warn
retention-days: 14

terra-smoke:
name: Terra image smoke test (linux/amd64)
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/create-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ jobs:
echo "tag already exists: ${RELEASE_VERSION}" >&2
exit 1
fi
- name: Verify recommended model sources
- name: Verify catalog model sources
run: python3 deploy/verify_model_sources.py --source-root .
- name: Verify release readiness on the exact commit
env:
Expand Down
9 changes: 3 additions & 6 deletions .github/workflows/dependency-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,8 @@ jobs:
- name: Review dependencies
uses: actions/dependency-review-action@v5.0.0
with:
# The CUDA 11.8 vLLM environment is isolated in the hashed GPU lock.
# The CUDA 12.9 vLLM environment is isolated in the hashed GPU lock.
# diskcache and torch have no patched compatible release; Heartwood
# does not load caches across trust domains or expose torch.jit.script
# to input. vLLM GHSA-8fr4-5q9j-m8gm is backported by removing the
# vulnerable config registry entry exactly as upstream PR 28126 does,
# with an exploit-regression check at build, install, and launch time.
# Revisit these exact exceptions with every vLLM update.
allow-ghsas: GHSA-w8v5-vhqr-4h9v, GHSA-rrmf-rvhw-rf47, GHSA-8fr4-5q9j-m8gm
# to input. Revisit these exact exceptions with every vLLM update.
allow-ghsas: GHSA-w8v5-vhqr-4h9v, GHSA-rrmf-rvhw-rf47
171 changes: 141 additions & 30 deletions .github/workflows/gpu-container-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,35 @@ name: GPU Container Image
on:
workflow_call:
workflow_dispatch:
inputs:
publish_commit_candidate:
description: Publish validated immutable GPU tags for this commit without moving channel tags
required: true
default: false
type: boolean
run_gpu_qualification:
description: Run the coding-agent acceptance suite on a protected self-hosted GPU runner
required: true
default: false
type: boolean
qualification_configuration:
description: Optional compatibility-matrix row used only when GPU qualification is enabled
required: false
default: terra-t4-qwen25-coder-7b-awq
type: choice
options:
- terra-t4-qwen25-coder-7b-awq
- terra-t4-qwen25-coder-14b-awq
- terra-2xt4-qwen3-coder-30b-awq
- terra-4xt4-qwen25-coder-32b-awq
- carina-l40s-qwen3-coder-30b-fp8
- carina-4xl40s-qwen3-coder-next-fp8
- carina-2xl40s-gpt-oss-120b
qualification_runner:
description: JSON array of protected self-hosted GPU runner labels
required: true
default: '["self-hosted","linux","x64","gpu"]'
type: string

concurrency:
group: gpu-container-image-${{ github.workflow }}-${{ github.ref }}
Expand Down Expand Up @@ -44,46 +73,117 @@ jobs:
--python-platform x86_64-manylinux_2_28 \
--generate-hashes \
--emit-index-url \
--exclude-newer 2026-07-15T00:00:00Z \
--exclude-newer 2026-07-20T00:00:00Z \
--override images/gpu/vllm-overrides.txt \
--exclude images/gpu/vllm-exclusions.txt \
--output-file images/gpu/vllm-requirements.txt \
images/gpu/vllm.in
cmp /tmp/vllm-requirements.expected images/gpu/vllm-requirements.txt
grep --fixed-strings 'vllm-0.10.1.1%2Bcu118' images/gpu/vllm-requirements.txt
grep --fixed-strings 'certifi-2026.6.17-py3-none-any.whl' images/gpu/vllm-requirements.txt
grep --fixed-strings 'ray==2.55.0' images/gpu/vllm-requirements.txt
grep --fixed-strings 'setuptools==78.1.1' images/gpu/vllm-requirements.txt
grep --fixed-strings 'torch-2.7.1%2Bcu118-cp312-cp312-manylinux_2_28_x86_64.whl' images/gpu/vllm-requirements.txt
grep --fixed-strings 'torchaudio-2.7.1%2Bcu118-cp312-cp312-manylinux_2_28_x86_64.whl' images/gpu/vllm-requirements.txt
grep --fixed-strings 'torchvision-0.22.1%2Bcu118-cp312-cp312-manylinux_2_28_x86_64.whl' images/gpu/vllm-requirements.txt
grep --fixed-strings 'xformers-0.0.31-cp39-abi3-manylinux_2_28_x86_64.whl' images/gpu/vllm-requirements.txt
grep --fixed-strings 'transformers==5.5.0' images/gpu/vllm-requirements.txt
grep --fixed-strings 'requests==2.34.2' images/gpu/vllm-requirements.txt
grep --fixed-strings 'urllib3==2.7.0' images/gpu/vllm-requirements.txt
grep --fixed-strings 'xgrammar==0.1.32' images/gpu/vllm-requirements.txt
grep --fixed-strings 'xgrammar==0.1.32' images/gpu/vllm-overrides.txt
grep --fixed-strings 'idna==3.18' images/gpu/vllm-requirements.txt
grep --fixed-strings 'idna==3.18' images/gpu/vllm-overrides.txt
grep --fixed-strings 'nvidia-cuda-runtime-cu11==11.8.89' images/gpu/vllm-requirements.txt
if grep --fixed-strings --quiet -- '--extra-index-url https://download.pytorch.org/whl/cu118' images/gpu/vllm-requirements.txt; then
echo 'CUDA artifacts must use immutable wheel URLs instead of exposing the CUDA index to general dependency resolution.' >&2
exit 1
fi
if grep --fixed-strings --quiet 'nvidia-cuda-runtime-cu13' images/gpu/vllm-requirements.txt; then
echo 'CUDA 13 is incompatible with the NVIDIA driver currently available on Terra.' >&2
exit 1
fi
if grep --fixed-strings --quiet 'certifi==2022.12.7' images/gpu/vllm-requirements.txt; then
echo 'The GPU lock must not use the obsolete CA bundle mirrored by the CUDA index.' >&2
exit 1
fi
grep --fixed-strings 'vllm-0.25.1%2Bcu129-cp38-abi3-manylinux_2_28_x86_64.whl' images/gpu/vllm-requirements.txt
grep --fixed-strings 'torch-2.11.0%2Bcu129-cp312-cp312-manylinux_2_28_x86_64.whl' images/gpu/vllm-requirements.txt
grep --fixed-strings 'torchaudio-2.11.0%2Bcu129-cp312-cp312-manylinux_2_28_x86_64.whl' images/gpu/vllm-requirements.txt
grep --fixed-strings 'torchvision-0.26.0%2Bcu129-cp312-cp312-manylinux_2_28_x86_64.whl' images/gpu/vllm-requirements.txt
grep --fixed-strings 'flashinfer-python==0.6.13' images/gpu/vllm-requirements.txt
grep --fixed-strings 'nvidia-cuda-runtime-cu12==12.9.79' images/gpu/vllm-requirements.txt
grep --fixed-strings 'xgrammar==0.2.3' images/gpu/vllm-requirements.txt
grep --fixed-strings -- '--hash=sha256:' images/gpu/vllm-requirements.txt
python3 deploy/verify_gpu_compatibility.py
python3 -m py_compile \
images/gpu/qualification_config.py \
images/gpu/verify_vllm.py \
images/generic/scripts/verify_coding_agent_e2e.py \
deploy/verify_gpu_compatibility.py
bash -n images/gpu/start_vllm.sh
bash -n images/gpu/heartwood-vllm
bash -n images/gpu/install_runtime.sh
bash -n images/gpu/coding_agent_e2e.sh
bash -n images/generic/scripts/coding_agent_e2e.sh
test -x images/gpu/start_vllm.sh
test -x images/gpu/heartwood-vllm
test -x images/gpu/install_runtime.sh
test -x images/gpu/coding_agent_e2e.sh
test -x images/generic/scripts/coding_agent_e2e.sh

gpu-qualification:
name: GPU Coding-Agent Qualification
if: github.event_name == 'workflow_dispatch' && inputs.run_gpu_qualification
needs: contract
runs-on: ${{ fromJSON(inputs.qualification_runner) }}
timeout-minutes: 180
environment: gpu-qualification
permissions:
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@v7
with:
persist-credentials: false
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
with:
driver: docker
- name: Build the locked GPU runtime
run: >-
docker buildx bake --file docker-bake.hcl --load
--set runtime-gpu-nvidia.platform=linux/amd64
--set runtime-gpu-nvidia.tags=heartwood-gpu-qualification:local
runtime-gpu-nvidia
- name: Prepare isolated model and project storage
run: |
sudo mkdir -p "${RUNNER_TEMP}/heartwood-gpu-model" "${RUNNER_TEMP}/heartwood-gpu-project"
sudo chown -R 10001:10001 \
"${RUNNER_TEMP}/heartwood-gpu-model" "${RUNNER_TEMP}/heartwood-gpu-project"
- name: Resolve qualification model
id: model
env:
CONFIGURATION_ID: ${{ inputs.qualification_configuration }}
run: |
payload="$(python3 images/gpu/qualification_config.py "${CONFIGURATION_ID}")"
echo "snapshot=$(jq -r '.configuration.model_snapshot' <<<"${payload}")" >> "${GITHUB_OUTPUT}"
echo "platform=$(jq -r '.configuration.platform' <<<"${payload}")" >> "${GITHUB_OUTPUT}"
- name: Download and verify the pinned model
env:
SNAPSHOT: ${{ steps.model.outputs.snapshot }}
run: >-
docker run --rm --gpus all
--volume "${RUNNER_TEMP}/heartwood-gpu-model:/workspace"
heartwood-gpu-qualification:local
heartwood models download "${SNAPSHOT}"
- name: Run GPU coding-agent qualification without network
env:
CONFIGURATION_ID: ${{ inputs.qualification_configuration }}
PLATFORM_ID: ${{ steps.model.outputs.platform }}
SNAPSHOT: ${{ steps.model.outputs.snapshot }}
run: >-
docker run --rm --gpus all --network none --read-only --shm-size=16g
--cap-drop ALL --security-opt no-new-privileges=true --pids-limit 2048
--tmpfs /tmp:rw,nosuid,nodev,size=8g
--tmpfs /home/heartwood/.cache:rw,nosuid,nodev,size=2g,uid=10001,gid=10001,mode=0700
--tmpfs /home/heartwood/.openhands:rw,nosuid,nodev,size=512m,uid=10001,gid=10001,mode=0700
--volume "${RUNNER_TEMP}/heartwood-gpu-model/.heartwood/models/${SNAPSHOT}:/models/${SNAPSHOT}:ro"
--volume "${RUNNER_TEMP}/heartwood-gpu-project:/workspace"
--env HEARTWOOD_CAPABLE_PROJECT=/workspace
--env HEARTWOOD_GPU_CONFIGURATION_ID="${CONFIGURATION_ID}"
--env HEARTWOOD_LOCAL_MODEL_PATH="/models/${SNAPSHOT}"
--env HEARTWOOD_PLATFORM="${PLATFORM_ID}"
heartwood-gpu-qualification:local
bash /opt/heartwood/images/gpu/coding_agent_e2e.sh
- name: Prepare GPU qualification evidence
if: always()
run: >-
sudo chown -R "$(id -u):$(id -g)"
"${RUNNER_TEMP}/heartwood-gpu-project"
- name: Upload GPU qualification evidence
if: always()
uses: actions/upload-artifact@v7
with:
name: gpu-qualification-${{ inputs.qualification_configuration }}-${{ github.sha }}
path: |
${{ runner.temp }}/heartwood-gpu-project/heartwood-qualification.json
${{ runner.temp }}/heartwood-gpu-project/heartwood-replay.txt
${{ runner.temp }}/heartwood-gpu-project/heartwood-transcript.txt
if-no-files-found: warn
retention-days: 30

pull-request-build:
name: Build GPU candidate ${{ matrix.target }}
Expand Down Expand Up @@ -126,7 +226,9 @@ jobs:

build:
name: Build And Validate ${{ matrix.target }}
if: github.ref == 'refs/heads/main'
if: >-
github.ref == 'refs/heads/main'
|| (github.event_name == 'workflow_dispatch' && inputs.publish_commit_candidate)
needs: contract
runs-on: ubuntu-24.04
permissions:
Expand Down Expand Up @@ -183,6 +285,15 @@ jobs:
docker pull --platform linux/amd64 "${CANDIDATE}"
docker run --rm --platform linux/amd64 \
--entrypoint /opt/heartwood/images/gpu/verify_runtime.sh "${CANDIDATE}"
profiles="$(
docker run --rm --platform linux/amd64 \
--entrypoint heartwood-python "${CANDIDATE}" \
/opt/heartwood/images/gpu/qualification_config.py --list
)"
jq --exit-status '
length > 0
and all(.[].configuration_id; type == "string" and length > 0)
' <<<"${profiles}" >/dev/null
- name: Verify shared agent and platform interfaces
env:
CANDIDATE: ${{ steps.candidate.outputs.reference }}
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/main-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ jobs:
container-smoke:
name: Container Smoke Tests
uses: ./.github/workflows/container-smoke.yml
with:
run_capable_model: ${{ github.event_name != 'pull_request' }}
gpu-containers:
name: GPU Container Images
uses: ./.github/workflows/gpu-container-image.yml
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ concurrency:

jobs:
model-sources:
name: Verify Recommended Model Sources
name: Verify Catalog Model Sources
runs-on: ubuntu-latest
steps:
- name: Checkout repository
Expand Down
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ When project direction changes, update the relevant architecture or operations p
| Browser workflow | [documentation/use/browser.md](documentation/use/browser.md) |
| Command reference | [documentation/reference/cli.md](documentation/reference/cli.md) |
| Readiness states, stable diagnostics, and recovery steps | [documentation/reference/troubleshooting.md](documentation/reference/troubleshooting.md) |
| Qualified GPU runtime, model, and platform combinations | [documentation/reference/gpu-compatibility.md](documentation/reference/gpu-compatibility.md) |
| Product boundaries and durable technical rationale | [documentation/architecture/index.md](documentation/architecture/index.md) |
| Project, gateway, adapter, interface, and data-flow architecture | [documentation/architecture/system.md](documentation/architecture/system.md) |
| Security and controlled-data responsibilities | [documentation/operate/security.md](documentation/operate/security.md) |
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ docker run --rm -it \
--env HOME=/tmp \
-p 127.0.0.1:8767:8767 \
-v "$PWD:/workspace" \
ghcr.io/schmiedmayerlab/heartwood:0.2.0-beta.5 \
ghcr.io/schmiedmayerlab/heartwood:0.2.0-beta.6 \
heartwood --interface web --host 0.0.0.0
```

Expand Down
2 changes: 1 addition & 1 deletion VERSION.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
# SPDX-FileCopyrightText: 2026 Stanford University and the project authors (see CONTRIBUTORS.md)
# SPDX-License-Identifier: MIT

version = "0.2.0-beta.5"
version = "0.2.0-beta.6"
1 change: 0 additions & 1 deletion deploy/carina/bootstrap.sh
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,6 @@ images/gpu/install_runtime.sh \

export PATH="${root}/bootstrap/bin:${PATH}"
export LD_LIBRARY_PATH="${root}/bootstrap/lib${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}"
export VLLM_USE_FLASHINFER_SAMPLER=0

printf 'Heartwood: %s\n' "$("${root}/heartwood/bin/heartwood" --version)"
HEARTWOOD_VLLM_ROOT="${root}/vllm" \
Expand Down
24 changes: 12 additions & 12 deletions deploy/tests/native_installer_smoke.sh
Original file line number Diff line number Diff line change
Expand Up @@ -115,15 +115,13 @@ venv)
mkdir -p "${runtime}/bin"
cat >"${runtime}/bin/python" <<'COMMAND'
#!/usr/bin/env bash
if [[ "${1:-}" == */heartwood_vllm.py ]]; then
test "${2:-}" = "__heartwood_verify_runtime__"
grep --quiet 'GHSA-7rgv-gqhr-fxg3' "$1"
grep --quiet 'GHSA-65pc-fj4g-8rjx' "$1"
echo "Transformers synthetic integration and GPU security fixes verified"
if [[ "${1:-}" == */verify_vllm.py ]]; then
grep --quiet 'vllm_version' "$1"
grep --quiet 'cuda_13_qualified' "$1"
echo "Heartwood GPU runtime verified: synthetic CUDA 12.9 stack"
exit 0
fi
echo "vLLM: synthetic"
echo "PyTorch: synthetic (CUDA 11.8)"
echo "0.25.1+cu129 2.11.0+cu129 12.9"
COMMAND
cat >"${runtime}/bin/vllm" <<'COMMAND'
#!/usr/bin/env bash
Expand Down Expand Up @@ -323,14 +321,16 @@ test -x "${carina_runtime}/heartwood/bin/heartwood"
test -x "${carina_runtime}/vllm/bin/python"
test -x "${carina_runtime}/vllm/bin/vllm"
test -x "${carina_runtime}/vllm/bin/heartwood-vllm"
test -r "${carina_runtime}/vllm/bin/heartwood_vllm.py"
test -r "${carina_runtime}/vllm/bin/sitecustomize.py"
test -r "${carina_runtime}/vllm/bin/verify_vllm.py"
test -r "${carina_runtime}/vllm/bin/compatibility.toml"
test ! -e "${carina_runtime}/vllm/bin/heartwood_vllm.py"
test ! -e "${carina_runtime}/vllm/bin/sitecustomize.py"
test -x "${carina_runtime}/vllm/bin/hf"
test "$(file_mode "${carina_runtime}/vllm/bin/heartwood-vllm")" = "555"
test "$(file_mode "${carina_runtime}/vllm/bin/heartwood_vllm.py")" = "444"
test "$(file_mode "${carina_runtime}/vllm/bin/sitecustomize.py")" = "444"
test "$(file_mode "${carina_runtime}/vllm/bin/verify_vllm.py")" = "444"
test "$(file_mode "${carina_runtime}/vllm/bin/compatibility.toml")" = "444"
"${carina_runtime}/vllm/bin/heartwood-vllm" __heartwood_verify_runtime__ | \
grep --quiet 'GPU security fixes verified'
grep --quiet 'synthetic CUDA 12.9 stack'
test -L "${carina_installation}/bin/hf"
carina_current_target="$(readlink "${carina_installation}/current")"
test "$(readlink "${carina_installation}/bin/hf")" = \
Expand Down
Loading
Loading