Repository: kubernetes-sigs/kueue

Issue:
AFS: add unit tests for scheduling logic with AFS
**What would you like to be cleaned**:

Add unit tests for scheduling with AFS which includes entry penalties.

It could be a new test function like "TestScheduleForAFS", by analogy to "TestScheduleForTAS", because the main "TestSchedule" is already enormous. 

**Why is this needed**:

They were not added in the main PR: https://github.com/kubernetes-sigs/kueue/pull/6189

Unit tests are very useful for the ease of debugging. Unit tests are also much faster to run than integration tests, which already take 20min, so they allow to cover many corner cases almost cost free.

Discussion:
@mimowo: cc @PBundyra @IrvingMg @IrvingMg: /assign

Solution patch:
diff --git a/CHANGELOG/CHANGELOG-0.12.md b/CHANGELOG/CHANGELOG-0.12.md
index 0223d522f..c49a78540 100644
--- a/CHANGELOG/CHANGELOG-0.12.md
+++ b/CHANGELOG/CHANGELOG-0.12.md
@@ -1,3 +1,20 @@
+## v0.12.7
+
+Changes since `v0.12.6`:
+
+## Changes by Kind
+
+### Bug or Regression
+
+- Fix support for PodGroup integration used by external controllers, which determine the
+  the target LocalQueue and the group size only later. In that case the hash would not be
+  computed resulting in downstream issues for ProvisioningRequest.
+
+  Now such an external controller can indicate the control over the PodGroup by adding
+  the `kueue.x-k8s.io/pod-suspending-parent` annotation, and later patch the Pods by setting
+  other metadata, like the kueue.x-k8s.io/queue-name label to initiate scheduling of the PodGroup. (#6463, @pawloch00)
+- TAS: fix the bug that Kueue is crashing when PodSet has size 0, eg. no workers in LeaderWorkerSet instance. (#6524, @mimowo)
+
 ## v0.12.6
 
 Changes since `v0.12.5`:
diff --git a/CHANGELOG/CHANGELOG-0.13.md b/CHANGELOG/CHANGELOG-0.13.md
index cd9ddebbd..be8ff2ba5 100644
--- a/CHANGELOG/CHANGELOG-0.13.md
+++ b/CHANGELOG/CHANGELOG-0.13.md
@@ -1,3 +1,22 @@
+## V0.13.2
+
+Changes since `v0.13.1`:
+
+## Changes by Kind
+
+### Bug or Regression
+
+- ElasticJobs: Fix the bug that scheduling of the Pending workloads was not triggered on scale-down of the running
+  elastic Job which could result in admitting one or more of the queued workloads. (#6407, @ichekrygin)
+- Fix support for PodGroup integration used by external controllers, which determine the
+  the target LocalQueue and the group size only later. In that case the hash would not be
+  computed resulting in downstream issues for ProvisioningRequest.
+
+  Now such an external controller can indicate the control over the PodGroup by adding
+  the `kueue.x-k8s.io/pod-suspending-parent` annotation, and later patch the Pods by setting
+  other metadata, like the kueue.x-k8s.io/queue-name label to initiate scheduling of the PodGroup. (#6461, @pawloch00)
+- TAS: fix the bug that Kueue is crashing when PodSet has size 0, eg. no workers in LeaderWorkerSet instance. (#6522, @mimowo)
+
 ## v0.13.1
 
 Changes since `v0.13.0`:
diff --git a/Makefile b/Makefile
index f7adba6e4..89d7c13d3 100644
--- a/Makefile
+++ b/Makefile
@@ -85,7 +85,7 @@ LD_FLAGS += -X '$(version_pkg).BuildDate=$(shell date -u +%Y-%m-%dT%H:%M:%SZ)'
 
 # Update these variables when preparing a new release or a release branch.
 # Then run `make prepare-release-branch`
-RELEASE_VERSION=v0.13.1
+RELEASE_VERSION=v0.13.2
 RELEASE_BRANCH=main
 # Application version for Helm and npm (strips leading 'v' from RELEASE_VERSION)
 APP_VERSION := $(shell echo $(RELEASE_VERSION) | cut -c2-)
diff --git a/README.md b/README.md
index 135b46de7..1616864f3 100644
--- a/README.md
+++ b/README.md
@@ -62,7 +62,7 @@ Read the [overview](https://kueue.sigs.k8s.io/docs/overview/) and watch the Kueu
 To install the latest release of Kueue in your cluster, run the following command:
 
 ```shell
-kubectl apply --server-side -f https://github.com/kubernetes-sigs/kueue/releases/download/v0.13.1/manifests.yaml
+kubectl apply --server-side -f https://github.com/kubernetes-sigs/kueue/releases/download/v0.13.2/manifests.yaml
 ```
 
 The controller runs in the `kueue-system` namespace.
diff --git a/SECURITY-INSIGHTS.yaml b/SECURITY-INSIGHTS.yaml
index af713e4fe..94a084b99 100644
--- a/SECURITY-INSIGHTS.yaml
+++ b/SECURITY-INSIGHTS.yaml
@@ -1,11 +1,11 @@
 header:
   schema-version: 1.0.0
   expiration-date: '2024-09-28T01:00:00.000Z'
-  last-updated: '2025-08-01'
-  last-reviewed: '2025-08-01'
-  commit-hash: "81236abed536034d41156c5af20d614590f82935"
+  last-updated: '2025-08-11'
+  last-reviewed: '2025-08-11'
+  commit-hash: "2fb89c587565f18284775f0849f030c41b8a6980"
   project-url: 'https://github.com/kubernetes-sigs/kueue'
-  project-release: "0.13.1"
+  project-release: "0.13.2"
   changelog: 'https://github.com/kubernetes-sigs/kueue/tree/main/CHANGELOG'
   license: 'https://github.com/kubernetes-sigs/kueue/blob/main/LICENSE'
 project-lifecycle:
@@ -28,7 +28,7 @@ documentation:
   - 'https://kueue.sigs.k8s.io/docs/'
 distribution-points:
   - >-
-    https://github.com/kubernetes-sigs/kueue/releases/download/v0.13.1/manifests.yaml
+    https://github.com/kubernetes-sigs/kueue/releases/download/v0.13.2/manifests.yaml
 security-artifacts:
   threat-model:
     threat-model-created: false
@@ -62,5 +62,5 @@ dependencies:
   dependencies-lists:
     - 'https://github.com/kubernetes-sigs/kueue/blob/main/go.mod'
   sbom:
-    - sbom-file: https://github.com/kubernetes-sigs/kueue/releases/download/v0.13.1/kueue-v0.13.1.spdx.json
+    - sbom-file: https://github.com/kubernetes-sigs/kueue/releases/download/v0.13.2/kueue-v0.13.2.spdx.json
       sbom-format: SPDX
diff --git a/charts/kueue/Chart.yaml b/charts/kueue/Chart.yaml
index eb114896e..58bc89a9f 100644
--- a/charts/kueue/Chart.yaml
+++ b/charts/kueue/Chart.yaml
@@ -16,9 +16,9 @@ type: application
 # NOTE: Do not modify manually. In Kueue, the version and appVersion are
 # overridden to GIT_TAG when building the artifacts, including the helm charts,
 # via Makefile.
-version: 0.13.1
+version: 0.13.2
 # This is the version number of the application being deployed. This version number should be
 # incremented each time you make changes to the application. Versions are not expected to
 # follow Semantic Versioning. They should reflect the version the application is using.
 # It is recommended to use it with quotes.
-appVersion: "v0.13.1"
+appVersion: "v0.13.2"
diff --git a/charts/kueue/README.md b/charts/kueue/README.md
index 61ae67288..fd99de5e3 100644
--- a/charts/kueue/README.md
+++ b/charts/kueue/README.md
@@ -1,6 +1,6 @@
 # kueue
 
-![Version: 0.13.1](https://img.shields.io/badge/Version-0.13.1-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v0.13.1](https://img.shields.io/badge/AppVersion-v0.13.1-informational?style=flat-square)
+![Version: 0.13.2](https://img.shields.io/badge/Version-0.13.2-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v0.13.2](https://img.shields.io/badge/AppVersion-v0.13.2-informational?style=flat-square)
 
 Kueue is a set of APIs and controller for job queueing. It is a job-level manager that decides when a job should be admitted to start (as in pods can be created) and when it should stop (as in active pods should be deleted).
 
@@ -28,7 +28,7 @@ $ helm install kueue kueue/ --create-namespace --namespace kueue-system
 Or use the charts pushed to `oci://registry.k8s.io/kueue/charts/kueue`:
 
 ```bash
-helm install kueue oci://registry.k8s.io/kueue/charts/kueue --version="0.13.1" --create-namespace --namespace=kueue-system
+helm install kueue oci://registry.k8s.io/kueue/charts/kueue --version="0.13.2" --create-namespace --namespace=kueue-system
 ```
 
 For more advanced parametrization of Kueue, we recommend using a local overrides file, passed via the `--values` flag. For example:
@@ -50,7 +50,7 @@ controllerManager:
 ```
 
 ```bash
-helm install kueue oci://registry.k8s.io/kueue/charts/kueue --version="0.13.1" \
+helm install kueue oci://registry.k8s.io/kueue/charts/kueue --version="0.13.2" \
   --create-namespace --namespace=kueue-system \
   --values overrides.yaml
 ```
@@ -58,7 +58,7 @@ helm install kueue oci://registry.k8s.io/kueue/charts/kueue --version="0.13.1" \
 You can also use the `--set` flag. For example, to enable a feature gate (e.g., `TopologyAwareScheduling`):
 
 ```bash
-helm install kueue oci://registry.k8s.io/kueue/charts/kueue --version="0.13.1" \
+helm install kueue oci://registry.k8s.io/kueue/charts/kueue --version="0.13.2" \
   --create-namespace --namespace=kueue-system \
   --set "controllerManager.featureGates[0].name=TopologyAwareScheduling" \
   --set "controllerManager.featureGates[0].enabled=true"
diff --git a/charts/kueue/README.md.gotmpl b/charts/kueue/README.md.gotmpl
index 55393cae1..53f012a68 100644
--- a/charts/kueue/README.md.gotmpl
+++ b/charts/kueue/README.md.gotmpl
@@ -30,7 +30,7 @@ $ helm install kueue kueue/ --create-namespace --namespace kueue-system
 Or use the charts pushed to `oci://registry.k8s.io/kueue/charts/kueue`:
 
 ```bash
-helm install kueue oci://registry.k8s.io/kueue/charts/kueue --version="0.13.1" --create-namespace --namespace=kueue-system
+helm install kueue oci://registry.k8s.io/kueue/charts/kueue --version="0.13.2" --create-namespace --namespace=kueue-system
 ```
 
 For more advanced parametrization of Kueue, we recommend using a local overrides file, passed via the `--values` flag. For example:
@@ -52,7 +52,7 @@ controllerManager:
 ```
 
 ```bash
-helm install kueue oci://registry.k8s.io/kueue/charts/kueue --version="0.13.1" \
+helm install kueue oci://registry.k8s.io/kueue/charts/kueue --version="0.13.2" \
   --create-namespace --namespace=kueue-system \
   --values overrides.yaml
 ```
@@ -60,7 +60,7 @@ helm install kueue oci://registry.k8s.io/kueue/charts/kueue --version="0.13.1" \
 You can also use the `--set` flag. For example, to enable a feature gate (e.g., `TopologyAwareScheduling`):
 
 ```bash
-helm install kueue oci://registry.k8s.io/kueue/charts/kueue --version="0.13.1" \
+helm install kueue oci://registry.k8s.io/kueue/charts/kueue --version="0.13.2" \
   --create-namespace --namespace=kueue-system \
   --set "controllerManager.featureGates[0].name=TopologyAwareScheduling" \
   --set "controllerManager.featureGates[0].enabled=true"
diff --git a/cmd/kueue/main.go b/cmd/kueue/main.go
index 9ace605f4..657f17a5d 100644
--- a/cmd/kueue/main.go
+++ b/cmd/kueue/main.go
@@ -289,12 +289,10 @@ func setupIndexes(ctx context.Context, mgr ctrl.Manager, cfg *configapi.Configur
 	}
 
 	// setup provision admission check controller indexes
-	if features.Enabled(features.ProvisioningACC) {
-		if err := provisioning.ServerSupportsProvisioningRequest(mgr); err != nil {
-			setupLog.Error(err, "Skipping admission check controller setup: Provisioning Requests not supported (Possible cause: missing or unsupported cluster-autoscaler)")
-		} else if err := provisioning.SetupIndexer(ctx, mgr.GetFieldIndexer()); err != nil {
-			return fmt.Errorf("could not setup provisioning indexer: %w", err)
-		}
+	if err := provisioning.ServerSupportsProvisioningRequest(mgr); err != nil {
+		setupLog.Error(err, "Skipping admission check controller setup: Provisioning Requests not supported (Possible cause: missing or unsupported cluster-autoscaler)")
+	} else if err := provisioning.SetupIndexer(ctx, mgr.GetFieldIndexer()); err != nil {
+		return fmt.Errorf("could not setup provisioning indexer: %w", err)
 	}
 
 	if features.Enabled(features.TopologyAwareScheduling) {
@@ -325,18 +323,16 @@ func setupControllers(ctx context.Context, mgr ctrl.Manager, cCache *cache.Cache
 	}
 
 	// setup provision admission check controller
-	if features.Enabled(features.ProvisioningACC) {
-		if err := provisioning.ServerSupportsProvisioningRequest(mgr); err != nil {
-			setupLog.Info("Skipping provisioning controller setup: Provisioning Requests not supported (Possible cause: missing or unsupported cluster-autoscaler)")
-		} else {
-			ctrl, err := provisioning.NewController(mgr.GetClient(), mgr.GetEventRecorderFor("kueue-provisioning-request-controller"))
-			if err != nil {
-				return fmt.Errorf("could not create the provisioning controller: %w", err)
-			}
+	if err := provisioning.ServerSupportsProvisioningRequest(mgr); err != nil {
+		setupLog.Info("Skipping provisioning controller setup: Provisioning Requests not supported (Possible cause: missing or unsupported cluster-autoscaler)")
+	} else {
+		ctrl, err := provisioning.NewController(mgr.GetClient(), mgr.GetEventRecorderFor("kueue-provisioning-request-controller"))
+		if err != nil {
+			return fmt.Errorf("could not create the provisioning controller: %w", err)
+		}
 
-			if err := ctrl.SetupWithManager(mgr); err != nil {
-				return fmt.Errorf("could not setup provisioning controller: %w", err)
-			}
+		if err := ctrl.SetupWithManager(mgr); err != nil {
+			return fmt.Errorf("could not setup provisioning controller: %w", err)
 		}
 	}
 
diff --git a/cmd/kueueviz/INSTALL.md b/cmd/kueueviz/INSTALL.md
index 51052f83b..1c41c6076 100644
--- a/cmd/kueueviz/INSTALL.md
+++ b/cmd/kueueviz/INSTALL.md
@@ -3,7 +3,7 @@
 KueueViz can be installed using `kubectl` with the following command:
 
 ```
-kubectl create -f https://github.com/kubernetes-sigs/kueue/releases/download/v0.13.1/kueueviz.yaml
+kubectl create -f https://github.com/kubernetes-sigs/kueue/releases/download/v0.13.2/kueueviz.yaml
 ```
 If you are using `kind` and that you don't have an `ingress` controller, you can use `port-forward` to 
 configure and run `KueueViz`:
@@ -23,7 +23,7 @@ by ensuring that `enableKueueViz` is set to `true`:
 
 ```
 helm upgrade --install kueue oci://registry.k8s.io/kueue/charts/kueue \
-  --version="0.13.1"
+  --version="0.13.2"
   --namespace kueue-system \
   --set enableKueueViz=true \
   --create-namespace
@@ -44,7 +44,7 @@ kind create cluster
 kind get kubeconfig > kubeconfig
 export KUBECONFIG=$PWD/kubeconfig
 helm install kueue oci://us-central1-docker.pkg.dev/k8s-staging-images/charts/kueue \
-            --version="0.13.1" --create-namespace --namespace=kueue-system
+            --version="0.13.2" --create-namespace --namespace=kueue-system
 ```
 
 ## Build
diff --git a/cmd/kueueviz/frontend/package-lock.json b/cmd/kueueviz/frontend/package-lock.json
index 68ea09b0b..6e1ab3a17 100644
--- a/cmd/kueueviz/frontend/package-lock.json
+++ b/cmd/kueueviz/frontend/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "kueueviz-frontend",
-  "version": "0.13.1",
+  "version": "0.13.2",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
       "name": "kueueviz-frontend",
-      "version": "0.13.1",
+      "version": "0.13.2",
       "license": "Apache 2.0",
       "dependencies": {
         "@emotion/react": "^11.14.0",
@@ -17,13 +17,13 @@
         "react": "^19.1.1",
         "react-ace": "^14.0.1",
         "react-dom": "^19.1.1",
-        "react-router-dom": "^7.7.1",
+        "react-router-dom": "^7.8.0",
         "react-toastify": "^11.0.5"
       },
       "devDependencies": {
-        "@vitejs/plugin-react": "^4.7.0",
+        "@vitejs/plugin-react": "^5.0.0",
         "depcheck": "^1.4.7",
-        "vite": "^7.0.6"
+        "vite": "^7.1.1"
       }
     },
     "node_modules/@ampproject/remapping": {
@@ -1163,9 +1163,9 @@
       }
     },
     "node_modules/@rolldown/pluginutils": {
-      "version": "1.0.0-beta.27",
-      "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz",
-      "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==",
+      "version": "1.0.0-beta.30",
+      "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.30.tgz",
+      "integrity": "sha512-whXaSoNUFiyDAjkUF8OBpOm77Szdbk5lGNqFe6CbVbJFrhCCPinCbRA3NjawwlNHla1No7xvXXh+CpSxnPfUEw==",
       "dev": true,
       "license": "MIT"
     },
@@ -1551,21 +1551,21 @@
       }
     },
     "node_modules/@vitejs/plugin-react": {
-      "version": "4.7.0",
-      "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz",
-      "integrity": "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==",
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.0.0.tgz",
+      "integrity": "sha512-Jx9JfsTa05bYkS9xo0hkofp2dCmp1blrKjw9JONs5BTHOvJCgLbaPSuZLGSVJW6u2qe0tc4eevY0+gSNNi0YCw==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
         "@babel/core": "^7.28.0",
         "@babel/plugin-transform-react-jsx-self": "^7.27.1",
         "@babel/plugin-transform-react-jsx-source": "^7.27.1",
-        "@rolldown/pluginutils": "1.0.0-beta.27",
+        "@rolldown/pluginutils": "1.0.0-beta.30",
         "@types/babel__core": "^7.20.5",
         "react-refresh": "^0.17.0"
       },
       "engines": {
-        "node": "^14.18.0 || >=16.0.0"
+        "node": "^20.19.0 || >=22.12.0"
       },
       "peerDependencies": {
         "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
@@ -2857,9 +2857,9 @@
       }
     },
     "node_modules/react-router": {
-      "version": "7.7.1",
-      "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.7.1.tgz",
-      "integrity": "sha512-jVKHXoWRIsD/qS6lvGveckwb862EekvapdHJN/cGmzw40KnJH5gg53ujOJ4qX6EKIK9LSBfFed/xiQ5yeXNrUA==",
+      "version": "7.8.0",
+      "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.8.0.tgz",
+      "integrity": "sha512-r15M3+LHKgM4SOapNmsH3smAizWds1vJ0Z9C4mWaKnT9/wD7+d/0jYcj6LmOvonkrO4Rgdyp4KQ/29gWN2i1eg==",
       "license": "MIT",
       "dependencies": {
         "cookie": "^1.0.1",
@@ -2879,12 +2879,12 @@
       }
     },
     "node_modules/react-router-dom": {
-      "version": "7.7.1",
-      "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.7.1.tgz",
-      "integrity": "sha512-bavdk2BA5r3MYalGKZ01u8PGuDBloQmzpBZVhDLrOOv1N943Wq6dcM9GhB3x8b7AbqPMEezauv4PeGkAJfy7FQ==",
+      "version": "7.8.0",
+      "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.8.0.tgz",
+      "integrity": "sha512-ntInsnDVnVRdtSu6ODmTQ41cbluak/ENeTif7GBce0L6eztFg6/e1hXAysFQI8X25C8ipKmT9cClbJwxx3Kaqw==",
       "license": "MIT",
       "dependencies": {
-        "react-router": "7.7.1"
+        "react-router": "7.8.0"
       },
       "engines": {
         "node": ">=20.0.0"
@@ -3236,9 +3236,9 @@
       }
     },
     "node_modules/vite": {
-      "version": "7.0.6",
-      "resolved": "https://registry.npmjs.org/vite/-/vite-7.0.6.tgz",
-      "integrity": "sha512-MHFiOENNBd+Bd9uvc8GEsIzdkn1JxMmEeYX35tI3fv0sJBUTfW5tQsoaOwuY4KhBI09A3dUJ/DXf2yxPVPUceg==",
+      "version": "7.1.1",
+      "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.1.tgz",
+      "integrity": "sha512-yJ+Mp7OyV+4S+afWo+QyoL9jFWD11QFH0i5i7JypnfTcA1rmgxCbiA8WwAICDEtZ1Z1hzrVhN8R8rGTqkTY8ZQ==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -3246,7 +3246,7 @@
         "fdir": "^6.4.6",
         "picomatch": "^4.0.3",
         "postcss": "^8.5.6",
-        "rollup": "^4.40.0",
+        "rollup": "^4.43.0",
         "tinyglobby": "^0.2.14"
       },
       "bin": {
diff --git a/cmd/kueueviz/frontend/package.json b/cmd/kueueviz/frontend/package.json
index 723341e3e..927dbbe74 100644
--- a/cmd/kueueviz/frontend/package.json
+++ b/cmd/kueueviz/frontend/package.json
@@ -1,6 +1,6 @@
 {
   "name": "kueueviz-frontend",
-  "version": "0.13.1",
+  "version": "0.13.2",
   "private": true,
   "description": "Frontend dashboard for visualizing Kueue status",
   "main": "src/index.jsx",
@@ -21,13 +21,13 @@
     "react": "^19.1.1",
     "react-ace": "^14.0.1",
     "react-dom": "^19.1.1",
-    "react-router-dom": "^7.7.1",
+    "react-router-dom": "^7.8.0",
     "react-toastify": "^11.0.5"
   },
   "devDependencies": {
-    "@vitejs/plugin-react": "^4.7.0",
+    "@vitejs/plugin-react": "^5.0.0",
     "depcheck": "^1.4.7",
-    "vite": "^7.0.6"
+    "vite": "^7.1.1"
   },
   "browserslist": {
     "production": [
diff --git a/go.mod b/go.mod
index 0e693ca93..145050fb7 100644
--- a/go.mod
+++ b/go.mod
@@ -37,7 +37,7 @@ require (
 	k8s.io/utils v0.0.0-20250604170112-4c0f3b243397
 	sigs.k8s.io/controller-runtime v0.21.0
 	sigs.k8s.io/jobset v0.8.2
-	sigs.k8s.io/lws v0.6.2
+	sigs.k8s.io/lws v0.7.0
 	sigs.k8s.io/structured-merge-diff/v4 v4.7.0
 	sigs.k8s.io/yaml v1.6.0
 )
@@ -140,7 +140,7 @@ require (
 	gopkg.in/inf.v0 v0.9.1 // indirect
 	gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
-	k8s.io/apiextensions-apiserver v0.33.1 // indirect
+	k8s.io/apiextensions-apiserver v0.33.3 // indirect
 	k8s.io/code-generator v0.33.3 // indirect
 	k8s.io/gengo/v2 v2.0.0-20250604051438-85fd79dbfd9f // indirect
 	k8s.io/kms v0.33.3 // indirect
diff --git a/go.sum b/go.sum
index 9781a71a0..31ccadbb8 100644
--- a/go.sum
+++ b/go.sum
@@ -349,8 +349,8 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 k8s.io/api v0.33.3 h1:SRd5t//hhkI1buzxb288fy2xvjubstenEKL9K51KBI8=
 k8s.io/api v0.33.3/go.mod h1:01Y/iLUjNBM3TAvypct7DIj0M0NIZc+PzAHCIo0CYGE=
-k8s.io/apiextensions-apiserver v0.33.1 h1:N7ccbSlRN6I2QBcXevB73PixX2dQNIW0ZRuguEE91zI=
-k8s.io/apiextensions-apiserver v0.33.1/go.mod h1:uNQ52z1A1Gu75QSa+pFK5bcXc4hq7lpOXbweZgi4dqA=
+k8s.io/apiextensions-apiserver v0.33.3 h1:qmOcAHN6DjfD0v9kxL5udB27SRP6SG/MTopmge3MwEs=
+k8s.io/apiextensions-apiserver v0.33.3/go.mod h1:oROuctgo27mUsyp9+Obahos6CWcMISSAPzQ77CAQGz8=
 k8s.io/apimachinery v0.33.3 h1:4ZSrmNa0c/ZpZJhAgRdcsFcZOw1PQU1bALVQ0B3I5LA=
 k8s.io/apimachinery v0.33.3/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
 k8s.io/apiserver v0.33.3 h1:Wv0hGc+QFdMJB4ZSiHrCgN3zL3QRatu56+rpccKC3J4=
@@ -397,8 +397,8 @@ sigs.k8s.io/kustomize/api v0.19.0 h1:F+2HB2mU1MSiR9Hp1NEgoU2q9ItNOaBJl0I4Dlus5SQ
 sigs.k8s.io/kustomize/api v0.19.0/go.mod h1:/BbwnivGVcBh1r+8m3tH1VNxJmHSk1PzP5fkP6lbL1o=
 sigs.k8s.io/kustomize/kyaml v0.19.0 h1:RFge5qsO1uHhwJsu3ipV7RNolC7Uozc0jUBC/61XSlA=
 sigs.k8s.io/kustomize/kyaml v0.19.0/go.mod h1:FeKD5jEOH+FbZPpqUghBP8mrLjJ3+zD3/rf9NNu1cwY=
-sigs.k8s.io/lws v0.6.2 h1:5ulPJDaLBI9zk6ayGO2Lfg9P/FBL3C1LsmHmJVqvHvo=
-sigs.k8s.io/lws v0.6.2/go.mod h1:7nbwcpHwdDticuWPTDe6Va5OpjasS0MoVeVD61N5Y0c=
+sigs.k8s.io/lws v0.7.0 h1:qWfzX8+UBak+Hq0+m/PuE3uO0mp/3dmm5q/h/7z31A8=
+sigs.k8s.io/lws v0.7.0/go.mod h1:WLg0CkyJTRQWMUOUam6qi9qRmcj3LAIWQUT81d4BGr4=
 sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
 sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
 sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
diff --git a/keps/1136-provisioning-request-support/README.md b/keps/1136-provisioning-request-support/README.md
index a68253daa..9c762bff7 100644
--- a/keps/1136-provisioning-request-support/README.md
+++ b/keps/1136-provisioning-request-support/README.md
@@ -325,11 +325,14 @@ The following scenarios should be tested:
 
 ### Graduation Criteria
 
-User feedback is positive.
+* `ProvisioningRequest` is using V1 APIs
+* `ProvisioningRequest` deprecated annotations are dropped by code.
+* `ProvisioningRequest` is beta without known issues.
 
 ## Implementation History
 
 2023-09-21: KEP
+2025-08-07: Promoted to GA.
 
 ## Alternatives
 
diff --git a/keps/1136-provisioning-request-support/kep.yaml b/keps/1136-provisioning-request-support/kep.yaml
index c37a217c3..f1f81b71f 100644
--- a/keps/1136-provisioning-request-support/kep.yaml
+++ b/keps/1136-provisioning-request-support/kep.yaml
@@ -3,25 +3,28 @@ kep-number: 1136
 authors:
   - "@mwielgus"
   - "@pbundyra"
-status: draft
+status: implemented
 creation-date: 2023-09-20
 reviewers:
   - "@kerthcet"
   - "@alculquicondor"
+  - "@PBundyra"
 approvers:
   - "@alculquicondor"
+  - "@mimowo"
 
 # The target maturity stage in the current dev cycle for this KEP.
-stage: beta
+stage: stable
 
 # The most recent milestone for which work toward delivery of this KEP has been
 # done. This can be the current (upcoming) milestone, if it is being actively
 # worked on.
-latest-milestone: "v0.5"
+latest-milestone: "v0.14"
 
 # The milestone at which this feature was, or is targeted to be, at each stage.
 milestone:
   beta: "v0.5"
+  stable: "v0.14"
 
 feature-gates:
   - KeepQuotaForProvReqRetry
diff --git a/pkg/features/kube_features.go b/pkg/features/kube_features.go
index da25573d6..99e3db500 100644
--- a/pkg/features/kube_features.go
+++ b/pkg/features/kube_features.go
@@ -213,6 +213,7 @@ var defaultVersionedFeatureGates = map[featuregate.Feature]featuregate.Versioned
 	},
 	ProvisioningACC: {
 		{Version: version.MustParse("0.5"), Default: true, PreRelease: featuregate.Beta},
+		{Version: version.MustParse("0.14"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 0.15
 	},
 	VisibilityOnDemand: {
 		{Version: version.MustParse("0.6"), Default: false, PreRelease: featuregate.Alpha},
diff --git a/pkg/workloadslicing/workloadslicing.go b/pkg/workloadslicing/workloadslicing.go
index e91094197..9e61cd502 100644
--- a/pkg/workloadslicing/workloadslicing.go
+++ b/pkg/workloadslicing/workloadslicing.go
@@ -28,7 +28,6 @@ import (
 	apimeta "k8s.io/apimachinery/pkg/api/meta"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime/schema"
-	"k8s.io/apiserver/pkg/storage"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 
 	kueue "sigs.k8s.io/kueue/apis/kueue/v1beta1"
@@ -112,21 +111,6 @@ func Finish(ctx context.Context, clnt client.Client, workloadSlice *kueue.Worklo
 	return nil
 }
 
-// versionHelper is used in the FindNotFinishedWorkloads sort routine as a tiebreaker
-// for workloads with identical creationTimestamp values.
-//
-// Note: Kubernetes documentation explicitly states:
-//
-//	"Clients must not assume that resource versions are numeric or collatable."
-//
-// To comply with this guidance, we rely on the Kubernetes apiserver/storage library
-// (storage.APIObjectVersioner) to perform resourceVersion comparisons.
-//
-// This ensures that if Kubernetes changes its internal resourceVersion format or semantics,
-// the helper will either be updated accordingly or removed entirely, in which case,
-// such changes will surface at compile time, prompting this code to be updated as needed.
-var versionHelper = storage.APIObjectVersioner{}
-
 // FindNotFinishedWorkloads returns a sorted list of workloads "owned by" the provided job object/gvk combination and
 // without "Finished" condition with status = "True".
 func FindNotFinishedWorkloads(ctx context.Context, clnt client.Client, jobObject client.Object, jobObjectGVK schema.GroupVersionKind) ([]kueue.Workload, error) {
@@ -137,14 +121,14 @@ func FindNotFinishedWorkloads(ctx context.Context, clnt client.Client, jobObject
 
 	// Sort workloads by creation timestamp, oldest first.
 	// In the rare case that two workload slices have identical creationTimestamp values
-	// (due to RFC3339 second-level precision), fall back to resourceVersion comparison
+	// (due to RFC3339 second-level precision), use WorkloadSliceReplacementFor
 	// as a tiebreaker. This edge case is uncommon in production but can occur in
 	// integration or e2e tests where the original and scaled-up workloads are created
 	// in rapid succession.
 	sort.Slice(list.Items, func(i, j int) bool {
 		a, b := list.Items[i], list.Items[j]
 		if a.CreationTimestamp.Equal(&b.CreationTimestamp) {
-			return versionHelper.CompareResourceVersion(&a, &b) < 0
+			return b.Annotations[WorkloadSliceReplacementFor] == string(workload.Key(&a))
 		}
 		return a.CreationTimestamp.Before(&b.CreationTimestamp)
 	})
@@ -217,12 +201,12 @@ func EnsureWorkloadSlices(ctx context.Context, clnt client.Client, jobPodSets []
 		// This transient state typically occurs when a new slice has been created,
 		// and the old slice is pending deactivation. The system should resolve this
 		// by deactivating the old slice, after which processing will continue under "case #1".
-
-		// There is also an edge-case when the old slice was preempted/evicted by the scheduler
-		// to make the room for other (than new slice) workload, which would result in two
-		// "pending" workloads. In such case - it is safe to deactivate the old slice.
 		oldWorkload := workloads[0]
-		if !workload.HasQuotaReservation(&oldWorkload) {
+
+		// Finish the old workload slice if it lost its quota reservation or if it was
+		// explicitly evicted.
+		if evictedCondition := apimeta.FindStatusCondition(oldWorkload.Status.Conditions, kueue.WorkloadEvicted); !workload.HasQuotaReservation(&oldWorkload) || evictedCondition != nil {
+			// Finish the old workload slice as out of sync.
 			if err := Finish(ctx, clnt, &oldWorkload, kueue.WorkloadFinishedReasonOutOfSync, "The workload slice is out of sync with its parent job"); err != nil {
 				return nil, true, err
 			}
diff --git a/site/content/en/docs/admission-check-controllers/provisioning.md b/site/content/en/docs/admission-check-controllers/provisioning.md
index a5aa214d7..5b41ad35a 100644
--- a/site/content/en/docs/admission-check-controllers/provisioning.md
+++ b/site/content/en/docs/admission-check-controllers/provisioning.md
@@ -8,7 +8,7 @@ description: >
 
 The Provisioning AdmissionCheck Controller is an AdmissionCheck Controller designed to integrate Kueue with [Kubernetes cluster-autoscaler](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler). Its primary function is to create [ProvisioningRequests](https://github.com/kubernetes/autoscaler/blob/4872bddce2bcc5b4a5f6a3d569111c11b8a2baf4/cluster-autoscaler/provisioningrequest/apis/autoscaling.x-k8s.io/v1beta1/types.go#L41) for the workloads holding [Quota Reservation](/docs/concepts/#quota-reservation) and keeping the [AdmissionCheckState](/docs/concepts/admission_check/#admissioncheckstate) in sync.
 
-The controller is part of Kueue. It is enabled by default. You can disable it by editing the `ProvisioningACC` feature gate. Check the [Installation](/docs/installation/#change-the-feature-gates-configuration) guide for details on feature gate configuration.
+The controller is part of Kueue and is enabled by default. The feature is now Generally Available (GA) as of Kueue v0.14.
 
 Check the list of supported Provisioning Classes and prerequisite for them in [ClusterAutoscaler documentation](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/FAQ.md#supported-provisioningclasses).
 
diff --git a/site/content/en/docs/concepts/_index.md b/site/content/en/docs/concepts/_index.md
index 8c12d7483..644ca239b 100644
--- a/site/content/en/docs/concepts/_index.md
+++ b/site/content/en/docs/concepts/_index.md
@@ -89,4 +89,9 @@ resources that are now required by the owning ClusterQueue.
 
 ### [Fair Sharing](/docs/concepts/fair_sharing)
 
-Mechanisms in Kueue to share quota between tenants fairly.
\ No newline at end of file
+Mechanisms in Kueue to share quota between tenants fairly.
+
+### [Elastic Workloads](/docs/concepts/elastic_workload)
+
+Workload types that support dynamic scaling.
+
diff --git a/site/content/en/docs/concepts/elastic_workload.md b/site/content/en/docs/concepts/elastic_workload.md
new file mode 100644
index 000000000..9bffc0ff9
--- /dev/null
+++ b/site/content/en/docs/concepts/elastic_workload.md
@@ -0,0 +1,76 @@
+---
+title: "Elastic Workloads"
+date: 2025-04-16
+weight: 4
+description: >
+  Workload types that support dynamic scaling.
+---
+
+{{< feature-state state="alpha" for_version="v0.13" >}}
+
+## Elastic Workloads (Workload Slices)
+
+Elastic Workloads extend the core `Workload` abstraction in Kueue to support **dynamic scaling** of admitted jobs, without requiring suspension or requeueing.
+This is achieved through the use of **Workload Slices**, which track partial allocations of a parent job's scale-up and scale-down operations.
+
+This feature enables more responsive and efficient scheduling for jobs that can adapt to changing cluster capacity, particularly in environments with fluctuating workloads or constrained resources.
+
+## Dynamic Scaling
+
+Traditionally, a `Workload` in Kueue represents a single atomic unit of admission.
+Once admitted, it reflects a fixed set of pod replicas and consumes a defined amount of quota. If a job needs to scale up or down, the `Workload` must be suspended, removed, or replaced entirely.
+
+While scaling **down** a workload is relatively straightforward and does not require additional capacity or a new workload slice, scaling **up** is more involved. It requires *additional capacity* that must be explicitly requested and *admitted* by Kueue through a new `Workload Slice`.
+
+**Note:** While scaling **down** is conceptually similar to [Dynamic Reclaim](https://kueue.sigs.k8s.io/docs/concepts/workload/#dynamic-reclaim), it is an orthogonal concept, it neither intersects with nor depends on Dynamic Reclaim functionality.
+
+## Use Cases
+
+* Dynamically adjusting throughput for [embarrassingly parallel](https://en.wikipedia.org/wiki/Embarrassingly_parallel) jobs.
+* Using AI/ML frameworks which support elasticity (Distributed Torch Elastic).
+
+## Lifecycle
+
+1. **Initial Admission**: A job is submitted and its first `Workload` is created and admitted.
+2. **Scaling Up**: If the job requests more parallelism, a new slice is created with the **increased** replicas count. Once admitted, the new slice replaces the original workload by marking the old one as `Finished`.
+3. **Scaling Down**: If the job reduces its parallelism, the updated pod count is recorded directly into the existing workload.
+4. **Preemption**: Follows the existing workload preemption mechanism.
+5. **Completion**: Follows the existing workload completion behavior.
+
+## Example
+
+{{< include "examples/jobs/sample-scalable-job.yaml" "yaml" >}}
+
+The example above will result in an admitted workload and 3 running pods.
+The parallelism can be adjusted (increased or decreased) as long as the job remains in an "Active" state (i.e., not yet completed).
+
+## Feature Gate
+
+Elastic Workloads via Workload Slices are gated by the following feature flag:
+
+```yaml
+ElasticJobsViaWorkloadSlices: true
+```
+
+Additionally, Elastic Job behavior must be explicitly enabled on a per-job basis via annotation:
+
+```yaml
+metadata:
+  annotations:
+    kueue.x-k8s.io/elastic-job: "true"
+```
+
+## Limitations
+
+* Currently available only for `batch/v1.Job` workloads.
+* Elastic workloads are not supported for jobs with partial admission enabled.
+
+    * Attempting to scale jobs with partial admission enabled will result in an admission validation error similar to the following:
+
+      ```text
+      Error from server (Forbidden): error when applying patch:
+      error when patching "job.yaml": admission webhook "vjob.kb.io" denied the request: spec.parallelism: Forbidden: cannot change when partial admission is enabled and the job is not suspended
+      ```
+* When scaling up a previously admitted job the new workload must reuse the originally assigned flavor, even if other eligible flavors have available capacity.
+* No Multikueue support.
+* No Topology-Aware Scheduling (TAS) support. 
\ No newline at end of file
diff --git a/site/content/en/docs/installation/_index.md b/site/content/en/docs/installation/_index.md
index bbdfe9bd6..fc2adf5fd 100644
--- a/site/content/en/docs/installation/_index.md
+++ b/site/content/en/docs/installation/_index.md
@@ -271,7 +271,7 @@ spec:
 | `PartialAdmission`                            | `false` | Alpha | 0.4   | 0.4   |
 | `PartialAdmission`                            | `true`  | Beta  | 0.5   |       |
 | `ProvisioningACC`                             | `false` | Alpha | 0.5   | 0.6   |
-| `ProvisioningACC`                             | `true`  | Beta  | 0.7   |       |
+| `ProvisioningACC`                             | `true`  | Beta  | 0.7   | 0.14  |
 | `QueueVisibility`                             | `false` | Alpha | 0.5   | 0.9   |
 | `VisibilityOnDemand`                          | `false` | Alpha | 0.6   | 0.8   |
 | `VisibilityOnDemand`                          | `true`  | Beta  | 0.9   |       |
@@ -301,6 +301,7 @@ spec:
 | Feature                           | Default | Stage      | Since | Until |
 | --------------------------------- | ------- | ---------- | ----- | ----- |
 | `ManagedJobsNamespaceSelector`    | `true`  | GA         | 0.13  |       |
+| `ProvisioningACC`                 | `true`  | GA         | 0.14  |       |
 | `QueueVisibility`                 | `false` | Alpha      | 0.4   | 0.9   |
 | `QueueVisibility`                 | `false` | Deprecated | 0.9   |       |
 | `TASProfileMostFreeCapacity`      | `false` | Deprecated | 0.11  | 0.13  |
diff --git a/site/content/en/docs/tasks/run/jobs.md b/site/content/en/docs/tasks/run/jobs.md
index 3be198ef6..0fc59f28a 100644
--- a/site/content/en/docs/tasks/run/jobs.md
+++ b/site/content/en/docs/tasks/run/jobs.md
@@ -215,3 +215,97 @@ For example, a Job defined by the following manifest:
 {{< include "examples/jobs/sample-job-partial-admission.yaml" "yaml" >}}
 
 When queued in a ClusterQueue with only 9 CPUs available, it will be admitted with `parallelism=9`. Note that the number of completions doesn't change.
+
+## ElasticJob
+
+{{< feature-state state="alpha" for_version="v0.13" >}}
+
+Kueue supports the ability for batch users to scale a `Job`'s parallelism **without recreating, restarting, or suspending** the Job.
+
+To enable this feature, ensure the following:
+
+* The `ElasticJobsViaWorkloadSlices` feature gate is set to `true`
+* The Job is annotated with `kueue.x-k8s.io/elastic-job: "true"`
+
+For example, a Job defined by the following manifest:
+
+{{< include "examples/jobs/sample-scalable-job.yaml" "yaml" >}}
+
+Once the Job is created, you can scale it by updating the `parallelism` field and applying the change.
+
+When scaling **up**, you should observe:
+
+* A **new workload** created and admitted for the updated parallelism
+* The **previous workload** being marked as `Finished`
+
+### Example Walkthrough
+
+#### Create
+
+1. Create a Job using the provided example.
+2. Observe the Job, Pod, and Workload objects.
+
+```text
+kubectl get job,deploy,rs,pod,workload
+
+NAME                           STATUS    COMPLETIONS   DURATION   AGE
+job.batch/sample-elastic-job   Running   0/10          4s         4s
+
+NAME                           READY   STATUS    RESTARTS   AGE
+pod/sample-elastic-job-468nl   1/1     Running   0          4s
+pod/sample-elastic-job-gd9qn   1/1     Running   0          4s
+pod/sample-elastic-job-snk6j   1/1     Running   0          4s
+
+NAME                                                   QUEUE       RESERVED IN   ADMITTED   FINISHED   ACTIVE   POD-COUNT   AGE
+workload.kueue.x-k8s.io/job-sample-elastic-job-615b3   user-queue  user-queue    True                  true     3           4s
+```
+
+#### Scale Down
+
+1. Update the example, reducing the `parallelism` value from `3` to `1`.
+2. Observe changes to the Job, Pod, and Workload objects.
+
+```text
+kubectl get job,deploy,rs,pod,workload
+
+NAME                           STATUS    COMPLETIONS   DURATION   AGE
+job.batch/sample-elastic-job   Running   0/10          27s        27s
+
+NAME                           READY   STATUS        RESTARTS   AGE
+pod/sample-elastic-job-468nl   1/1     Terminating   0          27s <-- 
+pod/sample-elastic-job-gd9qn   1/1     Running       0          27s
+pod/sample-elastic-job-snk6j   1/1     Terminating   0          27s <--
+
+NAME                                                   QUEUE       RESERVED IN   ADMITTED   FINISHED   ACTIVE   POD-COUNT   AGE
+workload.kueue.x-k8s.io/job-sample-elastic-job-615b3   user-queue  user-queue    True                  true     1           4s
+```
+
+* Two Pods are terminating, while the remaining Pod continues running.
+* No new Workload object is created.
+
+#### Scale Up
+
+1. Update the example, increasing the `parallelism` value from `1` to `4`.
+2. Observe changes to the Job, Pod, and Workload objects.
+
+```text
+kubectl get job,deploy,rs,pod,workload
+
+NAME                           STATUS    COMPLETIONS   DURATION   AGE
+job.batch/sample-elastic-job   Running   1/10          82s        82s
+
+NAME                           READY   STATUS      RESTARTS   AGE
+pod/sample-elastic-job-4xtsq   1/1     Running     0          10s 
+pod/sample-elastic-job-fl6j4   1/1     Running     0          10s
+pod/sample-elastic-job-gd9qn   1/1     Running     0          52s <-- old pod
+pod/sample-elastic-job-q482v   1/1     Running     0          10s
+
+
+NAME                                                   QUEUE       RESERVED IN   ADMITTED   FINISHED   ACTIVE   POD-COUNT   AGE
+workload.kueue.x-k8s.io/job-sample-elastic-job-615b3   user-queue  user-queue    True       True       true     1           52s <-- old workload
+workload.kueue.x-k8s.io/job-sample-elastic-job-992ea   user-queue  user-queue    True                  true     4           10s <-- new workload
+```
+
+* New Pods are created and running.
+* A **new Workload** is created with the updated Pod count.
+* The **old Workload** is marked as `Finished`.
diff --git a/site/content/en/docs/tasks/troubleshooting/troubleshooting_provreq.md b/site/content/en/docs/tasks/troubleshooting/troubleshooting_provreq.md
index 5cceb4341..574010307 100644
--- a/site/content/en/docs/tasks/troubleshooting/troubleshooting_provreq.md
+++ b/site/content/en/docs/tasks/troubleshooting/troubleshooting_provreq.md
@@ -17,7 +17,7 @@ Before you begin troubleshooting, make sure your cluster meets the following req
 Check your cloud provider's documentation to determine the minimum versions that support ProvisioningRequest. If you use GKE, your cluster should be running version `1.28.3-gke.1098000` or newer.
 - You use a type of nodes that support ProvisioningRequest. It may vary depending on your cloud provider.
 - Kueue's version is `v0.5.3` or newer.
-- You have enabled the `ProvisioningACC` in [the feature gates configuration](/docs/installation/#change-the-feature-gates-configuration). This feature gate is enabled by default for Kueue `v0.7.0` or newer.
+- ProvisioningRequest support is enabled. This feature has been enabled by default since Kueue `v0.7.0` and is Generally Available (GA) as of Kueue `v0.14.0`.
 
 ## Identifying the Provisioning Request for your job
 
@@ -125,26 +125,16 @@ The states transitions are as follow:
 
 If Kueue did not create a Provisioning Request for your job, try checking the following requirements:
 
-### a. Ensure the Kueue's controller manager enables the `ProvisioningACC` feature gate
+### a. Verify ProvisioningRequest support is available
 
-Run the following command to check whether your Kueue's controller manager has enabled the `ProvisioningACC` feature gate:
+Since Kueue v0.14.0, ProvisioningRequest support is Generally Available (GA) and always enabled. For older versions of Kueue (v0.7.0 to v0.13.x), the feature was enabled by default via the `ProvisioningACC` feature gate.
 
-```bash
-kubectl describe pod -n kueue-system kueue-controller-manager-
-```
-
-The arguments for Kueue container should be similar to the following:
+If you're using an older version of Kueue, you can verify the feature gate is enabled by running:
 
 ```bash
-    ...
-    Args:
-      --config=/controller_manager_config.yaml
-      --zap-log-level=2
-      --feature-gates=ProvisioningACC=true
+kubectl describe pod -n kueue-system kueue-controller-manager-
 ```
 
-Note for Kueue `v0.7.0` or newer the feature is enabled by default, so you may see different output.
-
 ### b. Ensure your Workload has reserved quota
 
 To check if your Workload has reserved quota in a ClusterQueue check your Workload's status by running the following command:
diff --git a/site/content/zh-CN/docs/reference/kubectl-kueue/commands/kueuectl_resume/kueuectl_resume_clusterqueue.md b/site/content/zh-CN/docs/reference/kubectl-kueue/commands/kueuectl_resume/kueuectl_resume_clusterqueue.md
index 82150eb35..6e4555361 100644
--- a/site/content/zh-CN/docs/reference/kubectl-kueue/commands/kueuectl_resume/kueuectl_resume_clusterqueue.md
+++ b/site/content/zh-CN/docs/reference/kubectl-kueue/commands/kueuectl_resume/kueuectl_resume_clusterqueue.md
@@ -5,30 +5,24 @@ auto_generated: true
 no_list: false
 ---
 
-<!--
-The file is auto-generated from the Go source code of the component using the
-[generator](https://github.com/kubernetes-sigs/kueue/tree/main/cmd/kueuectl-docs).
--->
+## 概要 {#synopsis}
 
-## Synopsis
-
-
-Resumes the previously held ClusterQueue.
+恢复之前暂停的 ClusterQueue。
 
 ```
 kueuectl resume clusterqueue NAME
 ```
 
 
-## Examples
+## 示例 {#examples}
 
 ```
-  # Resume the clusterqueue
+  # 恢复集群队列
   kueuectl resume clusterqueue my-clusterqueue
 ```
 
 
-## Options
+## 选项 {#options}
 
 
 <table style="width: 100%; table-layout: fixed;">
@@ -38,12 +32,12 @@ kueuectl resume clusterqueue NAME
     </colgroup>
     <tbody>
     <tr>
-        <td colspan="2">--allow-missing-template-keys&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Default: true</td>
+        <td colspan="2">--allow-missing-template-keys&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;默认值： true</td>
     </tr>
     <tr>
         <td></td>
         <td style="line-height: 130%; word-wrap: break-word;">
-            <p>If true, ignore any errors in templates when a field or map key is missing in the template. Only applies to golang and jsonpath output formats.</p>
+            <p>如果为 true，当模板中缺少字段或映射键时忽略模板中的任何错误。仅适用于 golang 和 jsonpath 输出格式。</p>
         </td>
     </tr>
     <tr>
@@ -52,7 +46,7 @@ kueuectl resume clusterqueue NAME
     <tr>
         <td></td>
         <td style="line-height: 130%; word-wrap: break-word;">
-            <p>help for clusterqueue</p>
+            <p>clusterqueue 命令的帮助信息</p>
         </td>
     </tr>
     <tr>
@@ -61,7 +55,7 @@ kueuectl resume clusterqueue NAME
     <tr>
         <td></td>
         <td style="line-height: 130%; word-wrap: break-word;">
-            <p>Output format. One of: (json, yaml, name, go-template, go-template-file, template, templatefile, jsonpath, jsonpath-as-json, jsonpath-file).</p>
+            <p>输出格式。可选值为：json、yaml、name、go-template、go-template-file、template、templatefile、jsonpath、jsonpath-as-json、jsonpath-file。</p>
         </td>
     </tr>
     <tr>
@@ -70,7 +64,7 @@ kueuectl resume clusterqueue NAME
     <tr>
         <td></td>
         <td style="line-height: 130%; word-wrap: break-word;">
-            <p>If true, keep the managedFields when printing objects in JSON or YAML format.</p>
+            <p>如果为 true，在 JSON 或 YAML 格式打印对象时保留 managedFields。</p>
         </td>
     </tr>
     <tr>
@@ -79,7 +73,7 @@ kueuectl resume clusterqueue NAME
     <tr>
         <td></td>
         <td style="line-height: 130%; word-wrap: break-word;">
-            <p>Template string or path to template file to use when -o=go-template, -o=go-template-file. The template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].</p>
+            <p>当使用 -o=go-template、-o=go-template-file 时要使用的模板字符串或模板文件路径。模板格式是 golang 模板 [http://golang.org/pkg/text/template/#pkg-overview]。</p>
         </td>
     </tr>
     </tbody>
@@ -87,7 +81,7 @@ kueuectl resume clusterqueue NAME
 
 
 
-## Options inherited from parent commands
+## 从父命令继承的选项 {#options-inherited-from-parent-commands}
 <table style="width: 100%; table-layout: fixed;">
     <colgroup>
         <col span="1" style="width: 10px;" />
@@ -100,7 +94,7 @@ kueuectl resume clusterqueue NAME
     <tr>
         <td></td>
         <td style="line-height: 130%; word-wrap: break-word;">
-            <p>Username to impersonate for the operation. User could be a regular user or a service account in a namespace.</p>
+            <p>为操作模拟的用户名。用户可以是普通用户或命名空间中的服务账户。</p>
         </td>
     </tr>
     <tr>
@@ -109,7 +103,7 @@ kueuectl resume clusterqueue NAME
     <tr>
         <td></td>
         <td style="line-height: 130%; word-wrap: break-word;">
-            <p>Group to impersonate for the operation, this flag can be repeated to specify multiple groups.</p>
+            <p>为操作模拟的组，此标志可以重复使用，以指定多个组。</p>
         </td>
     </tr>
     <tr>
@@ -118,16 +112,16 @@ kueuectl resume clusterqueue NAME
     <tr>
         <td></td>
         <td style="line-height: 130%; word-wrap: break-word;">
-            <p>UID to impersonate for the operation.</p>
+            <p>为操作模拟的 UID。</p>
         </td>
     </tr>
     <tr>
-        <td colspan="2">--cache-dir string&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Default: &#34;$HOME/.kube/cache&#34;</td>
+        <td colspan="2">--cache-dir string&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;默认值： &#34;$HOME/.kube/cache&#34;</td>
     </tr>
     <tr>
         <td></td>
         <td style="line-height: 130%; word-wrap: break-word;">
-            <p>Default cache directory</p>
+            <p>默认缓存目录</p>
         </td>
     </tr>
     <tr>
@@ -136,7 +130,7 @@ kueuectl resume clusterqueue NAME
     <tr>
         <td></td>
         <td style="line-height: 130%; word-wrap: break-word;">
-            <p>Path to a cert file for the certificate authority</p>
+            <p>证书颁发机构的证书文件路径</p>
         </td>
     </tr>
     <tr>
@@ -145,7 +139,7 @@ kueuectl resume clusterqueue NAME
     <tr>
         <td></td>
         <td style="line-height: 130%; word-wrap: break-word;">
-            <p>Path to a client certificate file for TLS</p>
+            <p>TLS 客户端证书文件路径</p>
         </td>
     </tr>
     <tr>
@@ -154,7 +148,7 @@ kueuectl resume clusterqueue NAME
     <tr>
         <td></td>
         <td style="line-height: 130%; word-wrap: break-word;">
-            <p>Path to a client key file for TLS</p>
+            <p>TLS 客户端密钥文件路径</p>
         </td>
     </tr>
     <tr>
@@ -163,7 +157,7 @@ kueuectl resume clusterqueue NAME
     <tr>
         <td></td>
         <td style="line-height: 130%; word-wrap: break-word;">
-            <p>The name of the kubeconfig cluster to use</p>
+            <p>要使用的 kubeconfig 集群的名称</p>
         </td>
     </tr>
     <tr>
@@ -172,7 +166,7 @@ kueuectl resume clusterqueue NAME
     <tr>
         <td></td>
         <td style="line-height: 130%; word-wrap: break-word;">
-            <p>The name of the kubeconfig context to use</p>
+            <p>要使用的 kubeconfig 上下文的名称</p>
         </td>
     </tr>
     <tr>
@@ -181,16 +175,16 @@ kueuectl resume clusterqueue NAME
     <tr>
         <td></td>
         <td style="line-height: 130%; word-wrap: break-word;">
-            <p>If true, opt-out of response compression for all requests to the server</p>
+            <p>如果为 true，则取消对所有服务器请求的响应压缩</p>
         </td>
     </tr>
     <tr>
-        <td colspan="2">--dry-run string&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Default: &#34;none&#34;</td>
+        <td colspan="2">--dry-run string&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;默认值： &#34;none&#34;</td>
     </tr>
     <tr>
         <td></td>
         <td style="line-height: 130%; word-wrap: break-word;">
-            <p>Must be &#34;none&#34;, &#34;server&#34;, or &#34;client&#34;. If client strategy, only print the object that would be sent, without sending it. If server strategy, submit server-side request without persisting the resource.</p>
+            <p>必须是 &#34;none&#34;、&#34;server&#34; 或 &#34;client&#34;。如果是客户端策略，只打印将要发送的对象，而不发送它。如果是服务器策略，提交服务器端请求而不持久化资源。</p>
         </td>
     </tr>
     <tr>
@@ -199,7 +193,7 @@ kueuectl resume clusterqueue NAME
     <tr>
         <td></td>
         <td style="line-height: 130%; word-wrap: break-word;">
-            <p>If true, the server&#39;s certificate will not be checked for validity. This will make your HTTPS connections insecure</p>
+            <p>如果为 true，将不检查服务器证书的有效性。这将使你的 HTTPS 连接不安全</p>
         </td>
     </tr>
     <tr>
@@ -208,7 +202,7 @@ kueuectl resume clusterqueue NAME
     <tr>
         <td></td>
         <td style="line-height: 130%; word-wrap: break-word;">
-            <p>Path to the kubeconfig file to use for CLI requests.</p>
+            <p>用于 CLI 请求的 kubeconfig 文件路径。</p>
         </td>
     </tr>
     <tr>
@@ -217,16 +211,16 @@ kueuectl resume clusterqueue NAME
     <tr>
         <td></td>
         <td style="line-height: 130%; word-wrap: break-word;">
-            <p>If present, the namespace scope for this CLI request</p>
+            <p>如果存在，则为此次 CLI 请求的命名空间范围</p>
         </td>
     </tr>
     <tr>
-        <td colspan="2">--request-timeout string&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Default: &#34;0&#34;</td>
+        <td colspan="2">--request-timeout string&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;默认值： &#34;0&#34;</td>
     </tr>
     <tr>
         <td></td>
         <td style="line-height: 130%; word-wrap: break-word;">
-            <p>The length of time to wait before giving up on a single server request. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means don&#39;t timeout requests.</p>
+            <p>在放弃单个服务器请求之前要等待的时间长度。非零值应包含相应的时间单位（例如 1s、2m、3h）。零值意味着不要超时请求。</p>
         </td>
     </tr>
     <tr>
@@ -235,7 +229,7 @@ kueuectl resume clusterqueue NAME
     <tr>
         <td></td>
         <td style="line-height: 130%; word-wrap: break-word;">
-            <p>The address and port of the Kubernetes API server</p>
+            <p>Kubernetes API 服务器的地址和端口</p>
         </td>
     </tr>
     <tr>
@@ -244,7 +238,7 @@ kueuectl resume clusterqueue NAME
     <tr>
         <td></td>
         <td style="line-height: 130%; word-wrap: break-word;">
-            <p>Server name to use for server certificate validation. If it is not provided, the hostname used to contact the server is used</p>
+            <p>用于服务器证书验证的服务器名称。如果未提供，则使用联系服务器所用的主机名</p>
         </td>
     </tr>
     <tr>
@@ -253,7 +247,7 @@ kueuectl resume clusterqueue NAME
     <tr>
         <td></td>
         <td style="line-height: 130%; word-wrap: break-word;">
-            <p>Bearer token for authentication to the API server</p>
+            <p>API 服务器身份验证所用的持有者令牌</p>
         </td>
     </tr>
     <tr>
@@ -262,7 +256,7 @@ kueuectl resume clusterqueue NAME
     <tr>
         <td></td>
         <td style="line-height: 130%; word-wrap: break-word;">
-            <p>The name of the kubeconfig user to use</p>
+            <p>要使用的 kubeconfig 用户的名称</p>
         </td>
     </tr>
     </tbody>
@@ -270,7 +264,7 @@ kueuectl resume clusterqueue NAME
 
 
 
-## See Also
+## 另请参阅 {#see-also}
 
-* [kueuectl resume](../)	 - Resume the resource
+* [kueuectl resume](../) - 恢复资源
 
diff --git a/site/content/zh-CN/docs/tasks/manage/administer_cluster_quotas.md b/site/content/zh-CN/docs/tasks/manage/administer_cluster_quotas.md
index 42e68fb09..58ea8ccd3 100644
--- a/site/content/zh-CN/docs/tasks/manage/administer_cluster_quotas.md
+++ b/site/content/zh-CN/docs/tasks/manage/administer_cluster_quotas.md
@@ -1,43 +1,40 @@
 ---
-title: "Administer Cluster Quotas"
+title: "管理集群配额"
 date: 2022-03-14
 weight: 2
 description: >
-  Manage your cluster resource quotas and to establish Fair Sharing rules among the tenants.
+  管理你的集群资源配额，并在租户之间建立公平共享规则。
 ---
 
-This page shows you how to manage your cluster resource quotas and to establish
-Fair Sharing rules among the tenants.
+本页面向你展示如何管理集群资源配额，
+并在租户之间建立公平共享规则。
 
-The intended audience for this page are [batch administrators](/docs/tasks#batch-administrator).
+本页面的目标读者是[批处理管理员](/zh-CN/docs/tasks#batch-administrator)。
 
-## Before you begin
+## 你开始之前 {#before-you-begin}
 
-Make sure the following conditions are met:
+请确保满足以下条件：
 
-- A Kubernetes cluster is running.
-- The kubectl command-line tool has communication with your cluster.
-- [Kueue is installed](/docs/installation).
+- Kubernetes 集群已运行。
+- kubectl 命令行工具能与你的集群通信。
+- [已安装 Kueue](/zh-CN/docs/installation)。
 
-## Single ClusterQueue and single ResourceFlavor setup
+## 安装单一 ClusterQueue 和 ResourceFlavor {#single-clusterqueue-and-single-resourceflavor-setup}
 
-In the following steps, you will create a queuing system with a single
-ClusterQueue and a single [ResourceFlavor](/docs/concepts/cluster_queue#resourceflavor-object)
-to govern the quota of your cluster.
+在以下步骤中，你将创建一个排队系统用于管理集群的配额，它拥有
+一个 ClusterQueue 和一个 [ResourceFlavor](/zh-CN/docs/concepts/cluster_queue#resourceflavor-object)。
 
-You can perform all these steps at once by
-applying [examples/admin/single-clusterqueue-setup.yaml](/examples/admin/single-clusterqueue-setup.yaml):
+你可以通过 apply [examples/admin/single-clusterqueue-setup.yaml](/examples/admin/single-clusterqueue-setup.yaml)一次性完成这些步骤：
 
 ```shell
 kubectl apply -f examples/admin/single-clusterqueue-setup.yaml
 ```
 
-### 1. Create a [ClusterQueue](/docs/concepts/cluster_queue)
+### 1. 创建 [ClusterQueue](/zh-CN/docs/concepts/cluster_queue) {#1-create-clusterqueue}
 
-Create a single ClusterQueue to represent the resource quotas for your entire
-cluster.
+创建一个 ClusterQueue 来表示整个集群的资源配额。
 
-Write the manifest for the ClusterQueue. It should look similar to the following:
+编写 ClusterQueue 的清单文件。应类似如下：
 
 ```yaml
 # cluster-queue.yaml
@@ -58,28 +55,27 @@ spec:
         nominalQuota: 36Gi
 ```
 
-To create the ClusterQueue, run the following command:
+要创建 ClusterQueue，请运行以下命令：
 
 ```shell
 kubectl apply -f cluster-queue.yaml
 ```
 
-This ClusterQueue governs the usage of [resource types](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#resource-types)
-`cpu` and `memory`. Each resource type has a single [resource flavor](/docs/concepts/cluster_queue#resourceflavor-object),
-named `default` with a nominal quota.
+此 ClusterQueue 管理[资源类型](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#resource-types)
+`cpu` 和 `memory` 的使用。每种资源类型都有一个名为 `default` 的 [ResourceFlavor](/zh-CN/docs/concepts/cluster_queue#resourceflavor-object)，
+并设置了名义配额。
 
-The empty `namespaceSelector` allows any namespace to use these resources.
+空的 `namespaceSelector` 允许任何命名空间使用这些资源。
 
-### 2. Create a [ResourceFlavor](/docs/concepts/cluster_queue#resourceflavor-object)
+### 2. 创建 [ResourceFlavor](/zh-CN/docs/concepts/cluster_queue#resourceflavor-object) {#2-create-resourceflavor}
 
-The ClusterQueue is not ready to be used yet, as the `default` flavor is not
-defined.
+ClusterQueue 目前还不能使用，因为 `default` 风味尚未定义。
 
-Typically, a resource flavor has node labels and/or taints to scope which nodes
-can provide it. However, since we are using a single flavor to represent all the
-resources available in the cluster, you can create an empty ResourceFlavor.
+通常，ResourceFlavor 有节点标签和/或污点，用于限定哪些节点可以提供此 Flavor。
+但由于我们使用单一风味来代表
+集群中所有可用资源，你可以创建一个空的 ResourceFlavor。
 
-Write the manifest for the ResourceFlavor. It should look similar to the following:
+编写 ResourceFlavor 的清单文件。应类似如下：
 
 ```yaml
 # default-flavor.yaml
@@ -89,24 +85,24 @@ metadata:
   name: "default-flavor"
 ```
 
-To create the ResourceFlavor, run the following command:
+要创建 ResourceFlavor，请运行以下命令：
 
 ```shell
 kubectl apply -f default-flavor.yaml
 ```
 
-The `.metadata.name` matches the `.spec.resourceGroups[0].flavors[0].name`
-field in the ClusterQueue.
+`.metadata.name` 字段需与 ClusterQueue 中 `.spec.resourceGroups[0].flavors[0].name`
+字段一致。
 
-### 3. Create [LocalQueues](/docs/concepts/local_queue)
+### 3. 创建 [LocalQueues](/zh-CN/docs/concepts/local_queue) {#3-create-localqueues}
 
-Users cannot directly send [workloads](/docs/concepts/workload) to
-ClusterQueues. Instead, users need to send their workloads to a Queue in their
-namespace.
-Thus, for the queuing system to be complete, you need to create a Queue in
-each namespace that needs access to the ClusterQueue.
+用户不能直接将[工作负载](/zh-CN/docs/concepts/workload)
+发送到 ClusterQueue。
+用户需要将工作负载发送到其命名空间中的队列。
+因此，为了使排队系统完整，
+你需要在每个需要访问 ClusterQueue 的命名空间中创建一个队列。
 
-Write the manifest for the LocalQueue. It should look similar to the following:
+编写 LocalQueue 的清单文件。应类似如下：
 
 ```yaml
 # default-user-queue.yaml
@@ -119,24 +115,23 @@ spec:
   clusterQueue: "cluster-queue"
 ```
 
-To create the LocalQueue, run the following command:
+要创建 LocalQueue，请运行以下命令：
 
 ```shell
 kubectl apply -f default-user-queue.yaml
 ```
 
-## Multiple ResourceFlavors setup
+## 多 ResourceFlavor 设置 {#multiple-resourceflavors-setup}
 
-You can define quotas for different [resource flavors](/docs/concepts/cluster_queue#resourceflavor-object).
+你可以为不同的 [ResourceFlavor](/zh-CN/docs/concepts/cluster_queue#resourceflavor-object)定义配额。
 
-For the rest of this section, assume that your cluster has nodes with two CPU
-architectures, namely `x86` and `arm`, specified in the node label `cpu-arch`.
+本节其余部分假设你的集群有两种 CPU 架构的节点，
+分别为 `x86` 和 `arm`，通过节点标签 `cpu-arch` 指定。
 
+### 1. 创建 ResourceFlavors {#1-create-resourceflavors}
 
-### 1. Create ResourceFlavors
-
-Write the manifests for the ResourceFlavors. They should look similar to the
-following:
+编写 ResourceFlavor 的清单文件。
+应类似如下：
 
 ```yaml
 # flavor-x86.yaml
@@ -160,21 +155,19 @@ spec:
     cpu-arch: arm
 ```
 
-To create the ResourceFlavors, run the following command:
+要创建 ResourceFlavor，请运行以下命令：
 
 ```shell
 kubectl apply -f flavor-x86.yaml -f flavor-arm.yaml
 ```
 
-The labels set in the ResourceFlavors should match the labels in your nodes.
-If you are using [cluster autoscaler](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler)
-(or equivalent controllers), make sure it is configured to add those labels when
-adding new nodes.
+ResourceFlavor 中设置的标签应与你的节点标签一致。
+如果你使用 [cluster autoscaler](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler)
+或类似控制器，请确保其配置为在添加新节点时添加这些标签。
 
-### 2. Create a ClusterQueue referencing the flavors
+### 2. 创建引用 ResourceFlavor 的 ClusterQueue {#2-create-a-clusterqueue-referencing-the-flavors}
 
-Write the manifest for the ClusterQueue that references the flavors. It should
-look similar to the following:
+编写引用 ResourceFlavor 的 ClusterQueue 清单文件。应类似如下：
 
 ```yaml
 # cluster-queue.yaml
@@ -203,26 +196,25 @@ spec:
         nominalQuota: 84Gi
 ```
 
-The flavor names in the fields `.spec.resourceGroups[*].flavors[*].name`
-should match the names of the ResourceFlavors created earlier.
+`.spec.resourceGroups[*].flavors[*].name`
+字段中的风味名称应与前面创建的 ResourceFlavor 名称一致。
 
-Note that `memory` is referencing the `default-flavor` flavor created in the [single flavor setup.](#single-clusterqueue-and-single-resourceflavor-setup)
-This means that you don't want to distinguish if the memory is given from `x86`
-or `arm` nodes.
+注意，`memory` 引用了在[单一风味设置](#single-clusterqueue-and-single-resourceflavor-setup)
+中创建的 `default-flavor` 风味。
+这意味着你不区分内存来自 `x86` 还是 `arm` 节点。
 
-To create the ClusterQueue, run the following command:
+要创建 ClusterQueue，请运行以下命令：
 
 ```shell
 kubectl apply -f cluster-queue.yaml
 ```
 
-## Multiple ClusterQueues and borrowing cohorts
+## 多 ClusterQueue 与借用 cohort {#multiple-clusterqueues-and-borrowing-cohorts}
 
-Two or more ClusterQueues can borrow unused quota from other ClusterQueues in
-the same [cohort](/docs/concepts/cluster_queue#cohort).
+两个或多个 ClusterQueue 可以在同一 [cohort](/zh-CN/docs/concepts/cluster_queue#cohort)
+中相互借用未使用的配额。
 
-Using the following example, you can establish a cohort `team-ab` that includes
-ClusterQueues `team-a-cq` and `team-b-cq`.
+通过以下示例，你可以建立一个包含 ClusterQueue `team-a-cq` 和 `team-b-cq` 的 cohort `team-ab`。
 
 ```yaml
 # team-a-cq.yaml
@@ -265,27 +257,26 @@ spec:
         nominalQuota: 48Gi
 ```
 
-Note that the ClusterQueue `team-a-cq` also defines [borrowingLimit](/docs/concepts/cluster_queue#borrowingLimit).
-This restricts the ability of the ClusterQueue to borrow the unused quota from
-the cohort up to the configured `borrowingLimit`, even if the quota is completely unused.
+注意，ClusterQueue `team-a-cq` 还定义了 [borrowingLimit](/zh-CN/docs/concepts/cluster_queue#borrowingLimit)。
+这限制了 ClusterQueue 从 cohort 借用未使用配额的能力，
+最多只能借用到配置的 `borrowingLimit`，即使配额完全未被使用。
 
-To create these ClusterQueues, save the preceding manifests and run the
-following command:
+要创建这些 ClusterQueue，
+请保存上述清单并运行以下命令：
 
 ```shell
 kubectl apply -f team-a-cq.yaml -f team-b-cq.yaml
 ```
 
-## Multiple ClusterQueue with dedicated and fallback flavors
+## 多个 ClusterQueue 包含专用和回退资源类型 {#multiple-clusterqueue-with-dedicated-and-fallback-flavors}
 
-A ClusterQueue can borrow resources from the [cohort](/docs/concepts/cluster_queue#cohort)
-even if the ClusterQueue has zero nominalQuota for a flavor. This allows you to
-give dedicated quota for a flavor and fallback to quota for a different flavor,
-shared with other tenants.
+即使 ClusterQueue 某个风味的 nominalQuota 为零，
+也可以从 [cohort](/zh-CN/docs/concepts/cluster_queue#cohort)
+借用资源。这允许你为某个风味分配专用配额，并在需要时回退到与其他租户共享的风味配额。
 
-Such setup can be accomplished with a ClusterQueue for each tenant and an extra
-ClusterQueue for the shared resources. For example, the manifests for two
-tenants look like the following:
+这种设置可以通过为每个租户创建一个 ClusterQueue，
+并为共享资源创建一个额外的 ClusterQueue 实现。
+例如，两个租户的清单如下：
 
 ```yaml
 # team-a-cq.yaml
@@ -369,29 +360,27 @@ spec:
         nominalQuota: 24Gi
 ```
 
-Note the following setup:
+请注意以下设置：
 
-- `team-a-cq` and `team-b-cq` define a `borrowingLimit: 0` 
-  for the `arm` flavor. Therefore, they can't borrow this flavor from each
-  other.
-- `team-a-cq` and `team-b-cq` define `nominalQuota: 0` for the `x86` flavor.
-  Therefore, they don't have any dedicated quota for the flavor and they can
-  only borrow it from `shared-cq`.
+- `team-a-cq` 和 `team-b-cq` 为 `arm` 风味定义了 `borrowingLimit: 0`，
+  因此它们不能相互借用该风味。
+- `team-a-cq` 和 `team-b-cq` 为 `x86` 风味定义了 `nominalQuota: 0`，
+  因此它们没有该风味的专用配额，
+  只能从 `shared-cq` 借用。
 
-To create these ClusterQueues, save the preceding manifests and run the
-following command:
+要创建这些 ClusterQueue，
+请保存上述清单并运行以下命令：
 
 ```shell
 kubectl apply -f team-a-cq.yaml -f team-b-cq.yaml -f shared-cq.yaml
 ```
 
-## Exclude arbitrary resources in the quota management 
-By default, administrators must specify all resources required by Pods in the ClusterQueues `.spec.resourceGroups[*]`.
-If you want to exclude some resources in the ClusterQueues quota management and admission process, 
-you can specify the resource prefixes in the Kueue Configuration as a cluster-level setting.
+## 在配额管理中排除任意资源 {#exclude-arbitrary-resources-in-the-quota-management}
+默认情况下，管理员必须在 ClusterQueue 的 `.spec.resourceGroups[*]` 中指定 Pod 所需的所有资源。
+如果你希望在 ClusterQueue 配额管理和准入过程中排除某些资源，可以在 Kueue 配置中以集群级别设置资源前缀。
 
-Follow the [installation instructions for using a custom configuration](/docs/installation#install-a-custom-configured-released-version) 
-and extend the configuration with fields similar to the following:
+请按照[使用自定义配置的安装说明](/zh-CN/docs/installation#install-a-custom-configured-released-version)
+操作，并在配置中添加如下字段：
 
 ```yaml
 apiVersion: config.kueue.x-k8s.io/v1beta1
@@ -401,31 +390,30 @@ resources:
   - "example.com"
 ```
 
-## Transform resources for quota management
+## 配额管理的资源转换 {#transform-resources-for-quota-management}
 
 {{< feature-state state="beta" for_version="v0.10" >}}
-{{% alert title="Note" color="primary" %}}
+{{% alert title="注意" color="primary" %}}
 
-`ConfigurableResourceTransformation` is a Beta feature that is enabled by default.
+`ConfigurableResourceTransformation` 是一个 Beta 特性，默认启用。
 
-You can disable it by setting the `ConfigurableResourceTransformation` feature gate. Check the [Installation](/docs/installation/#change-the-feature-gates-configuration) guide for details on feature gate configuration.
+你可以通过设置 `ConfigurableResourceTransformation` 特性开关来禁用它。详细的特性开关配置请查阅[安装指南](/zh-CN/docs/installation/#change-the-feature-gates-configuration)。
 {{% /alert %}}
 
-An administrator may customize how the resources requested by Pods are
-converted into Workload resource requests. This enables
-the admission and quota calculations done by ClusterQueues to be performed
-on a transformed set of resources requirements without changing
-the resource requests and limits that the Pods created by the Workload
-will present to the Kubernetes Scheduler when the Workload is admitted by
-a ClusterQueue. Customizations are defined by specifying resource transformations
-in the Kueue configuration as a cluster-level setting.
+管理员可以自定义 Pod 请求的资源是如何转换成 Workload 的资源请求的。
+这样，ClusterQueue 在执行准入（admission）和配额（quota）计算时，
+可以基于转换后的资源需求进行，
+而无需更改 Workload
+在被 ClusterQueue 接受后、其创建的 Pod 向 Kubernetes Scheduler 所呈现的资源请求与限制。
+这种自定义通过在 Kueue 配置中指定 资源转换规则 来实现，
+并作为集群级别的设置生效。
 
-The supported transformations enable mapping an input resource into one or more
-output resources by multiplying the input resource quantity by a scaling factor.
-The input resource may either be retained (default) or removed from the transformed resources. If no transformation is defined for an input resource, it is retained without change.
+支持的转换允许通过乘以缩放因子，将输入资源映射为一个或多个输出资源。
+输入资源可以保留（默认）或从转换后的资源中移除。
+如果未为输入资源定义转换，则保持不变。
 
-Follow the [installation instructions for using a custom configuration](/docs/installation#install-a-custom-configured-released-version)
-and extend the Kueue configuration with fields similar to the following:
+请按照[使用自定义配置的安装说明](/zh-CN/docs/installation#install-a-custom-configured-released-version)
+操作，并在 Kueue 配置中添加如下字段：
 
 ```yaml
 apiVersion: config.kueue.x-k8s.io/v1beta1
@@ -448,7 +436,7 @@ resources:
       example.com/credits: 1
 ```
 
-With this example configuration, a Pod that requests:
+有了此配置，Pod 请求如下：
 ```yaml
     resources:
       requests:
@@ -459,7 +447,7 @@ With this example configuration, a Pod that requests:
         example.com/gpu-type2: 1
 ```
 
-The Workload obtains an effective resource requests for quota purposes:
+Workload 获得的有效资源请求为：
 
 ```yaml
     resources:
diff --git a/site/content/zh-CN/docs/tasks/run/appwrappers.md b/site/content/zh-CN/docs/tasks/run/appwrappers.md
index 6266d2c58..7cd97fe38 100644
--- a/site/content/zh-CN/docs/tasks/run/appwrappers.md
+++ b/site/content/zh-CN/docs/tasks/run/appwrappers.md
@@ -1,39 +1,39 @@
 ---
-title: "Run An AppWrapper"
-linkTitle: "AppWrappers"
+title: "运行 AppWrapper"
+linkTitle: "AppWrapper"
 date: 2025-01-08
 weight: 6
-description: >
-  Run an AppWrapper on Kueue.
+description: 在 Kueue 上运行 AppWrapper。
 ---
 
-This page shows how to leverage Kueue's scheduling and resource management capabilities when running [AppWrappers](https://project-codeflare.github.io/appwrapper/).
+本页面展示了在运行 [AppWrapper](https://project-codeflare.github.io/appwrapper/)
+时，如何利用 Kueue 的调度和资源管理能力。
 
-AppWrappers provide a flexible and workload-agnostic mechanism for enabling Kueue to manage a group of Kubernetes resources as a single
-logical unit without requiring any Kueue-specific support by the controllers of those resources.
+AppWrapper 提供了一种灵活且与工作负载无关的机制，使 Kueue 能够将一组 Kubernetes 资源作为一个单一的逻辑单元进行管理，
+而无需这些资源的控制器具备任何 Kueue 特定的支持。
 
-AppWrappers are designed to harden workloads by providing an additional level of automatic fault detection and recovery. The
-AppWrapper controller monitors the health of the workload and if corrective actions are not taken by the primary resource controllers
-within specified deadlines, the AppWrapper controller will orchestrate workload-level retries and resource deletion to ensure that either the
-workload returns to a healthy state or is cleanly removed from the cluster and its quota freed for use by other workloads.
+AppWrapper 旨在通过提供额外的自动故障检测和恢复机制来增强工作负载的健壮性。
+AppWrapper 控制器会监控工作负载的健康状况，
+如果主要资源控制器在指定的截止时间内未采取纠正措施，AppWrapper 控制器将协调工作负载级别的重试和资源删除，
+以确保工作负载要么恢复到健康状态，要么被干净地从集群中移除，并释放其配额供其他工作负载使用。
 
-This guide is for [batch users](/docs/tasks#batch-user) that have a basic understanding of Kueue. For more information, see [Kueue's overview](/docs/overview).
+本指南适用于对 Kueue 有基本了解的[批用户](/zh-CN/docs/tasks#batch-user)。更多信息请参见 [Kueue 概述](/zh-CN/docs/overview)。
 
-## Before you begin
+## 开始之前 {#before-you-begin}
 
-Check [Administer cluster quotas](/docs/tasks/manage/administer_cluster_quotas) for details on the initial Kueue setup.
+请查阅[管理集群配额](/zh-CN/docs/tasks/manage/administer_cluster_quotas)以了解 Kueue 的初始设置详情。
 
-To simplify setup, make sure you are using Kueue v0.11.0 version or newer and AppWrapper v1.1.1 or newer.
+为简化设置，请确保你使用的是 Kueue v0.11.0 和 AppWrapper v1.1.1 及以上版本。
 
-See [AppWrapper Quick-Start Guide](https://project-codeflare.github.io/appwrapper/quick-start/) for installation and configuration details of the AppWrapper Operator.
+有关 AppWrapper Operator 的安装和配置详情，请参见 [AppWrapper 快速入门指南](https://project-codeflare.github.io/appwrapper/quick-start/)。
 
-## AppWrapper definition
+## AppWrapper 定义 {#appwrapper-definition}
 
-When running AppWrappers on Kueue, take into consideration the following aspects:
+在 Kueue 上运行 AppWrapper 时，请注意以下方面：
 
-### a. Queue selection
+### a. 队列选择 {#a-queue-selection}
 
-The target [local queue](/docs/concepts/local_queue) should be specified in the `metadata.labels` section of the AppWrapper.
+目标[本地队列](/zh-CN/docs/concepts/local_queue)应在 AppWrapper 的 `metadata.labels` 部分指定。
 
 ```yaml
 metadata:
@@ -41,23 +41,23 @@ metadata:
     kueue.x-k8s.io/queue-name: user-queue
 ```
 
-### b. Configure the resource needs
+### b. 配置资源需求 {#b-configure-the-resource-needs}
 
-The resource needs of the workload are computed by combining the resource needs of each wrapper component.
+工作负载的资源需求通过组合每个 Wrapper 组件的资源需求来计算。
 
-## Example AppWrapper containing a PyTorchJob
+## 包含 PyTorchJob 的 AppWrapper 示例 {#example-appwrapper-containing-a-pytorchjob}
 
-The AppWrapper looks like the following:
+AppWrapper 如下所示：
 
 {{< include "examples/appwrapper/pytorch-sample.yaml" "yaml" >}}
 
-{{% alert title="Note" color="primary" %}}
-The example above comes from [here](https://raw.githubusercontent.com/project-codeflare/appwrapper/refs/heads/main/samples/wrapped-pytorch-job.yaml)
-and only has the `queue-name` label changed.
+{{% alert title="注意" color="primary" %}}
+上述示例来自[这里](https://raw.githubusercontent.com/project-codeflare/appwrapper/refs/heads/main/samples/wrapped-pytorch-job.yaml)，
+仅更改了 `queue-name` 标签。
 {{% /alert %}}
 
-## Example AppWrapper containing a Deployment
+## 包含 Deployment 的 AppWrapper 示例 {#example-appwrapper-containing-a-deployment}
 
-The AppWrapper looks like the following:
+AppWrapper 如下所示：
 
 {{< include "examples/appwrapper/deployment-sample.yaml" "yaml" >}}
diff --git a/site/hugo.toml b/site/hugo.toml
index a0a735edc..4596fe64f 100644
--- a/site/hugo.toml
+++ b/site/hugo.toml
@@ -99,10 +99,10 @@ ignoreFiles = []
   # The major.minor version tag for the version of the docs represented in this
   # branch of the repository. Used in the "version-banner" partial to display a
   # version number for this doc set.
-  version = "v0.13.1"
+  version = "v0.13.2"
 
   # Version of Kueue without the leading "v", as used for Helm charts.
-  chart_version = "0.13.1"
+  chart_version = "0.13.2"
 
   # Flag used in the "version-banner" partial to decide whether to display a
   # banner on every page indicating that this is an archived version of the docs.
diff --git a/site/static/examples/jobs/sample-scalable-job.yaml b/site/static/examples/jobs/sample-scalable-job.yaml
new file mode 100644
index 000000000..7eff878bb
--- /dev/null
+++ b/site/static/examples/jobs/sample-scalable-job.yaml
@@ -0,0 +1,25 @@
+apiVersion: batch/v1
+kind: Job
+metadata:
+  name: sample-elastic-job
+  namespace: default
+  annotations:
+    kueue.x-k8s.io/elastic-job: "true"
+  labels:
+    kueue.x-k8s.io/queue-name: user-queue
+spec:
+  parallelism: 3
+  completions: 100
+  suspend: true
+  template:
+    spec:
+      containers:
+      - name: dummy-job
+        image: registry.k8s.io/e2e-test-images/agnhost:2.53
+        command: [ "/bin/sh" ]
+        args: [ "-c", "sleep 60" ]
+        resources:
+          requests:
+            cpu: "100m"
+            memory: "100Mi"
+      restartPolicy: Never
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 842003191..f4314b71a 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -754,7 +754,7 @@ k8s.io/api/storage/v1
 k8s.io/api/storage/v1alpha1
 k8s.io/api/storage/v1beta1
 k8s.io/api/storagemigration/v1alpha1
-# k8s.io/apiextensions-apiserver v0.33.1
+# k8s.io/apiextensions-apiserver v0.33.3
 ## explicit; go 1.24.0
 k8s.io/apiextensions-apiserver/pkg/apis/apiextensions
 k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1
@@ -1681,7 +1681,7 @@ sigs.k8s.io/kustomize/kyaml/yaml/internal/k8sgen/pkg/util/validation/field
 sigs.k8s.io/kustomize/kyaml/yaml/merge2
 sigs.k8s.io/kustomize/kyaml/yaml/schema
 sigs.k8s.io/kustomize/kyaml/yaml/walk
-# sigs.k8s.io/lws v0.6.2
+# sigs.k8s.io/lws v0.7.0
 ## explicit; go 1.24.0
 sigs.k8s.io/lws/api/leaderworkerset/scheme
 sigs.k8s.io/lws/api/leaderworkerset/v1
diff --git a/vendor/sigs.k8s.io/lws/api/leaderworkerset/v1/leaderworkerset_types.go b/vendor/sigs.k8s.io/lws/api/leaderworkerset/v1/leaderworkerset_types.go
index ab52599fb..d190ca12f 100644
--- a/vendor/sigs.k8s.io/lws/api/leaderworkerset/v1/leaderworkerset_types.go
+++ b/vendor/sigs.k8s.io/lws/api/leaderworkerset/v1/leaderworkerset_types.go
@@ -248,6 +248,20 @@ const (
 
 // RollingUpdateConfiguration defines the parameters to be used for RollingUpdateStrategyType.
 type RollingUpdateConfiguration struct {
+	// Partition indicates the ordinal at which the lws should be partitioned for updates.
+	// During a rolling update, all the groups from ordinal Partition to Replicas-1 will be updated.
+	// The groups from 0 to Partition-1 will not be updated.
+	// This is helpful in incremental rollout strategies like canary deployments
+	// or interactive rollout strategies for multiple replicas like xPyD deployments.
+	// Once partition field and maxSurge field both set, the bursted replicas will keep remaining
+	// until the rolling update is completely done and the partition field is reset to 0.
+	// This is as expected to reduce the reconciling complexity.
+	// The default value is 0.
+	//
+	// +optional
+	// +kubebuilder:default=0
+	Partition *int32 `json:"partition,omitempty"`
+
 	// The maximum number of replicas that can be unavailable during the update.
 	// Value can be an absolute number (ex: 5) or a percentage of total replicas at the start of update (ex: 10%).
 	// Absolute number is calculated from percentage by rounding down.
@@ -365,6 +379,10 @@ const (
 //+kubebuilder:subresource:status
 //+kubebuilder:subresource:scale:specpath=.spec.replicas,statuspath=.status.replicas,selectorpath=.status.hpaPodSelector
 //+kubebuilder:resource:shortName={lws}
+//+kubebuilder:printcolumn:name="Ready",type="integer",JSONPath=".status.readyReplicas",description="Number of ready replicas"
+//+kubebuilder:printcolumn:name="Desired",type="integer",JSONPath=".spec.replicas",description="Number of desired replicas"
+//+kubebuilder:printcolumn:name="Up-to-date",type="integer",JSONPath=".status.updatedReplicas",description="Number of up-to-date replicas"
+//+kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp"
 
 // LeaderWorkerSet is the Schema for the leaderworkersets API
 type LeaderWorkerSet struct {
diff --git a/vendor/sigs.k8s.io/lws/api/leaderworkerset/v1/zz_generated.deepcopy.go b/vendor/sigs.k8s.io/lws/api/leaderworkerset/v1/zz_generated.deepcopy.go
index eb61e7f99..c3c59865c 100644
--- a/vendor/sigs.k8s.io/lws/api/leaderworkerset/v1/zz_generated.deepcopy.go
+++ b/vendor/sigs.k8s.io/lws/api/leaderworkerset/v1/zz_generated.deepcopy.go
@@ -188,6 +188,11 @@ func (in *NetworkConfig) DeepCopy() *NetworkConfig {
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *RollingUpdateConfiguration) DeepCopyInto(out *RollingUpdateConfiguration) {
 	*out = *in
+	if in.Partition != nil {
+		in, out := &in.Partition, &out.Partition
+		*out = new(int32)
+		**out = **in
+	}
 	out.MaxUnavailable = in.MaxUnavailable
 	out.MaxSurge = in.MaxSurge
 }
@@ -208,7 +213,7 @@ func (in *RolloutStrategy) DeepCopyInto(out *RolloutStrategy) {
 	if in.RollingUpdateConfiguration != nil {
 		in, out := &in.RollingUpdateConfiguration, &out.RollingUpdateConfiguration
 		*out = new(RollingUpdateConfiguration)
-		**out = **in
+		(*in).DeepCopyInto(*out)
 	}
 }
 



Test patch:
diff --git a/pkg/scheduler/scheduler_test.go b/pkg/scheduler/scheduler_test.go
index 626f05d0d..081567486 100644
--- a/pkg/scheduler/scheduler_test.go
+++ b/pkg/scheduler/scheduler_test.go
@@ -9411,3 +9411,292 @@ func TestScheduleForTASCohorts(t *testing.T) {
 		})
 	}
 }
+
+func TestScheduleForAFS(t *testing.T) {
+	afsConfig := &config.AdmissionFairSharing{
+		UsageHalfLifeTime:     metav1.Duration{Duration: 10 * time.Second},
+		UsageSamplingInterval: metav1.Duration{Duration: 1 * time.Second},
+	}
+	now := time.Now()
+	fakeClock := testingclock.NewFakeClock(now)
+	resourceFlavors := []*kueue.ResourceFlavor{
+		utiltesting.MakeResourceFlavor("default").Obj(),
+	}
+	clusterQueues := []kueue.ClusterQueue{
+		*utiltesting.MakeClusterQueue("cq1").
+			ResourceGroup(*utiltesting.MakeFlavorQuotas("default").
+				Resource(corev1.ResourceCPU, "8").
+				Resource(corev1.ResourceMemory, "8Gi").Obj()).
+			AdmissionMode(kueue.UsageBasedAdmissionFairSharing).
+			Obj(),
+	}
+	queues := []kueue.LocalQueue{
+		*utiltesting.MakeLocalQueue("lq-a", "default").
+			FairSharing(&kueue.FairSharing{Weight: ptr.To(resource.MustParse("1"))}).
+			ClusterQueue("cq1").
+			FairSharingStatus(&kueue.FairSharingStatus{
+				WeightedShare: 1,
+				AdmissionFairSharingStatus: &kueue.AdmissionFairSharingStatus{
+					ConsumedResources: corev1.ResourceList{},
+				},
+			}).
+			Obj(),
+		*utiltesting.MakeLocalQueue("lq-b", "default").
+			FairSharing(&kueue.FairSharing{Weight: ptr.To(resource.MustParse("1"))}).
+			ClusterQueue("cq1").
+			FairSharingStatus(&kueue.FairSharingStatus{
+				WeightedShare: 1,
+				AdmissionFairSharingStatus: &kueue.AdmissionFairSharingStatus{
+					ConsumedResources: corev1.ResourceList{},
+				},
+			}).
+			Obj(),
+		*utiltesting.MakeLocalQueue("lq-c", "default").
+			FairSharing(&kueue.FairSharing{Weight: ptr.To(resource.MustParse("1"))}).
+			ClusterQueue("cq1").
+			FairSharingStatus(&kueue.FairSharingStatus{
+				WeightedShare: 1,
+				AdmissionFairSharingStatus: &kueue.AdmissionFairSharingStatus{
+					ConsumedResources: corev1.ResourceList{},
+				},
+			}).
+			Obj(),
+	}
+
+	cases := map[string]struct {
+		enableFairSharing bool
+		initialUsage      map[string]corev1.ResourceList
+		workloads         []kueue.Workload
+		wantAdmissions    map[workload.Reference]kueue.Admission
+		wantPending       []workload.Reference
+	}{
+		"admits workload from less active localqueue": {
+			enableFairSharing: true,
+			initialUsage: map[string]corev1.ResourceList{
+				"lq-a": {corev1.ResourceCPU: resource.MustParse("8")},
+				"lq-b": {corev1.ResourceCPU: resource.MustParse("2")},
+			},
+			workloads: []kueue.Workload{
+				*utiltesting.MakeWorkload("wl-a1", "default").
+					Queue("lq-a").
+					PodSets(*utiltesting.MakePodSet("one", 1).
+						Request(corev1.ResourceCPU, "8").
+						Obj()).
+					Creation(now).
+					Obj(),
+				*utiltesting.MakeWorkload("wl-b1", "default").
+					Queue("lq-b").
+					PodSets(*utiltesting.MakePodSet("one", 1).
+						Request(corev1.ResourceCPU, "8").
+						Obj()).
+					Creation(now.Add(1 * time.Second)).
+					Obj(),
+			},
+			wantAdmissions: map[workload.Reference]kueue.Admission{
+				"default/wl-b1": *utiltesting.MakeAdmission("cq1", "one").Assignment(corev1.ResourceCPU, "default", "8").Obj(),
+			},
+			wantPending: []workload.Reference{
+				"default/wl-a1",
+			},
+		},
+		"without AFS: classic admission decision ignores queue usage": {
+			enableFairSharing: false,
+			initialUsage: map[string]corev1.ResourceList{
+				"lq-a": {corev1.ResourceCPU: resource.MustParse("8")},
+				"lq-b": {corev1.ResourceCPU: resource.MustParse("2")},
+			},
+			workloads: []kueue.Workload{
+				*utiltesting.MakeWorkload("wl-a1", "default").
+					Queue("lq-a").
+					PodSets(*utiltesting.MakePodSet("one", 1).
+						Request(corev1.ResourceCPU, "8").
+						Obj()).
+					Creation(now).
+					Obj(),
+				*utiltesting.MakeWorkload("wl-b1", "default").
+					Queue("lq-b").
+					PodSets(*utiltesting.MakePodSet("one", 1).
+						Request(corev1.ResourceCPU, "8").
+						Obj()).
+					Creation(now.Add(1 * time.Second)).
+					Obj(),
+			},
+			wantAdmissions: map[workload.Reference]kueue.Admission{
+				"default/wl-a1": *utiltesting.MakeAdmission("cq1", "one").Assignment(corev1.ResourceCPU, "default", "8").Obj(),
+			},
+			wantPending: []workload.Reference{
+				"default/wl-b1",
+			},
+		},
+		"admits one workload from each localqueue when quota is limited": {
+			enableFairSharing: true,
+			initialUsage: map[string]corev1.ResourceList{
+				"lq-a": {corev1.ResourceCPU: resource.MustParse("4")},
+				"lq-b": {corev1.ResourceCPU: resource.MustParse("4")},
+			},
+			workloads: []kueue.Workload{
+				*utiltesting.MakeWorkload("wl-a1", "default").
+					Queue("lq-a").
+					PodSets(*utiltesting.MakePodSet("one", 1).
+						Request(corev1.ResourceCPU, "4").
+						Obj()).
+					Creation(now).
+					Obj(),
+				*utiltesting.MakeWorkload("wl-a2", "default").
+					Queue("lq-a").
+					PodSets(*utiltesting.MakePodSet("one", 1).
+						Request(corev1.ResourceCPU, "4").
+						Obj()).
+					Creation(now.Add(1 * time.Second)).
+					Obj(),
+				*utiltesting.MakeWorkload("wl-b1", "default").
+					Queue("lq-b").
+					PodSets(*utiltesting.MakePodSet("one", 1).
+						Request(corev1.ResourceCPU, "4").
+						Obj()).
+					Creation(now.Add(2 * time.Second)).
+					Obj(),
+				*utiltesting.MakeWorkload("wl-b2", "default").
+					Queue("lq-b").
+					PodSets(*utiltesting.MakePodSet("one", 1).
+						Request(corev1.ResourceCPU, "4").
+						Obj()).
+					Creation(now.Add(3 * time.Second)).
+					Obj(),
+			},
+			wantAdmissions: map[workload.Reference]kueue.Admission{
+				"default/wl-a1": *utiltesting.MakeAdmission("cq1", "one").Assignment(corev1.ResourceCPU, "default", "4").Obj(),
+				"default/wl-b1": *utiltesting.MakeAdmission("cq1", "one").Assignment(corev1.ResourceCPU, "default", "4").Obj(),
+			},
+			wantPending: []workload.Reference{
+				"default/wl-a2",
+				"default/wl-b2",
+			},
+		},
+		"schedules normally when queues have equal usage": {
+			enableFairSharing: true,
+			initialUsage: map[string]corev1.ResourceList{
+				"lq-a": {corev1.ResourceCPU: resource.MustParse("2")},
+				"lq-b": {corev1.ResourceCPU: resource.MustParse("2")},
+				"lq-c": {corev1.ResourceCPU: resource.MustParse("2")},
+			},
+			workloads: []kueue.Workload{
+				*utiltesting.MakeWorkload("wl-a1", "default").
+					Queue("lq-a").
+					PodSets(*utiltesting.MakePodSet("one", 1).
+						Request(corev1.ResourceCPU, "4").
+						Obj()).
+					Obj(),
+				*utiltesting.MakeWorkload("wl-b1", "default").
+					Queue("lq-b").
+					PodSets(*utiltesting.MakePodSet("one", 1).
+						Request(corev1.ResourceCPU, "3").
+						Obj()).
+					Obj(),
+				*utiltesting.MakeWorkload("wl-c1", "default").
+					Queue("lq-c").
+					PodSets(*utiltesting.MakePodSet("one", 1).
+						Request(corev1.ResourceCPU, "1").
+						Obj()).
+					Obj(),
+			},
+			wantAdmissions: map[workload.Reference]kueue.Admission{
+				"default/wl-a1": *utiltesting.MakeAdmission("cq1", "one").Assignment(corev1.ResourceCPU, "default", "4").Obj(),
+				"default/wl-b1": *utiltesting.MakeAdmission("cq1", "one").Assignment(corev1.ResourceCPU, "default", "3").Obj(),
+				"default/wl-c1": *utiltesting.MakeAdmission("cq1", "one").Assignment(corev1.ResourceCPU, "default", "1").Obj(),
+			},
+			wantPending: []workload.Reference{},
+		},
+	}
+
+	for name, tc := range cases {
+		t.Run(name, func(t *testing.T) {
+			if tc.enableFairSharing {
+				features.SetFeatureGateDuringTest(t, features.AdmissionFairSharing, true)
+			}
+
+			for i, q := range queues {
+				if resList, found := tc.initialUsage[q.Name]; found {
+					queues[i].Status.FairSharing.AdmissionFairSharingStatus.ConsumedResources = resList
+				}
+			}
+
+			clientBuilder := utiltesting.NewClientBuilder().
+				WithLists(
+					&kueue.WorkloadList{Items: tc.workloads},
+					&kueue.ClusterQueueList{Items: clusterQueues},
+					&kueue.LocalQueueList{Items: queues}).
+				WithObjects(
+					utiltesting.MakeNamespace("default"),
+				)
+			cl := clientBuilder.Build()
+
+			fairSharing := &config.FairSharing{
+				Enable: tc.enableFairSharing,
+			}
+			cqCache := cache.New(cl, cache.WithFairSharing(fairSharing.Enable), cache.WithAdmissionFairSharing(afsConfig))
+			qManager := queue.NewManager(cl, cqCache, queue.WithAdmissionFairSharing(afsConfig))
+
+			ctx, log := utiltesting.ContextWithLog(t)
+			for _, q := range queues {
+				if err := qManager.AddLocalQueue(ctx, &q); err != nil {
+					t.Fatalf("Inserting queue %s/%s in manager: %v", q.Namespace, q.Name, err)
+				}
+			}
+			for _, rf := range resourceFlavors {
+				cqCache.AddOrUpdateResourceFlavor(log, rf)
+			}
+			for _, cq := range clusterQueues {
+				if err := cqCache.AddClusterQueue(ctx, &cq); err != nil {
+					t.Fatalf("Inserting clusterQueue %s in cache: %v", cq.Name, err)
+				}
+				if err := qManager.AddClusterQueue(ctx, &cq); err != nil {
+					t.Fatalf("Inserting clusterQueue %s in manager: %v", cq.Name, err)
+				}
+			}
+			recorder := &utiltesting.EventRecorder{}
+			scheduler := New(qManager, cqCache, cl, recorder,
+				WithFairSharing(fairSharing),
+				WithAdmissionFairSharing(afsConfig),
+				WithClock(t, fakeClock))
+			wg := sync.WaitGroup{}
+			scheduler.setAdmissionRoutineWrapper(routine.NewWrapper(
+				func() { wg.Add(1) },
+				func() { wg.Done() },
+			))
+
+			gotScheduled := make(map[workload.Reference]kueue.Admission)
+			var mu sync.Mutex
+			scheduler.applyAdmission = func(ctx context.Context, w *kueue.Workload) error {
+				mu.Lock()
+				gotScheduled[workload.Key(w)] = *w.Status.Admission
+				mu.Unlock()
+				return nil
+			}
+
+			ctx, cancel := context.WithTimeout(ctx, queueingTimeout)
+			go qManager.CleanUpOnContext(ctx)
+			defer cancel()
+
+			for range len(tc.workloads) {
+				scheduler.schedule(ctx)
+				wg.Wait()
+			}
+
+			if diff := cmp.Diff(tc.wantAdmissions, gotScheduled); diff != "" {
+				t.Errorf("Unexpected scheduled workloads (-want,+got):\n%s", diff)
+			}
+
+			gotPending := make([]workload.Reference, 0)
+			for _, wl := range tc.workloads {
+				wlKey := workload.Key(&wl)
+				if _, scheduled := gotScheduled[wlKey]; !scheduled {
+					gotPending = append(gotPending, wlKey)
+				}
+			}
+			if diff := cmp.Diff(tc.wantPending, gotPending); diff != "" {
+				t.Errorf("Unexpected pending workloads (-want,+got):\n%s", diff)
+			}
+		})
+	}
+}
diff --git a/pkg/workloadslicing/workloadslicing_test.go b/pkg/workloadslicing/workloadslicing_test.go
index 1c8f596fd..7f8b03521 100644
--- a/pkg/workloadslicing/workloadslicing_test.go
+++ b/pkg/workloadslicing/workloadslicing_test.go
@@ -772,7 +772,7 @@ func TestEnsureWorkloadSlices(t *testing.T) {
 				compatible: true,
 			},
 		},
-		"TwoWorkloadSlices_NewIsIncompatible": {
+		"TwoWorkloads_NewIsIncompatible": {
 			args: args{
 				ctx: t.Context(),
 				clnt: testWorkloadClientBuilder().WithObjects(
@@ -823,6 +823,34 @@ func TestEnsureWorkloadSlices(t *testing.T) {
 				compatible: true,
 			},
 		},
+		"TwoWorkloads_OldWithReservedQuotaAndEvicted_NewWithoutQuotaReservation": {
+			args: args{
+				ctx: t.Context(),
+				clnt: testWorkloadClientBuilder().WithObjects(
+					utiltesting.MakeWorkload(testJobObject.Name+"-1", testJobObject.Namespace).
+						OwnerReference(testJobGVK, testJobObject.Name, string(testJobObject.UID)).
+						ResourceVersion("1").
+						Creation(fiveMinutesAgo).
+						PodSets(*utiltesting.MakePodSet(kueue.DefaultPodSetName, 1).Request(corev1.ResourceCPU, "1").Obj()).
+						ReserveQuota(utiltesting.MakeAdmission("default", kueue.DefaultPodSetName).Assignment(corev1.ResourceCPU, "default", "1").AssignmentPodCount(1).Obj()).
+						Evicted().
+						Obj(),
+					utiltesting.MakeWorkload(testJobObject.Name+"-2", testJobObject.Namespace).
+						OwnerReference(testJobGVK, testJobObject.Name, string(testJobObject.UID)).
+						ResourceVersion("1").
+						Creation(now).
+						PodSets(*utiltesting.MakePodSet(kueue.DefaultPodSetName, 3).Request(corev1.ResourceCPU, "1").Obj()).
+						Obj()).
+					Build(),
+				jobPodSets:   []kueue.PodSet{*utiltesting.MakePodSet(kueue.DefaultPodSetName, 5).Request(corev1.ResourceCPU, "1").Obj()},
+				jobObject:    testJobObject,
+				jobObjectGVK: testJobGVK,
+			},
+			want: want{
+				error:      true,
+				compatible: true,
+			},
+		},
 		"TwoWorkloadSlices_NewIsUnreservedAndCurrent": {
 			args: args{
 				ctx: t.Context(),
diff --git a/test/e2e/kueueviz/package-lock.json b/test/e2e/kueueviz/package-lock.json
index a0f2d12f5..f99adb7c1 100644
--- a/test/e2e/kueueviz/package-lock.json
+++ b/test/e2e/kueueviz/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "kueueviz-frontend-tests",
-  "version": "0.13.1",
+  "version": "0.13.2",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
       "name": "kueueviz-frontend-tests",
-      "version": "0.13.1",
+      "version": "0.13.2",
       "devDependencies": {
         "@testing-library/cypress": "^10.0.3",
         "cypress": "^14.5.3",
diff --git a/test/e2e/kueueviz/package.json b/test/e2e/kueueviz/package.json
index dbddcf09e..f65afe4b3 100644
--- a/test/e2e/kueueviz/package.json
+++ b/test/e2e/kueueviz/package.json
@@ -1,6 +1,6 @@
 {
   "name": "kueueviz-frontend-tests",
-  "version": "0.13.1",
+  "version": "0.13.2",
   "scripts": {
     "cypress:run": "cypress run --headless",
     "check-unused": "depcheck"
diff --git a/test/e2e/multikueue/e2e_test.go b/test/e2e/multikueue/e2e_test.go
index f85e849c4..bbf55466c 100644
--- a/test/e2e/multikueue/e2e_test.go
+++ b/test/e2e/multikueue/e2e_test.go
@@ -171,11 +171,11 @@ var _ = ginkgo.Describe("MultiKueue", func() {
 		gomega.Expect(util.DeleteNamespace(ctx, k8sWorker1Client, worker1Ns)).To(gomega.Succeed())
 		gomega.Expect(util.DeleteNamespace(ctx, k8sWorker2Client, worker2Ns)).To(gomega.Succeed())
 
-		util.ExpectObjectToBeDeleted(ctx, k8sWorker1Client, worker1Cq, true)
-		util.ExpectObjectToBeDeleted(ctx, k8sWorker1Client, worker1Flavor, true)
+		util.ExpectObjectToBeDeletedWithTimeout(ctx, k8sWorker1Client, worker1Cq, true, util.LongTimeout)
+		util.ExpectObjectToBeDeletedWithTimeout(ctx, k8sWorker1Client, worker1Flavor, true, util.LongTimeout)
 
-		util.ExpectObjectToBeDeleted(ctx, k8sWorker2Client, worker2Cq, true)
-		util.ExpectObjectToBeDeleted(ctx, k8sWorker2Client, worker2Flavor, true)
+		util.ExpectObjectToBeDeletedWithTimeout(ctx, k8sWorker2Client, worker2Cq, true, util.LongTimeout)
+		util.ExpectObjectToBeDeletedWithTimeout(ctx, k8sWorker2Client, worker2Flavor, true, util.LongTimeout)
 
 		util.ExpectObjectToBeDeletedWithTimeout(ctx, k8sManagerClient, managerCq, true, util.LongTimeout)
 		util.ExpectObjectToBeDeletedWithTimeout(ctx, k8sManagerClient, managerFlavor, true, util.LongTimeout)
@@ -898,17 +898,9 @@ var _ = ginkgo.Describe("MultiKueue", func() {
 			createdLeaderWorkload := &kueue.Workload{}
 			wlLookupKey := types.NamespacedName{Name: workloadjob.GetWorkloadNameForJob(job.Name, job.UID), Namespace: managerNs.Name}
 			// the execution should be given to the worker
-			ginkgo.By("Waiting to be admitted in worker2, and the manager's job unsuspended", func() {
-				gomega.Eventually(func(g gomega.Gomega) {
-					g.Expect(k8sManagerClient.Get(ctx, wlLookupKey, createdLeaderWorkload)).To(gomega.Succeed())
-					g.Expect(workload.FindAdmissionCheck(createdLeaderWorkload.Status.AdmissionChecks, kueue.AdmissionCheckReference(multiKueueAc.Name))).To(gomega.BeComparableTo(&kueue.AdmissionCheckState{
-						Name:    kueue.AdmissionCheckReference(multiKueueAc.Name),
-						State:   kueue.CheckStateReady,
-						Message: `The workload got reservation on "worker2"`,
-					}, cmpopts.IgnoreFields(kueue.AdmissionCheckState{}, "LastTransitionTime")))
-					g.Expect(ptr.Deref(createdLeaderWorkload.Status.ClusterName, "")).To(gomega.Equal(workerCluster2.Name))
-				}, util.Timeout, util.Interval).Should(gomega.Succeed())
+			waitForJobAdmitted(wlLookupKey, multiKueueAc.Name, "worker2")
 
+			ginkgo.By("Waiting for the manager's job unsuspended", func() {
 				gomega.Eventually(func(g gomega.Gomega) {
 					createdJob := &batchv1.Job{}
 					g.Expect(k8sManagerClient.Get(ctx, client.ObjectKeyFromObject(job), createdJob)).To(gomega.Succeed())
diff --git a/test/integration/singlecluster/controller/jobs/job/job_controller_test.go b/test/integration/singlecluster/controller/jobs/job/job_controller_test.go
index 632b9545d..bcf154db5 100644
--- a/test/integration/singlecluster/controller/jobs/job/job_controller_test.go
+++ b/test/integration/singlecluster/controller/jobs/job/job_controller_test.go
@@ -19,6 +19,7 @@ package job
 import (
 	"fmt"
 	"maps"
+	"strconv"
 	"time"
 
 	"github.com/google/go-cmp/cmp/cmpopts"
@@ -3095,6 +3096,7 @@ var _ = ginkgo.Describe("Job with elastic jobs via workload-slices support", gin
 		clusterQueue   *kueue.ClusterQueue
 		localQueue     *kueue.LocalQueue
 	)
+	cpuNominalQuota := 5
 
 	ginkgo.BeforeAll(func() {
 		gomega.Expect(utilfeature.DefaultMutableFeatureGate.SetFromMap(map[string]bool{string(features.ElasticJobsViaWorkloadSlices): true})).Should(gomega.Succeed())
@@ -3111,14 +3113,16 @@ var _ = ginkgo.Describe("Job with elastic jobs via workload-slices support", gin
 		util.MustCreate(ctx, k8sClient, resourceFlavor)
 
 		clusterQueue = testing.MakeClusterQueue("default").
-			ResourceGroup(*testing.MakeFlavorQuotas("default").Resource(corev1.ResourceCPU, "5").Obj()).
+			ResourceGroup(*testing.MakeFlavorQuotas(resourceFlavor.Name).Resource(corev1.ResourceCPU, strconv.Itoa(cpuNominalQuota)).Obj()).
+			Preemption(kueue.ClusterQueuePreemption{
+				WithinClusterQueue: kueue.PreemptionPolicyLowerPriority,
+			}).
 			Obj()
 		util.MustCreate(ctx, k8sClient, clusterQueue)
 
 		localQueue = testing.MakeLocalQueue("default", ns.Name).ClusterQueue(clusterQueue.Name).Obj()
 		util.MustCreate(ctx, k8sClient, localQueue)
 	})
-
 	ginkgo.AfterEach(func() {
 		gomega.Expect(util.DeleteNamespace(ctx, k8sClient, ns)).To(gomega.Succeed())
 		util.ExpectObjectToBeDeleted(ctx, k8sClient, clusterQueue, true)
@@ -3126,180 +3130,249 @@ var _ = ginkgo.Describe("Job with elastic jobs via workload-slices support", gin
 		util.ExpectObjectToBeDeleted(ctx, k8sClient, resourceFlavor, true)
 	})
 
-	ginkgo.When("ElasticJobsViaWorkloadSlices is enabled", func() {
-		ginkgo.When("Job is opted in", func() {
-			ginkgo.It("Should support job scale-down and scale-up", func() {
-				testJob := testingjob.MakeJob("job1", ns.Name).
-					SetAnnotation(workloadslicing.EnabledAnnotationKey, workloadslicing.EnabledAnnotationValue).
-					Queue(kueue.LocalQueueName(localQueue.Name)).
-					Request(corev1.ResourceCPU, "100m").
-					Parallelism(3).
-					Completions(3).
-					Obj()
+	ginkgo.It("Should support job scale-down and scale-up", func() {
+		testJob := testingjob.MakeJob("job1", ns.Name).
+			SetAnnotation(workloadslicing.EnabledAnnotationKey, workloadslicing.EnabledAnnotationValue).
+			Queue(kueue.LocalQueueName(localQueue.Name)).
+			Request(corev1.ResourceCPU, "100m").
+			Parallelism(3).
+			Completions(3).
+			Obj()
 
-				var testJobWorkload *kueue.Workload
+		var testJobWorkload *kueue.Workload
 
-				ginkgo.By("creating a job")
-				util.MustCreate(ctx, k8sClient, testJob)
+		ginkgo.By("creating a job")
+		util.MustCreate(ctx, k8sClient, testJob)
 
-				ginkgo.By("admitting the job's workload")
-				gomega.Eventually(func(g gomega.Gomega) {
-					workloads := &kueue.WorkloadList{}
-					g.Expect(k8sClient.List(ctx, workloads, client.InNamespace(testJob.Namespace))).Should(gomega.Succeed())
-					g.Expect(workloads.Items).Should(gomega.HaveLen(1))
-					testJobWorkload = &workloads.Items[0]
-					util.ExpectWorkloadsToBeAdmitted(ctx, k8sClient, testJobWorkload)
-				}, util.Timeout, util.Interval).Should(gomega.Succeed())
+		ginkgo.By("admitting the job's workload")
+		gomega.Eventually(func(g gomega.Gomega) {
+			workloads := &kueue.WorkloadList{}
+			g.Expect(k8sClient.List(ctx, workloads, client.InNamespace(testJob.Namespace))).Should(gomega.Succeed())
+			g.Expect(workloads.Items).Should(gomega.HaveLen(1))
+			testJobWorkload = &workloads.Items[0]
+			util.ExpectWorkloadsToBeAdmitted(ctx, k8sClient, testJobWorkload)
+		}, util.Timeout, util.Interval).Should(gomega.Succeed())
 
-				ginkgo.By("the job is unsuspended")
-				gomega.Eventually(func(g gomega.Gomega) {
-					g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(testJob), testJob)).Should(gomega.Succeed())
-					g.Expect(ptr.Deref(testJob.Spec.Suspend, false)).Should(gomega.BeFalse())
-				}, util.Timeout, util.Interval).Should(gomega.Succeed())
+		ginkgo.By("the job is unsuspended")
+		gomega.Eventually(func(g gomega.Gomega) {
+			g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(testJob), testJob)).Should(gomega.Succeed())
+			g.Expect(ptr.Deref(testJob.Spec.Suspend, false)).Should(gomega.BeFalse())
+		}, util.Timeout, util.Interval).Should(gomega.Succeed())
 
-				ginkgo.By("resource flavor utilization is correctly recorded")
-				gomega.Eventually(func(g gomega.Gomega) {
-					cq := &kueue.ClusterQueue{}
-					g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(clusterQueue), cq)).Should(gomega.Succeed())
-					g.Expect(len(cq.Status.FlavorsUsage)).Should(gomega.BeEquivalentTo(1))
-					g.Expect(len(cq.Status.FlavorsUsage[0].Resources)).Should(gomega.BeEquivalentTo(1))
-					g.Expect(cq.Status.FlavorsUsage[0].Resources[0].Total).Should(gomega.BeEquivalentTo(resource.MustParse("300m")))
-				}, util.Timeout, util.Interval).Should(gomega.Succeed())
+		ginkgo.By("resource flavor utilization is correctly recorded")
+		gomega.Eventually(func(g gomega.Gomega) {
+			cq := &kueue.ClusterQueue{}
+			g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(clusterQueue), cq)).Should(gomega.Succeed())
+			g.Expect(len(cq.Status.FlavorsUsage)).Should(gomega.BeEquivalentTo(1))
+			g.Expect(len(cq.Status.FlavorsUsage[0].Resources)).Should(gomega.BeEquivalentTo(1))
+			g.Expect(cq.Status.FlavorsUsage[0].Resources[0].Total).Should(gomega.BeEquivalentTo(resource.MustParse("300m")))
+		}, util.Timeout, util.Interval).Should(gomega.Succeed())
 
-				ginkgo.By("reducing the job's parallelism to emulate scale-down operation")
-				gomega.Eventually(func(g gomega.Gomega) {
-					testJob.Spec.Parallelism = ptr.To(int32(1))
-					g.Expect(k8sClient.Update(ctx, testJob)).Should(gomega.Succeed())
-				}, util.Timeout, util.Interval).Should(gomega.Succeed())
+		ginkgo.By("reducing the job's parallelism to emulate scale-down operation")
+		gomega.Eventually(func(g gomega.Gomega) {
+			testJob.Spec.Parallelism = ptr.To(int32(1))
+			g.Expect(k8sClient.Update(ctx, testJob)).Should(gomega.Succeed())
+		}, util.Timeout, util.Interval).Should(gomega.Succeed())
 
-				ginkgo.By("resource flavor utilization is correctly updated")
-				gomega.Eventually(func(g gomega.Gomega) {
-					cq := &kueue.ClusterQueue{}
-					g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(clusterQueue), cq)).Should(gomega.Succeed())
-					g.Expect(len(cq.Status.FlavorsUsage)).Should(gomega.BeEquivalentTo(1))
-					g.Expect(len(cq.Status.FlavorsUsage[0].Resources)).Should(gomega.BeEquivalentTo(1))
-					g.Expect(cq.Status.FlavorsUsage[0].Resources[0].Total).Should(gomega.BeEquivalentTo(resource.MustParse("100m")))
-				}, util.Timeout, util.Interval).Should(gomega.Succeed())
+		ginkgo.By("resource flavor utilization is correctly updated")
+		gomega.Eventually(func(g gomega.Gomega) {
+			cq := &kueue.ClusterQueue{}
+			g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(clusterQueue), cq)).Should(gomega.Succeed())
+			g.Expect(len(cq.Status.FlavorsUsage)).Should(gomega.BeEquivalentTo(1))
+			g.Expect(len(cq.Status.FlavorsUsage[0].Resources)).Should(gomega.BeEquivalentTo(1))
+			g.Expect(cq.Status.FlavorsUsage[0].Resources[0].Total).Should(gomega.BeEquivalentTo(resource.MustParse("100m")))
+		}, util.Timeout, util.Interval).Should(gomega.Succeed())
 
-				ginkgo.By("assert the job's workload is updated and still admitted")
-				gomega.Eventually(func(g gomega.Gomega) {
-					workloads := &kueue.WorkloadList{}
-					g.Expect(k8sClient.List(ctx, workloads, client.InNamespace(testJob.Namespace))).Should(gomega.Succeed())
-					g.Expect(workloads.Items).Should(gomega.HaveLen(1))
-					util.ExpectWorkloadsToBeAdmitted(ctx, k8sClient, testJobWorkload)
-					g.Expect(workloads.Items[0].Spec.PodSets[0].Count).Should(gomega.BeEquivalentTo(int32(1)))
-					g.Expect(workloads.Items[0].UID).Should(gomega.BeEquivalentTo(testJobWorkload.UID))
-					testJobWorkload = &workloads.Items[0]
-				}, util.Timeout, util.Interval).Should(gomega.Succeed())
+		ginkgo.By("assert the job's workload is updated and still admitted")
+		gomega.Eventually(func(g gomega.Gomega) {
+			workloads := &kueue.WorkloadList{}
+			g.Expect(k8sClient.List(ctx, workloads, client.InNamespace(testJob.Namespace))).Should(gomega.Succeed())
+			g.Expect(workloads.Items).Should(gomega.HaveLen(1))
+			util.ExpectWorkloadsToBeAdmitted(ctx, k8sClient, testJobWorkload)
+			g.Expect(workloads.Items[0].Spec.PodSets[0].Count).Should(gomega.BeEquivalentTo(int32(1)))
+			g.Expect(workloads.Items[0].UID).Should(gomega.BeEquivalentTo(testJobWorkload.UID))
+			testJobWorkload = &workloads.Items[0]
+		}, util.Timeout, util.Interval).Should(gomega.Succeed())
 
-				ginkgo.By("increasing the job's parallelism to emulate scale-up operation")
-				gomega.Eventually(func(g gomega.Gomega) {
-					g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(testJob), testJob)).Should(gomega.Succeed())
-					testJob.Spec.Parallelism = ptr.To(int32(2))
-					g.Expect(k8sClient.Update(ctx, testJob)).Should(gomega.Succeed())
-				}, util.Timeout, util.Interval).Should(gomega.Succeed())
+		ginkgo.By("increasing the job's parallelism to emulate scale-up operation")
+		gomega.Eventually(func(g gomega.Gomega) {
+			g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(testJob), testJob)).Should(gomega.Succeed())
+			testJob.Spec.Parallelism = ptr.To(int32(2))
+			g.Expect(k8sClient.Update(ctx, testJob)).Should(gomega.Succeed())
+		}, util.Timeout, util.Interval).Should(gomega.Succeed())
 
-				ginkgo.By("resource flavor utilization is correctly updated")
-				gomega.Eventually(func(g gomega.Gomega) {
-					cq := &kueue.ClusterQueue{}
-					g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(clusterQueue), cq)).Should(gomega.Succeed())
-					g.Expect(len(cq.Status.FlavorsUsage)).Should(gomega.BeEquivalentTo(1))
-					g.Expect(len(cq.Status.FlavorsUsage[0].Resources)).Should(gomega.BeEquivalentTo(1))
-					g.Expect(cq.Status.FlavorsUsage[0].Resources[0].Total).Should(gomega.BeEquivalentTo(resource.MustParse("200m")))
-				}, util.Timeout, util.Interval).Should(gomega.Succeed())
+		ginkgo.By("resource flavor utilization is correctly updated")
+		gomega.Eventually(func(g gomega.Gomega) {
+			cq := &kueue.ClusterQueue{}
+			g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(clusterQueue), cq)).Should(gomega.Succeed())
+			g.Expect(len(cq.Status.FlavorsUsage)).Should(gomega.BeEquivalentTo(1))
+			g.Expect(len(cq.Status.FlavorsUsage[0].Resources)).Should(gomega.BeEquivalentTo(1))
+			g.Expect(cq.Status.FlavorsUsage[0].Resources[0].Total).Should(gomega.BeEquivalentTo(resource.MustParse("200m")))
+		}, util.Timeout, util.Interval).Should(gomega.Succeed())
 
-				ginkgo.By("old workload is finished and new workload is admitted")
-				gomega.Eventually(func(g gomega.Gomega) {
-					workloads := &kueue.WorkloadList{}
-					g.Expect(k8sClient.List(ctx, workloads, client.InNamespace(testJob.Namespace))).Should(gomega.Succeed())
-					g.Expect(workloads.Items).Should(gomega.HaveLen(2))
-					for i := range workloads.Items {
-						if workloads.Items[i].Name == testJobWorkload.Name {
-							g.Expect(workload.IsFinished(&workloads.Items[i])).Should(gomega.BeTrue())
-							continue
-						}
-						testJobWorkload = &workloads.Items[i]
-						util.ExpectWorkloadsToBeAdmitted(ctx, k8sClient, testJobWorkload)
-					}
-				}, util.Timeout, util.Interval).Should(gomega.Succeed())
-			})
+		ginkgo.By("old workload is finished and new workload is admitted")
+		gomega.Eventually(func(g gomega.Gomega) {
+			workloads := &kueue.WorkloadList{}
+			g.Expect(k8sClient.List(ctx, workloads, client.InNamespace(testJob.Namespace))).Should(gomega.Succeed())
+			g.Expect(workloads.Items).Should(gomega.HaveLen(2))
+			for i := range workloads.Items {
+				if workloads.Items[i].Name == testJobWorkload.Name {
+					g.Expect(workload.IsFinished(&workloads.Items[i])).Should(gomega.BeTrue())
+					continue
+				}
+				testJobWorkload = &workloads.Items[i]
+				util.ExpectWorkloadsToBeAdmitted(ctx, k8sClient, testJobWorkload)
+			}
+		}, util.Timeout, util.Interval).Should(gomega.Succeed())
+	})
 
-			ginkgo.It("Should support scheduling pending workload after freeing capacity on scale-down", func() {
-				var (
-					testJobAWorkload *kueue.Workload
-					testJobBWorkload *kueue.Workload
-				)
-
-				testJobA := testingjob.MakeJob("job-a", ns.Name).
-					SetAnnotation(workloadslicing.EnabledAnnotationKey, workloadslicing.EnabledAnnotationValue).
-					Queue(kueue.LocalQueueName(localQueue.Name)).
-					Request(corev1.ResourceCPU, "1").
-					Parallelism(3).
-					Completions(3).
-					Obj()
+	ginkgo.It("Should support scheduling pending workload after freeing capacity on scale-down", func() {
+		var (
+			testJobAWorkload *kueue.Workload
+			testJobBWorkload *kueue.Workload
+		)
 
-				ginkgo.By("creating a job-a")
-				util.MustCreate(ctx, k8sClient, testJobA)
+		testJobA := testingjob.MakeJob("job-a", ns.Name).
+			SetAnnotation(workloadslicing.EnabledAnnotationKey, workloadslicing.EnabledAnnotationValue).
+			Queue(kueue.LocalQueueName(localQueue.Name)).
+			Request(corev1.ResourceCPU, "1").
+			Parallelism(3).
+			Completions(3).
+			Obj()
 
-				ginkgo.By("admitting the job-a's workload")
-				gomega.Eventually(func(g gomega.Gomega) {
-					workloads := &kueue.WorkloadList{}
-					g.Expect(k8sClient.List(ctx, workloads, client.InNamespace(testJobA.Namespace))).Should(gomega.Succeed())
-					g.Expect(workloads.Items).Should(gomega.HaveLen(1))
-					testJobAWorkload = &workloads.Items[0]
-					util.ExpectWorkloadsToBeAdmitted(ctx, k8sClient, testJobAWorkload)
-				}, util.Timeout, util.Interval).Should(gomega.Succeed())
+		ginkgo.By("creating a job-a")
+		util.MustCreate(ctx, k8sClient, testJobA)
 
-				ginkgo.By("the job-a is unsuspended")
-				gomega.Eventually(func(g gomega.Gomega) {
-					g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(testJobA), testJobA)).Should(gomega.Succeed())
-					g.Expect(ptr.Deref(testJobA.Spec.Suspend, false)).Should(gomega.BeFalse())
-				}, util.Timeout, util.Interval).Should(gomega.Succeed())
+		ginkgo.By("admitting the job-a's workload")
+		gomega.Eventually(func(g gomega.Gomega) {
+			workloads := &kueue.WorkloadList{}
+			g.Expect(k8sClient.List(ctx, workloads, client.InNamespace(testJobA.Namespace))).Should(gomega.Succeed())
+			g.Expect(workloads.Items).Should(gomega.HaveLen(1))
+			testJobAWorkload = &workloads.Items[0]
+			util.ExpectWorkloadsToBeAdmitted(ctx, k8sClient, testJobAWorkload)
+		}, util.Timeout, util.Interval).Should(gomega.Succeed())
 
-				testJobB := testingjob.MakeJob("job-b", ns.Name).
-					SetAnnotation(workloadslicing.EnabledAnnotationKey, workloadslicing.EnabledAnnotationValue).
-					Queue(kueue.LocalQueueName(localQueue.Name)).
-					Request(corev1.ResourceCPU, "1").
-					Parallelism(3).
-					Completions(3).
-					Obj()
+		ginkgo.By("the job-a is unsuspended")
+		gomega.Eventually(func(g gomega.Gomega) {
+			g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(testJobA), testJobA)).Should(gomega.Succeed())
+			g.Expect(ptr.Deref(testJobA.Spec.Suspend, false)).Should(gomega.BeFalse())
+		}, util.Timeout, util.Interval).Should(gomega.Succeed())
 
-				ginkgo.By("creating a job-b")
-				util.MustCreate(ctx, k8sClient, testJobB)
+		testJobB := testingjob.MakeJob("job-b", ns.Name).
+			SetAnnotation(workloadslicing.EnabledAnnotationKey, workloadslicing.EnabledAnnotationValue).
+			Queue(kueue.LocalQueueName(localQueue.Name)).
+			Request(corev1.ResourceCPU, "1").
+			Parallelism(3).
+			Completions(3).
+			Obj()
 
-				ginkgo.By("the job-b remains suspended")
-				gomega.Eventually(func(g gomega.Gomega) {
-					g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(testJobB), testJobB)).Should(gomega.Succeed())
-					g.Expect(ptr.Deref(testJobB.Spec.Suspend, false)).Should(gomega.BeTrue())
-				}, util.Timeout, util.Interval).Should(gomega.Succeed())
+		ginkgo.By("creating a job-b")
+		util.MustCreate(ctx, k8sClient, testJobB)
 
-				ginkgo.By("job-b's workload remains pending with unreserved quota")
-				gomega.Eventually(func(g gomega.Gomega) {
-					workloads := &kueue.WorkloadList{}
-					g.Expect(k8sClient.List(ctx, workloads, client.InNamespace(testJobA.Namespace), client.MatchingLabels{constants.JobUIDLabel: string(testJobB.UID)})).Should(gomega.Succeed())
-					g.Expect(workloads.Items).Should(gomega.HaveLen(1))
-					testJobBWorkload = &workloads.Items[0]
-					util.ExpectWorkloadsToBePending(ctx, k8sClient, testJobBWorkload)
-				}, util.Timeout, util.Interval).Should(gomega.Succeed())
+		ginkgo.By("the job-b remains suspended")
+		gomega.Eventually(func(g gomega.Gomega) {
+			g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(testJobB), testJobB)).Should(gomega.Succeed())
+			g.Expect(ptr.Deref(testJobB.Spec.Suspend, false)).Should(gomega.BeTrue())
+		}, util.Timeout, util.Interval).Should(gomega.Succeed())
 
-				ginkgo.By("scale-down job-a to make room for job-b")
-				gomega.Eventually(func(g gomega.Gomega) {
-					testJobA.Spec.Parallelism = ptr.To(int32(1))
-					g.Expect(k8sClient.Update(ctx, testJobA)).Should(gomega.Succeed())
-				}, util.Timeout, util.Interval).Should(gomega.Succeed())
+		ginkgo.By("job-b's workload remains pending with unreserved quota")
+		gomega.Eventually(func(g gomega.Gomega) {
+			workloads := &kueue.WorkloadList{}
+			g.Expect(k8sClient.List(ctx, workloads, client.InNamespace(testJobA.Namespace), client.MatchingLabels{constants.JobUIDLabel: string(testJobB.UID)})).Should(gomega.Succeed())
+			g.Expect(workloads.Items).Should(gomega.HaveLen(1))
+			testJobBWorkload = &workloads.Items[0]
+			util.ExpectWorkloadsToBePending(ctx, k8sClient, testJobBWorkload)
+		}, util.Timeout, util.Interval).Should(gomega.Succeed())
 
-				ginkgo.By("admitting the job-b workload")
-				gomega.Eventually(func(g gomega.Gomega) {
-					g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(testJobBWorkload), testJobBWorkload)).Should(gomega.Succeed())
-					util.ExpectWorkloadsToBeAdmitted(ctx, k8sClient, testJobBWorkload)
-				}, util.Timeout, util.Interval).Should(gomega.Succeed())
+		ginkgo.By("scale-down job-a to make room for job-b")
+		gomega.Eventually(func(g gomega.Gomega) {
+			testJobA.Spec.Parallelism = ptr.To(int32(1))
+			g.Expect(k8sClient.Update(ctx, testJobA)).Should(gomega.Succeed())
+		}, util.Timeout, util.Interval).Should(gomega.Succeed())
 
-				ginkgo.By("the job-b is unsuspended")
-				gomega.Eventually(func(g gomega.Gomega) {
-					g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(testJobB), testJobB)).Should(gomega.Succeed())
-					g.Expect(ptr.Deref(testJobB.Spec.Suspend, false)).Should(gomega.BeFalse())
-				}, util.Timeout, util.Interval).Should(gomega.Succeed())
-			})
+		ginkgo.By("admitting the job-b workload")
+		gomega.Eventually(func(g gomega.Gomega) {
+			g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(testJobBWorkload), testJobBWorkload)).Should(gomega.Succeed())
+			util.ExpectWorkloadsToBeAdmitted(ctx, k8sClient, testJobBWorkload)
+		}, util.Timeout, util.Interval).Should(gomega.Succeed())
+
+		ginkgo.By("the job-b is unsuspended")
+		gomega.Eventually(func(g gomega.Gomega) {
+			g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(testJobB), testJobB)).Should(gomega.Succeed())
+			g.Expect(ptr.Deref(testJobB.Spec.Suspend, false)).Should(gomega.BeFalse())
+		}, util.Timeout, util.Interval).Should(gomega.Succeed())
+	})
+
+	ginkgo.It("Should mark old pending workload-slice evicted by scheduler as finished", func() {
+		features.SetFeatureGateDuringTest(ginkgo.GinkgoTB(), features.ElasticJobsViaWorkloadSlices, true)
+
+		ginkgo.By("create low priority class")
+		lowPriorityClass := testing.MakeWorkloadPriorityClass("low").PriorityValue(int32(priorityValue)).Obj()
+		util.MustCreate(ctx, k8sClient, lowPriorityClass)
+		ginkgo.DeferCleanup(func() {
+			gomega.Expect(k8sClient.Delete(ctx, lowPriorityClass)).To(gomega.Succeed())
 		})
+
+		ginkgo.By("create high priority class")
+		highPriorityClass := testing.MakeWorkloadPriorityClass("high").PriorityValue(int32(highPriorityValue)).Obj()
+		util.MustCreate(ctx, k8sClient, highPriorityClass)
+		ginkgo.DeferCleanup(func() {
+			gomega.Expect(k8sClient.Delete(ctx, highPriorityClass)).To(gomega.Succeed())
+		})
+
+		lowPriorityJob := testingjob.MakeJob("job-low", ns.Name).
+			SetAnnotation(workloadslicing.EnabledAnnotationKey, workloadslicing.EnabledAnnotationValue).
+			Queue(kueue.LocalQueueName(localQueue.Name)).
+			Request(corev1.ResourceCPU, "1000m").
+			Parallelism(3).
+			Completions(int32(cpuNominalQuota + 1)).
+			WorkloadPriorityClass(lowPriorityClass.Name).
+			Obj()
+
+		ginkgo.By("creating a low-priority job")
+		util.MustCreate(ctx, k8sClient, lowPriorityJob)
+
+		ginkgo.By("the low-priority job is unsuspended")
+		util.ExpectJobUnsuspendedWithNodeSelectors(ctx, k8sClient, client.ObjectKeyFromObject(lowPriorityJob), nil)
+		gomega.Eventually(func(g gomega.Gomega) {
+			g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(lowPriorityJob), lowPriorityJob)).Should(gomega.Succeed())
+			g.Expect(ptr.Deref(lowPriorityJob.Spec.Suspend, false)).Should(gomega.BeFalse())
+		}, util.Timeout, util.Interval).Should(gomega.Succeed())
+
+		var lowPriorityWorkloadSlice *kueue.Workload
+		ginkgo.By("the low-priority workload is admitted")
+		workloads := util.ExpectWorkloadsInNamespace(ctx, k8sClient, lowPriorityJob.Namespace, 1)
+		lowPriorityWorkloadSlice = &workloads[0]
+		util.ExpectWorkloadsToBeAdmitted(ctx, k8sClient, lowPriorityWorkloadSlice)
+
+		ginkgo.By("scale-up low-priority job beyond the queue's nominal capacity")
+		gomega.Eventually(func(g gomega.Gomega) {
+			g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(lowPriorityJob), lowPriorityJob)).Should(gomega.Succeed())
+			lowPriorityJob.Spec.Parallelism = ptr.To(int32(cpuNominalQuota + 1))
+			g.Expect(k8sClient.Update(ctx, lowPriorityJob)).Should(gomega.Succeed())
+		}, util.Timeout, util.Interval).Should(gomega.Succeed())
+
+		ginkgo.By("low priority new workload slice is pending")
+		lowPriorityNewWorkloadSlice := util.ExpectNewWorkloadSlice(ctx, k8sClient, lowPriorityWorkloadSlice)
+		gomega.Expect(lowPriorityNewWorkloadSlice).Should(gomega.Not(gomega.BeNil()))
+		util.ExpectWorkloadsToBePending(ctx, k8sClient, lowPriorityNewWorkloadSlice)
+
+		highPriorityJob := testingjob.MakeJob("high", ns.Name).
+			SetAnnotation(workloadslicing.EnabledAnnotationKey, workloadslicing.EnabledAnnotationValue).
+			Queue(kueue.LocalQueueName(localQueue.Name)).
+			Request(corev1.ResourceCPU, "1000m").
+			Parallelism(3).
+			Completions(3).
+			WorkloadPriorityClass(highPriorityClass.Name).
+			Obj()
+
+		ginkgo.By("creating a high priority job")
+		util.MustCreate(ctx, k8sClient, highPriorityJob)
+
+		ginkgo.By("the high priority job is unsuspended")
+		util.ExpectJobUnsuspendedWithNodeSelectors(ctx, k8sClient, client.ObjectKeyFromObject(highPriorityJob), nil)
+
+		ginkgo.By("the low priority old workload slice is finished")
+		util.ExpectWorkloadToFinish(ctx, k8sClient, client.ObjectKeyFromObject(lowPriorityWorkloadSlice))
 	})
 })
diff --git a/test/util/util.go b/test/util/util.go
index adf8fa11e..4cdc154a8 100644
--- a/test/util/util.go
+++ b/test/util/util.go
@@ -71,6 +71,7 @@ import (
 	utiltas "sigs.k8s.io/kueue/pkg/util/tas"
 	"sigs.k8s.io/kueue/pkg/util/testing"
 	"sigs.k8s.io/kueue/pkg/workload"
+	"sigs.k8s.io/kueue/pkg/workloadslicing"
 )
 
 const (
@@ -1121,3 +1122,51 @@ func ExpectLocalQueueFairSharingUsageToBe(ctx context.Context, k8sClient client.
 		g.Expect(usage.MilliValue()).To(gomega.BeNumerically(comparator, compareTo))
 	}, Timeout, Interval).Should(gomega.Succeed())
 }
+
+// ExpectWorkloadsInNamespace waits until the specified number of kueue.Workload
+// objects exist in the given namespace, then returns the list observed at that moment.
+//
+// It repeatedly lists Workloads using the provided client until the count of
+// items matches the expected value. The poll frequency and maximum wait time are
+// controlled by the test-scoped Interval and Timeout variables. If the expected
+// count is not reached before Timeout, the test fails.
+//
+// Returns:
+//
+//	The slice of Workloads present in the namespace when the expectation is met.
+func ExpectWorkloadsInNamespace(ctx context.Context, k8sClient client.Client, namespace string, count int) []kueue.Workload {
+	list := &kueue.WorkloadList{}
+	gomega.Eventually(func(g gomega.Gomega) {
+		g.Expect(k8sClient.List(ctx, list, client.InNamespace(namespace))).To(gomega.Succeed())
+		g.Expect(list.Items).Should(gomega.HaveLen(count))
+	}, Timeout, Interval).Should(gomega.Succeed())
+	return list.Items
+}
+
+// ExpectNewWorkloadSlice waits until a new kueue.Workload is created in the same
+// namespace as the given oldWorkload, and whose replacement annotation points to
+// the oldWorkload's key.
+//
+// This helper repeatedly lists Workloads in the oldWorkload's namespace until it
+// finds one where workloadslicing.ReplacementForKey matches the key of the given
+// oldWorkload. The search is retried until the test-scoped Timeout expires, polling
+// at the configured Interval. If no such workload is found within the Timeout,
+// the test fails.
+//
+// Returns:
+//   - newWorkload: A pointer to the discovered replacement Workload. Guaranteed
+//     non-nil if the function succeeds; otherwise, the test fails before returning.
+func ExpectNewWorkloadSlice(ctx context.Context, k8sClient client.Client, oldWorkload *kueue.Workload) (newWorkload *kueue.Workload) {
+	gomega.Eventually(func(g gomega.Gomega) {
+		wlList := &kueue.WorkloadList{}
+		g.Expect(k8sClient.List(ctx, wlList, client.InNamespace(oldWorkload.Namespace))).To(gomega.Succeed())
+		for i := range wlList.Items {
+			wl := &wlList.Items[i]
+			if key := workloadslicing.ReplacementForKey(wl); key != nil && *key == workload.Key(oldWorkload) {
+				newWorkload = wl
+				break
+			}
+		}
+	}, Timeout, Interval).Should(gomega.Succeed())
+	return newWorkload
+}