diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 53767473a365c9a570a951312195ef772ea49a1f..25cd201e87692b1a640bd784dee750bf5e168f07 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -2,11 +2,10 @@ image: alpine
 
 variables:
   ## External images
-  DOCKER_IMAGE: docker.io/docker:25.0.5
+  DOCKER_IMAGE: docker.io/docker:27.2.0
   SINGULARITY_IMAGE: quay.io/singularity/singularity:v3.11.5
 
   ## Default versions are specified in packages.yaml but can be overridden
-  ## note: nightly builds will always use the master/main branch
   EDM4EIC_VERSION: ""
   EICRECON_VERSION: ""
   EPIC_VERSION: ""
@@ -40,6 +39,8 @@ variables:
   ## Internal tag used for the CI
   INTERNAL_TAG: "pipeline-${CI_PIPELINE_ID}"
 
+  PIPELINE_NAME: "$CI_COMMIT_TITLE"
+
 stages:
   - status-pending
   - config
@@ -269,8 +270,10 @@ base:
   needs:
     - version
   script:
+    - attempts=0
+    - nocache=""
     - while !
-      docker buildx build --push ${BUILD_OPTIONS}
+      docker buildx build --push ${BUILD_OPTIONS} ${nocache}
                    --tag ${CI_REGISTRY}/${CI_PROJECT_PATH}/${BUILD_IMAGE}:${INTERNAL_TAG}
                    ${EXPORT_TAG:+
                      ${CI_PUSH:+--tag ${CI_REGISTRY}/${CI_PROJECT_PATH}/${BUILD_IMAGE}:${EXPORT_TAG}}
@@ -286,10 +289,15 @@ base:
                    2>&1 | tee build.log
       ; do
         if grep "unknown blob" build.log ; then
-          BUILD_OPTIONS="--no-cache ${BUILD_OPTIONS}" ;
+          nocache="--no-cache" ;
         else
           exit 1 ;
-        fi
+        fi ;
+        if test ${attempts} -ge 1 ; then
+          echo "Failed to build on second attempt!" ;
+          exit 1 ;
+        fi ;
+        let attempts=$attempts+1 ;
       done
 
 
@@ -353,8 +361,10 @@ eic:
       source eic-spack.sh ;
       export SPACK_VERSION ;
       cat mirrors.yaml.in | envsubst > mirrors.yaml
+    - attempts=0
+    - nocache=""
     - while !
-      docker buildx build --push ${BUILD_OPTIONS}
+      docker buildx build --push ${BUILD_OPTIONS} ${nocache}
                    --tag ${CI_REGISTRY}/${CI_PROJECT_PATH}/${BUILD_IMAGE}${ENV}:${INTERNAL_TAG}-${BUILD_TYPE}
                    --tag ${CI_REGISTRY}/${CI_PROJECT_PATH}/${BUILD_IMAGE/eic/jug}${ENV}:${INTERNAL_TAG}-${BUILD_TYPE}
                    ${EXPORT_TAG:+
@@ -427,10 +437,10 @@ eic:
                      ${JUGGLER_VERSION:+--build-arg JUGGLER_VERSION=${JUGGLER_VERSION}}
                    }
                    ${IF_BUILD_NIGHTLY+
-                     --build-arg EDM4EIC_VERSION=main
-                     --build-arg EICRECON_VERSION=main
-                     --build-arg EPIC_VERSION=main
-                     --build-arg JUGGLER_VERSION=main
+                     --build-arg EDM4EIC_VERSION=${EDM4EIC_VERSION:-main}
+                     --build-arg EICRECON_VERSION=${EICRECON_VERSION:-main}
+                     --build-arg EPIC_VERSION=${EPIC_VERSION:-main}
+                     --build-arg JUGGLER_VERSION=${JUGGLER_VERSION:-main}
                    }
                    --build-arg ENV=${ENV}
                    --build-arg jobs=${JOBS}
@@ -441,10 +451,15 @@ eic:
                    2>&1 | tee build.log
       ; do
         if grep "unknown blob" build.log ; then
-          BUILD_OPTIONS="--no-cache ${BUILD_OPTIONS}" ;
+          nocache="--no-cache" ;
         else
           exit 1 ;
-        fi
+        fi ;
+        if test ${attempts} -ge 1 ; then
+          echo "Failed to build on second attempt!" ;
+          exit 1 ;
+        fi ;
+        let attempts=$attempts+1 ;
       done
 
 .singularity:
@@ -507,7 +522,7 @@ jug_xl:singularity:nightly:
     DETECTOR_REPOSITORYURL: 'https://github.com/eic/epic.git'
     BENCHMARKS_CONTAINER: "eic_xl"
     BENCHMARKS_REGISTRY: "$CI_REGISTRY_IMAGE"
-    PIPELINE_NAME: "$PIPELINE_NAME"
+    PIPELINE_NAME: "eic_container: $CI_PIPELINE_NAME"
   allow_failure: false
 
 benchmarks:detector:default:
@@ -681,7 +696,9 @@ clean_pipeline:
           --filter=reference=${registry}/*:pipeline-*
           --format "{{.ID}} {{.Repository}} {{.Tag}} {{.CreatedSince}}" ;
       done
-    - for registry in
+    - # prevent grep exit code 1 when no match
+      mygrep() { grep "$@" || test $? = 1; } ;
+      for registry in
         eicweb
         eicweb.phy.anl.gov:4567/containers/eic_container
       ; do 
@@ -689,8 +706,8 @@ clean_pipeline:
           --filter=reference=${registry}/*:pipeline-*
           --format "{{.ID}} {{.Repository}} {{.Tag}} {{.CreatedSince}}" ;
       done
-      | grep -v ${CI_PIPELINE_ID}
-      | grep -v "hours ago"
+      | mygrep -v ${CI_PIPELINE_ID}
+      | mygrep -v "hours ago"
       | sed -n -E 's/pipeline-([0-9]+)(-.*){0,1}\s+.*$/\1 &/p'
       | while read id repository pipeline_id tag N durations ago ; do
         echo "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/pipelines/${pipeline_id}" ;
diff --git a/containers/jug/dev.Dockerfile b/containers/jug/dev.Dockerfile
index ee6c6e02c74813e4d5db4b8026cd37d2a8f949d1..807d5377ce9d394fa75de61df2114d71c14e6536 100644
--- a/containers/jug/dev.Dockerfile
+++ b/containers/jug/dev.Dockerfile
@@ -6,7 +6,7 @@ ARG RUNTIME_IMAGE="debian_stable_base"
 ARG INTERNAL_TAG="testing"
 
 ## ========================================================================================
-## STAGE0: spack image
+## STAGE 0: spack image
 ## EIC spack image with spack and eic-spack repositories
 ## ========================================================================================
 FROM ${DOCKER_REGISTRY}${BUILDER_IMAGE}:${INTERNAL_TAG} as spack
@@ -56,6 +56,7 @@ if [ -n "${SPACK_CHERRYPICKS}" ] ; then
     fi
   done
 fi
+git -C $SPACK_ROOT gc --prune=all --aggressive
 sed -i 's/timeout=60/timeout=None/' $SPACK_ROOT/lib/spack/spack/stage.py
 ln -s $SPACK_ROOT/share/spack/docker/entrypoint.bash /usr/bin/docker-shell
 ln -s $SPACK_ROOT/share/spack/docker/entrypoint.bash /usr/bin/interactive-shell
@@ -132,7 +133,7 @@ EOF
 
 
 ## ========================================================================================
-## STAGE1: builder
+## STAGE 1: builder
 ## EIC builder image with spack environment
 ## ========================================================================================
 FROM spack as builder
@@ -157,11 +158,12 @@ make --jobs ${jobs} --keep-going --directory /opt/spack-environment \
   SPACK_ENV=${SPACK_ENV} \
   BUILDCACHE_OCI_PROMPT="eicweb" \
   BUILDCACHE_OCI_FINAL="ghcr"
-spack find --implicit --no-groups \
+spack gc --yes-to-all
+spack find --long --no-groups \
 | sed -e '1,/Installed packages/d;s/\([^@]*\).*/\1/g' \
-| uniq -d | grep -v py-pip | grep -v py-cython \
+| uniq -D -f1 | grep -v -w -e "\(epic\|py-pip\|py-cython\)" \
 | tee /tmp/duplicates.txt
-test -s /tmp/duplicates.txt && exit 1
+test -s /tmp/duplicates.txt && ( cat /tmp/duplicates.txt | while read hash spec ; do spack spec --long /${hash} ; done ) && exit 1
 ccache --show-stats
 ccache --zero-stats
 EOF
@@ -208,11 +210,12 @@ spack concretize --fresh --force
 make --jobs ${jobs} --keep-going --directory /opt/spack-environment \
   SPACK_ENV=${SPACK_ENV} \
   BUILDCACHE_OCI_FINAL="eicweb"
-spack find --implicit --no-groups \
+spack gc --yes-to-all
+spack find --long --no-groups \
 | sed -e '1,/Installed packages/d;s/\([^@]*\).*/\1/g' \
-| uniq -d | grep -v py-pip | grep -v py-cython \
+| uniq -D -f1 | grep -v -w -e "\(epic\|py-pip\|py-cython\)" \
 | tee /tmp/duplicates.txt
-test -s /tmp/duplicates.txt && exit 1
+test -s /tmp/duplicates.txt && ( cat /tmp/duplicates.txt | while read hash spec ; do spack spec --long /${hash} ; done ) && exit 1
 ccache --show-stats
 ccache --zero-stats
 EOF
@@ -241,35 +244,16 @@ set -e
 spack env activate --sh --dir ${SPACK_ENV} > /etc/profile.d/z10_spack_environment.sh
 EOF
 
-## make sure we have the entrypoints setup correctly
-ENTRYPOINT []
-CMD ["bash", "--rcfile", "/etc/profile", "-l"]
-USER 0
-WORKDIR /
-
-
-## ========================================================================================
-## STAGE 2: staging image with unnecessariy packages removed and stripped binaries
-## ========================================================================================
-FROM builder as staging
-
-# Garbage collect in environment
-RUN spack -e ${SPACK_ENV} gc -y
-
-# Garbage collect in git
-#RUN git -C $SPACK_ROOT gc --prune=all --aggressive
-
-## Bugfix to address issues loading the Qt5 libraries on Linux kernels prior to 3.15
-## See
-#https://askubuntu.com/questions/1034313/ubuntu-18-4-libqt5core-so-5-cannot-open-shared-object-file-no-such-file-or-dir
-## and links therin for more info
+## Fixup /opt/detector/epic-git.fcf90937193c983c0af2acf1251e01f2e2c3a259_main
 RUN <<EOF
-set -ex
-if [ -f /opt/local/lib/libQt5Core.so ] ; then
-  strip --remove-section=.note.ABI-tag /opt/local/lib/libQt5Core.so
-fi
+shopt -s nullglob
+cd /opt/detector
+for detector in epic-git.*_* ; do
+  ln -s ${detector} epic-${detector/*_/}
+done
 EOF
 
+## Fill jug_info
 RUN <<EOF
 set -ex
 spack debug report | sed "s/^/ - /" | sed "s/\* \*\*//" | sed "s/\*\*//" >> /etc/jug_info
@@ -286,15 +270,6 @@ COPY profile.d/a00_cleanup.sh /etc/profile.d
 COPY profile.d/z11_jug_env.sh /etc/profile.d
 COPY singularity.d /.singularity.d
 
-## Fixup /opt/detector/epic-git.fcf90937193c983c0af2acf1251e01f2e2c3a259_main
-RUN <<EOF
-shopt -s nullglob
-cd /opt/detector
-for detector in epic-git.*_* ; do
-  ln -s ${detector} epic-${detector/*_/}
-done
-EOF
-
 ## Add minio client into /opt/local/bin
 ADD --chmod=0755 https://dl.min.io/client/mc/release/linux-amd64/mc /opt/local/bin/mc-amd64
 ADD --chmod=0755 https://dl.min.io/client/mc/release/linux-arm64/mc /opt/local/bin/mc-arm64
@@ -308,9 +283,15 @@ for t in ${target[*]} ; do
 done
 EOF
 
+## make sure we have the entrypoints setup correctly
+ENTRYPOINT []
+CMD ["bash", "--rcfile", "/etc/profile", "-l"]
+USER 0
+WORKDIR /
+
 
 ## ========================================================================================
-## STAGE 3
+## STAGE 2
 ## Lean target image
 ## ========================================================================================
 FROM ${DOCKER_REGISTRY}${RUNTIME_IMAGE}:${INTERNAL_TAG} as runtime
@@ -320,17 +301,17 @@ LABEL maintainer="Sylvester Joosten <sjoosten@anl.gov>" \
       name="jug_xl" \
       march="$TARGETPLATFORM"
 
-## copy over everything we need from staging
-COPY --from=staging /opt/spack /opt/spack
-COPY --from=staging /opt/spack-environment /opt/spack-environment
-COPY --from=staging /opt/software /opt/software
-COPY --from=staging /opt/._local /opt/._local
-COPY --from=staging /opt/._detector /opt/._detector
-COPY --from=staging /etc/profile.d /etc/profile.d
-COPY --from=staging /etc/jug_info /etc/jug_info
-COPY --from=staging /etc/eic-env.sh /etc/eic-env.sh
-COPY --from=staging /.singularity.d /.singularity.d
-COPY --from=staging /usr/bin/docker-shell /usr/bin/docker-shell
+## copy over everything we need from builder
+COPY --from=builder /opt/spack /opt/spack
+COPY --from=builder /opt/spack-environment /opt/spack-environment
+COPY --from=builder /opt/software /opt/software
+COPY --from=builder /opt/._local /opt/._local
+COPY --from=builder /opt/._detector /opt/._detector
+COPY --from=builder /etc/profile.d /etc/profile.d
+COPY --from=builder /etc/jug_info /etc/jug_info
+COPY --from=builder /etc/eic-env.sh /etc/eic-env.sh
+COPY --from=builder /.singularity.d /.singularity.d
+COPY --from=builder /usr/bin/docker-shell /usr/bin/docker-shell
 
 ## Use spack entrypoint. NOTE: Requires `set -ex` in all multi-line scripts!
 ENV SPACK_ROOT=/opt/spack
diff --git a/eic-spack.sh b/eic-spack.sh
index a9cb03135c5027dd1e1ed751e9e2c6e7271c525f..f863a8871b6f45e0942a9b52d2a006b9dff57059 100644
--- a/eic-spack.sh
+++ b/eic-spack.sh
@@ -3,4 +3,4 @@ EICSPACK_ORGREPO="eic/eic-spack"
 
 ## EIC spack commit hash or github version, e.g. v0.19.7
 ## note: nightly builds could use a branch e.g. releases/v0.19
-EICSPACK_VERSION="c8429aea4cb76c3dc40b301b4a5b375976fce674"
+EICSPACK_VERSION="bd66c9c7ff9f720567f12f13b49233198efa5132"
diff --git a/mirrors.yaml.in b/mirrors.yaml.in
index 62c99cc7fc487a193996e96540cd1edd4e29fd3e..3ccc29313a2492c06330e1833d839eb3f1821a2e 100644
--- a/mirrors.yaml.in
+++ b/mirrors.yaml.in
@@ -22,7 +22,7 @@ mirrors:
       - ${GITHUB_REGISTRY_USER}
       - ${GITHUB_REGISTRY_TOKEN}
   eics3rw:
-    autopush: true
+    autopush: false
     signed: false
     fetch:
       url: s3://eictest/EPIC/spack/${SPACK_VERSION}
diff --git a/spack-environment/Makefile b/spack-environment/Makefile
index 9b363d3b3b30d7f0147de33b82012e12d860250c..0ce2ee2c35e0745aa8f70f6aafb8e95ab10ab44c 100644
--- a/spack-environment/Makefile
+++ b/spack-environment/Makefile
@@ -1,6 +1,6 @@
 MAKEFLAGS += -Orecurse
 
-SPACK ?= spack
+SPACK ?= spack --backtrace
 SPACK_INSTALL_FLAGS += --no-check-signature --show-log-on-error
 
 export SPACK_COLOR = always
@@ -22,15 +22,15 @@ include $(SPACK_ENV)/spack.mk
 endif
 
 $(SPACK_ENV)/push: $(addprefix $(SPACK_ENV)/push/,$($(SPACK_ENV)/SPACK_PACKAGE_IDS))
-	$(foreach buildcache, $(BUILDCACHE_S3_FINAL), $(SPACK) buildcache push --unsigned $(buildcache) ;)
+	$(foreach buildcache, $(BUILDCACHE_S3_FINAL), $(SPACK) buildcache push --private --unsigned $(buildcache) ;)
 	$(foreach buildcache, $(BUILDCACHE_S3_FINAL), $(SPACK) buildcache update-index $(buildcache) ;)
 	$(foreach buildcache, $(BUILDCACHE_S3_PROMPT), $(SPACK) buildcache update-index $(buildcache) ;)
-	$(foreach buildcache, $(BUILDCACHE_OCI_FINAL), $(SPACK) buildcache push --unsigned --base-image $(BUILDCACHE_OCI_BASE_IMAGE) $(buildcache) | grep -v "Using cached archive" ;)
+	$(foreach buildcache, $(BUILDCACHE_OCI_FINAL), $(SPACK) buildcache push --private --unsigned --base-image $(BUILDCACHE_OCI_BASE_IMAGE) $(buildcache) | grep -v "Using cached archive" ;)
 
 $(SPACK_ENV)/push/%: $(SPACK_ENV)/install/%
 	@mkdir -p $(dir $@)
-	$(foreach buildcache, $(BUILDCACHE_S3_PROMPT), $(SPACK) buildcache push --unsigned --only=package $(buildcache) /$(HASH) ;) # push $(SPEC)
-	$(foreach buildcache, $(BUILDCACHE_OCI_PROMPT), $(SPACK) buildcache push --unsigned --base-image $(BUILDCACHE_OCI_BASE_IMAGE) $(buildcache) /$(HASH) | grep -v "Using cached archive" ;) # push $(SPEC)
+	$(foreach buildcache, $(BUILDCACHE_S3_PROMPT), $(SPACK) buildcache push --private --unsigned --only=package $(buildcache) /$(HASH) ;) # push $(SPEC)
+	$(foreach buildcache, $(BUILDCACHE_OCI_PROMPT), $(SPACK) buildcache push --private --unsigned --base-image $(BUILDCACHE_OCI_BASE_IMAGE) $(buildcache) /$(HASH) | grep -v "Using cached archive" ;) # push $(SPEC)
 	@touch $@
 
 $(SPACK_ENV)/spack.lock: $(SPACK_ENV)/spack.yaml Makefile
diff --git a/spack-environment/cuda/spack.yaml b/spack-environment/cuda/spack.yaml
index 1717fe4b97cca9e763578066cca2c1b366dabe38..414abd26c2daf595f7fe8c9322f7e332a12275f2 100644
--- a/spack-environment/cuda/spack.yaml
+++ b/spack-environment/cuda/spack.yaml
@@ -28,11 +28,11 @@ spack:
   - eigen
   - emacs
   - epic@main # EPIC_VERSION
-  - epic@24.04.0
   - epic@24.05.0
   - epic@24.05.2
   - epic@24.06.0
   - epic@24.07.0
+  - epic@24.08.0
   - fastjet
   - fjcontrib
   - fmt
diff --git a/spack-environment/packages.yaml b/spack-environment/packages.yaml
index c6200b2cba764c2f6e998504c2285551e9f4d8c2..1e3de1fca55f0fdcd5528546261b4d2608e44dbe 100644
--- a/spack-environment/packages.yaml
+++ b/spack-environment/packages.yaml
@@ -14,12 +14,13 @@ packages:
     require:
     - '%gcc'
     - any_of: [+ipo, '@:']
+    - any_of: [build_system=cmake, '@:']
     - any_of: [build_type=Release, '@:']
-    - any_of: [^py-pip@23.1.2, '@:']
   acts:
     require:
-    - '@31.2.0'
-    - cxxstd=20 +binaries +dd4hep +edm4hep +examples +fatras +geant4 +identification +json +onnx +podio +python +tgeo
+    - '%clang'
+    - '@33.1.0'
+    - cxxstd=20 +dd4hep +edm4hep +examples +fatras +geant4 +identification +json +onnx +podio +python +tgeo
   actsvg:
     require:
     - '@0.4.26'
@@ -87,7 +88,7 @@ packages:
     - '@656aa3192b097a631ddd1e0380e80c26fd6644a7'
   edm4eic:
     require:
-    - '@6.0.1' # EDM4EIC_VERSION
+    - '@7.0.0' # EDM4EIC_VERSION
     - cxxstd=20
   edm4hep:
     require:
@@ -103,7 +104,8 @@ packages:
     - '@1.1.12'
   eicrecon:
     require:
-    - '@1.15.0' # EICRECON_VERSION
+    - '%clang'
+    - '@1.17.0' # EICRECON_VERSION
   eigen:
     require:
     - '@3.4.0'
@@ -127,6 +129,9 @@ packages:
     require:
     - '@9.1.0'
     - +shared cxxstd=17
+  freetype:
+    require:
+    - build_system=autotools
   gaudi:
     require:
     - '@38.1'
@@ -136,27 +141,31 @@ packages:
     - '@12.1'
     - -debuginfod
   g4ndl:
+    buildable: False
     externals:
-    - spec: g4ndl@4.7
+    - spec: g4ndl@4.7.1
       prefix: /opt/software/externals/g4ndl
   geant4:
     require:
-    - '@11.2.1.east'
+    - '@11.2.2.east'
     - cxxstd=20 -vecgeom +threads -vtk
     - any_of: [+opengl +qt +x11, -opengl -qt -x11]
-  glew:
+  gettext: 
+    require:
+    - +libxml2
+  gl:
     require:
-    - gl=glx
+    - glx
   gloo:
     require:
     - '@2023-05-19'
   graphviz:
     require:
-    - '@8.0.1'
+    - '@12.1.0'
     - +expat +pangocairo
   hepmc3:
     require:
-    - '@3.2.7'
+    - '@3.3.0'
     - +python +rootio
   heppdt:
     require:
@@ -175,11 +184,11 @@ packages:
     - '@0.20'
   jana2:
     require:
-    - '@2.2.1-rc1'
+    - '@2.3.1'
     - -ipo +podio +root +zmq
   juggler:
     require:
-    - '@14.0.3' # JUGGLER_VERSION
+    - '@14.2.0' # JUGGLER_VERSION
     - cxxstd=20
   k4actstracking:
     require:
@@ -251,6 +260,9 @@ packages:
     require:
     - '@3.0.2'
     - +plot
+  protobuf:
+    require:
+    - '@3.21.12'
   pythia8:
     require:
     - '@8.311'
@@ -272,7 +284,16 @@ packages:
     - '@2023.4.1'
   py-epic-capybara:
     require:
-    - '@git.c388cecce90d06f2db75e45bb0427816db04c836'
+    - '@git.c8d357028a96f72215bcba516000ea81db4842a6'
+  py-hepunits:
+    require:
+    - '@2.3.2'
+  py-hist:
+    require:
+    - '@2.6.1'
+  py-histoprint:
+    require:
+    - '@2.4.0'
   py-ipython:
     require:
     - '@8.11.0'
@@ -315,12 +336,18 @@ packages:
   py-pandas:
     require:
     - '@1.5.3'
+  py-particle:
+    require:
+    - '@0.23.0'
   py-pip:
     require:
     - any_of: ['@23.1.2', '@23.0']
   py-pre-commit:
     require:
     - '@3.3.3'
+  py-protobuf:
+    require:
+    - '@4.21.9'
   py-pygithub:
     require:
     - '@2.1.1'
@@ -346,21 +373,34 @@ packages:
   py-uproot:
     require:
     - '@5.0.5'
+  py-vector:
+    require:
+    - '@1.4.1'
   py-wurlitzer:
     require:
     - '@3.0.2'
   py-yapf:
     require:
     - '@0.30.0'
+  qmake:
+    require:
+    - qt-base
   qt:
     require:
     - '@5.15.12'
     - +opengl
+  qt-base:
+    require:
+    - '@6.7.2'
+    - +opengl
   root:
     require:
     - '@6.30.02'
     - cxxstd=20 +fftw +fortran +gdml +http -ipo +mlp +python +root7 +tmva +tmva-sofie +vc +xrootd +ssl
     - any_of: [+opengl +webgui +x, -opengl -webgui -x]
+  simsipm:
+    require:
+    - '@2.0.2'
   snakemake:
     require:
     - '@8.5.2'
@@ -379,7 +419,7 @@ packages:
     - '@3.20.0'
   xrootd:
     require:
-    - '@5.6.9'
+    - '@5.7.0'
     - cxxstd=20 -davix +python +scitokens-cpp
   zlib-api:
     require:
diff --git a/spack-environment/view.yaml b/spack-environment/view.yaml
index 889bfaea85873416af15d4c13e0a31b485e2d4a7..8cc72277fd1be758e151fcaf21ed6157c11c9862 100644
--- a/spack-environment/view.yaml
+++ b/spack-environment/view.yaml
@@ -1,11 +1,14 @@
   view:
     default:
       root: /opt/local
-      exclude: [epic]
+      exclude: 
+      - epic
+      - py-pip@23.0
       link_type: symlink
     detectors:
       root: /opt/detector
-      select: [epic]
+      select:
+      - epic
       projections:
         all: '{name}-{version}'
       link: roots
diff --git a/spack-environment/xl/spack.yaml b/spack-environment/xl/spack.yaml
index b3bfe260f06c65a808950f2ad183a440e1d2f505..60145849152ff052a3268fc6e58cb224ac8519e1 100644
--- a/spack-environment/xl/spack.yaml
+++ b/spack-environment/xl/spack.yaml
@@ -28,17 +28,17 @@ spack:
   - eigen
   - emacs
   - epic@main # EPIC_VERSION
-  - epic@24.04.0
-  - epic@24.05.0
-  - epic@24.05.2
   - epic@24.06.0
   - epic@24.07.0
+  - epic@24.08.0
+  - epic@24.08.1
+  - epic@24.09.0
   - fastjet
   - fjcontrib
   - fmt
   - gaudi
   - gdb
-  - geant4
+  - geant4 +opengl
   - graphviz
   - hepmc3
   - heppdt
@@ -68,6 +68,9 @@ spack:
   - py-dask
   - py-deepdiff
   - py-epic-capybara
+  - py-hepunits
+  - py-hist
+  - py-histoprint
   - py-ipython
   - py-jinja2
   - py-jinja2-cli
@@ -82,6 +85,7 @@ spack:
   - py-onnx
   - py-onnxruntime
   - py-pandas
+  - py-particle
   - py-pip
   - py-pre-commit
   - py-pycairo
@@ -91,9 +95,11 @@ spack:
   - py-toml
   - py-torch
   - py-uproot
+  - py-vector
   - py-wurlitzer
   - py-yapf
   - root +opengl +webgui +x
+  - simsipm
   - snakemake
   - spdlog
   - stow
diff --git a/spack.sh b/spack.sh
index d431e6f97c15ec1e02e7749e5713213d23a1089f..7f9b3117e5419312409fc391de88fd45fdebcfae 100644
--- a/spack.sh
+++ b/spack.sh
@@ -3,7 +3,7 @@ SPACK_ORGREPO="spack/spack"
 
 ## Spack github version, e.g. v0.18.1 or commit hash
 ## note: nightly builds will use e.g. releases/v0.19
-SPACK_VERSION="v0.22.0"
+SPACK_VERSION="v0.22.1"
 
 ## Space-separated list of spack cherry-picks
 read -r -d '' SPACK_CHERRYPICKS <<- \
@@ -11,11 +11,24 @@ read -r -d '' SPACK_CHERRYPICKS <<- \
 09f75ee426a2e05e0543570821582480ff823ba5
 f6d50f790ee8b123f7775429f6ca6394170e6de9
 63f6e6079aacc99078386e5c8ff06173841b9595
-9bcc43c4c158639fa6cb575c6106595a34682081
-9f3e45ddbee24aaa7993e575297827e0aed2e6fe
+092dc96e6c87a9c043e4421e1a524e23ec649f60
 85f13442d2a7486daba81fdd9a3b6a1182ba11f6
 f73d7d2dce226857cbc774e942454bad2992969e
 cbab451c1a342523ed75e9be1098615a597a9b59
+4fe5f35c2fff6288e4c05e5946798ad2191a2c40
+4c60deb9921ff2cbbfa6771f4f63ff812a8a5840
+b894acf1fca8eb5cc52d2267b0c4c187065998c0
+8b45fa089e24c6ab7de2eaf614977369e69daa54
+2d8ca8af6932dfd50204d1e4f6fe587dec7beef5
+d3bf1e04fca844abb7c1eeac38dda4e126c81b67
+81125c3bd80e71a2e57c7fcff8e02c4b3add5b90
+8b2fec61f23a7b8230c0ed0378d90d04d8f590d8
+2242da65fdc06e7ac04c43613dc7795164b3a7a3
+1dc63dbea6c1d42aabf0e14b51439dcc46423e79
+3b59817ea7be35f4222dc88313734f7a30733ad7
+737b70cbbfacb3fba8054426e9b5bf8ede6d8faf
+a66586d749197841bd74e289802126f2359287a8
+7503a417731910d918a7863d1862f62c9b76429d
 ---
 ## Optional hash table with comma-separated file list
 read -r -d '' SPACK_CHERRYPICKS_FILES <<- \
@@ -26,8 +39,21 @@ read -r -d '' SPACK_CHERRYPICKS_FILES <<- \
 ## 09f75ee426a2e05e0543570821582480ff823ba5: setup-env.sh: if exe contains qemu, use /proc/$$/comm instead
 ## f6d50f790ee8b123f7775429f6ca6394170e6de9: gaudi: Add version 38.1
 ## 63f6e6079aacc99078386e5c8ff06173841b9595: gaudi: upstream patch when @38.1 for missing #include <list>
-## 9bcc43c4c158639fa6cb575c6106595a34682081: protobuf: update hash for patch needed when="@3.4:3.21"
-## 9f3e45ddbee24aaa7993e575297827e0aed2e6fe: acts: pass cuda_arch to CMAKE_CUDA_ARCHITECTURES
+## 092dc96e6c87a9c043e4421e1a524e23ec649f60: acts: pass cuda_arch to CMAKE_CUDA_ARCHITECTURES
 ## 85f13442d2a7486daba81fdd9a3b6a1182ba11f6: Consolidate concretization output for environments
 ## f73d7d2dce226857cbc774e942454bad2992969e: dd4hep: cleanup recipe, remove deprecated versions and patches
 ## cbab451c1a342523ed75e9be1098615a597a9b59: dd4hep: Add version 1.29
+## 4fe5f35c2fff6288e4c05e5946798ad2191a2c40: xrootd: add v5.7.0
+## 4c60deb9921ff2cbbfa6771f4f63ff812a8a5840: xrootd: add github as secondary url to avoid SSL issues
+## b894acf1fca8eb5cc52d2267b0c4c187065998c0: geant4: add v11.2.2, incl g4ndl v4.7.1
+## 8b45fa089e24c6ab7de2eaf614977369e69daa54: geant4: support Qt5 and Qt6
+## 2d8ca8af6932dfd50204d1e4f6fe587dec7beef5: qt-*: add v6.7.1, v6.7.2
+## d3bf1e04fca844abb7c1eeac38dda4e126c81b67: py-vector: add through v1.4.1 (switch to hatchling)
+## 81125c3bd80e71a2e57c7fcff8e02c4b3add5b90: hepmc3: pass root variant cxxstd as HEPMC3_CXX_STANDARD
+## 8b2fec61f23a7b8230c0ed0378d90d04d8f590d8: hepmc3: add v3.3.0
+## 2242da65fdc06e7ac04c43613dc7795164b3a7a3: graphviz: add through v12.1.0
+## 1dc63dbea6c1d42aabf0e14b51439dcc46423e79: acts: add v34.1.0, v35.0.0 (identification, sycl variants changes)
+## 3b59817ea7be35f4222dc88313734f7a30733ad7: deal with TimeoutError from ssl.py
+## 737b70cbbfacb3fba8054426e9b5bf8ede6d8faf: Buildcache: remove deprecated --allow-root and preview subcommand
+## a66586d749197841bd74e289802126f2359287a8: spack buildcache push: best effort
+## 7503a417731910d918a7863d1862f62c9b76429d: cuda: add v12.4.1