Repository: kubernetes-sigs/kueue

Issue:
Follow-ups related to status.nodesToReplace
<!-- Please only use this template for submitting clean up requests -->

**What would you like to be cleaned**:

Address the follow ups to https://github.com/kubernetes-sigs/kueue/pull/6648

In particular before the release the important is the comment affecting API: https://github.com/kubernetes-sigs/kueue/pull/6648#discussion_r2341231938

In conclusion, change nodesToReplace to unhealthyNodes with subfield "Name".

**Why is this needed**:

To make sure all comments are addressed.

Hints from issue comments:
@mimowo: cc @tenzen-y @pajakd @mbobrovskyi @mbobrovskyi: /assign@mimowo: @mbobrovskyi please also address https://github.com/kubernetes-sigs/kueue/pull/6648#discussion_r2341241428. I believe I addressed https://github.com/kubernetes-sigs/kueue/pull/6648#discussion_r2341236322 in the response.

Solution patch:
diff --git a/.github/workflows/sbom.yaml b/.github/workflows/sbom.yaml
index 2d96b7641..829961661 100644
--- a/.github/workflows/sbom.yaml
+++ b/.github/workflows/sbom.yaml
@@ -21,7 +21,7 @@ jobs:
         run: |
           TAG=${{ github.event.inputs.tag }}
           echo "TAG=$TAG" >> "$GITHUB_ENV"
-      - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5
+      - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00
         with:
           go-version-file: go.mod
           check-latest: true
diff --git a/Makefile b/Makefile
index eda9e0d27..f94852f1f 100644
--- a/Makefile
+++ b/Makefile
@@ -56,7 +56,8 @@ TOOLS_DIR := $(PROJECT_DIR)/hack/internal/tools
 # Use distroless as minimal base image to package the manager binary
 # Refer to https://github.com/GoogleContainerTools/distroless for more details
 BASE_IMAGE ?= gcr.io/distroless/static:nonroot
-BUILDER_IMAGE ?= golang:$(GO_VERSION)
+BASE_BUILDER_IMAGE ?= golang
+BUILDER_IMAGE ?= $(BASE_BUILDER_IMAGE):$(GO_VERSION)
 CGO_ENABLED ?= 0
 
 YAML_PROCESSOR_LOG_LEVEL ?= info
diff --git a/Makefile-test.mk b/Makefile-test.mk
index 7c89fc764..173536019 100644
--- a/Makefile-test.mk
+++ b/Makefile-test.mk
@@ -51,6 +51,9 @@ E2E_USE_HELM ?= false
 # Default will delete default kind cluster
 KIND_CLUSTER_NAME ?= kind
 
+# For restricting to a specific directory
+GO_TEST_TARGET ?= .
+
 ##@ Tests
 
 # Periodic builds are tested with full ray image
@@ -62,7 +65,7 @@ endif
 
 .PHONY: test
 test: gotestsum ## Run tests.
-	$(GOTESTSUM) --junitfile $(ARTIFACTS)/junit.xml -- $(GOFLAGS) $(GO_TEST_FLAGS) $(shell $(GO_CMD) list ./... | grep -v '/test/') -coverpkg=./... -coverprofile $(ARTIFACTS)/cover.out
+	$(GOTESTSUM) --junitfile $(ARTIFACTS)/junit.xml -- $(GOFLAGS) $(GO_TEST_FLAGS) $(shell $(GO_CMD) list $(GO_TEST_TARGET)/... | grep -v '/test/') -coverpkg=$(GO_TEST_TARGET)/... -coverprofile $(ARTIFACTS)/cover.out
 
 .PHONY: test-integration
 test-integration: gomod-download envtest ginkgo dep-crds kueuectl ginkgo-top ## Run integration tests for all singlecluster suites.
diff --git a/apis/kueue/v1alpha1/topology_types.go b/apis/kueue/v1alpha1/topology_types.go
index 47b1dd9b2..6df22abe5 100644
--- a/apis/kueue/v1alpha1/topology_types.go
+++ b/apis/kueue/v1alpha1/topology_types.go
@@ -85,10 +85,6 @@ const (
 	// the Pod's index within the group.
 	PodGroupPodIndexLabelAnnotation = "kueue.x-k8s.io/pod-group-pod-index-label"
 
-	// NodeToReplaceAnnotation is an annotation on a Workload. It holds a
-	// name of a failed node running at least one pod of this workload.
-	NodeToReplaceAnnotation = "alpha.kueue.x-k8s.io/node-to-replace"
-
 	// PodSetGroupName is an annotation indicating the name of the group of PodSets. PodSet Group
 	// is a unit flavor assignment and topology domain fitting.
 	PodSetGroupName = "kueue.x-k8s.io/podset-group-name"
diff --git a/apis/kueue/v1beta1/clusterqueue_types.go b/apis/kueue/v1beta1/clusterqueue_types.go
index a4076ce88..eef40861a 100644
--- a/apis/kueue/v1beta1/clusterqueue_types.go
+++ b/apis/kueue/v1beta1/clusterqueue_types.go
@@ -305,7 +305,8 @@ type ClusterQueueStatus struct {
 
 	// PendingWorkloadsStatus contains the information exposed about the current
 	// status of the pending workloads in the cluster queue.
-	// Deprecated: This field will be removed on v1beta2, use VisibilityOnDemand
+	// Deprecated: This field is no longer effective since v0.14.0, which means Kueue no longer stores and updates information.
+	// You can migrate to VisibilityOnDemand
 	// (https://kueue.sigs.k8s.io/docs/tasks/manage/monitor_pending_workloads/pending_workloads_on_demand/)
 	// instead.
 	// +optional
diff --git a/apis/kueue/v1beta1/workload_types.go b/apis/kueue/v1beta1/workload_types.go
index ce775279b..151f6500d 100644
--- a/apis/kueue/v1beta1/workload_types.go
+++ b/apis/kueue/v1beta1/workload_types.go
@@ -428,6 +428,14 @@ type WorkloadStatus struct {
 	// This field is reset after the Workload is evicted.
 	// +optional
 	ClusterName *string `json:"clusterName,omitempty"`
+
+	// nodesToReplace holds the names of failed nodes running at least one pod of this workload
+	// when Topology-Aware Scheduling is used. This field should not be set by the users.
+	// It indicates Kueue's scheduler is searching for replacements of the failed nodes.
+	// Requires enabling the TASFaliedNodReplacement feature gate.
+	//
+	// +optional
+	NodesToReplace []string `json:"nodesToReplace,omitempty"`
 }
 
 type SchedulingStats struct {
diff --git a/apis/kueue/v1beta1/zz_generated.deepcopy.go b/apis/kueue/v1beta1/zz_generated.deepcopy.go
index 1214c32d6..2642dd74e 100644
--- a/apis/kueue/v1beta1/zz_generated.deepcopy.go
+++ b/apis/kueue/v1beta1/zz_generated.deepcopy.go
@@ -2001,6 +2001,11 @@ func (in *WorkloadStatus) DeepCopyInto(out *WorkloadStatus) {
 		*out = new(string)
 		**out = **in
 	}
+	if in.NodesToReplace != nil {
+		in, out := &in.NodesToReplace, &out.NodesToReplace
+		*out = make([]string, len(*in))
+		copy(*out, *in)
+	}
 }
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkloadStatus.
diff --git a/charts/kueue/Chart.yaml b/charts/kueue/Chart.yaml
index 79e05cb9d..c83d6bf49 100644
--- a/charts/kueue/Chart.yaml
+++ b/charts/kueue/Chart.yaml
@@ -1,6 +1,6 @@
 apiVersion: v2
 name: kueue
-description: 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).
+description: Kueue is a set of APIs and controllers 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).
 # A chart can be either an 'application' or a 'library' chart.
 #
 # Application charts are a collection of templates that can be packaged into versioned archives
diff --git a/charts/kueue/README.md b/charts/kueue/README.md
index f51484c84..cdafa732a 100644
--- a/charts/kueue/README.md
+++ b/charts/kueue/README.md
@@ -2,7 +2,7 @@
 
 ![Version: 0.13.3](https://img.shields.io/badge/Version-0.13.3-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v0.13.3](https://img.shields.io/badge/AppVersion-v0.13.3-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).
+Kueue is a set of APIs and controllers 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).
 
 ### Installation
 
@@ -76,14 +76,14 @@ kueue-controller-manager       1/1     1            1           7s
 
 Kueue has support for third-party certificates.
 One can enable this by setting `enableCertManager` to true.
-This will use certManager to generate a secret, inject the CABundles and set up the tls.
+This will use certManager to generate a secret, inject the CABundles and set up the TLS.
 
 Check out the [site](https://kueue.sigs.k8s.io/docs/tasks/manage/productization/cert_manager/)
 for more information on installing cert manager with our Helm chart.
 
 ##### Prometheus
 
-Kueue supports prometheus metrics.
+Kueue supports Prometheus metrics.
 Check out the [site](https://kueue.sigs.k8s.io/docs/tasks/manage/productization/prometheus/)
 for more information on installing kueue with metrics using our Helm chart.
 
diff --git a/charts/kueue/README.md.gotmpl b/charts/kueue/README.md.gotmpl
index d025f1a42..2f615b065 100644
--- a/charts/kueue/README.md.gotmpl
+++ b/charts/kueue/README.md.gotmpl
@@ -78,14 +78,14 @@ kueue-controller-manager       1/1     1            1           7s
 
 Kueue has support for third-party certificates.
 One can enable this by setting `enableCertManager` to true.
-This will use certManager to generate a secret, inject the CABundles and set up the tls.
+This will use certManager to generate a secret, inject the CABundles and set up the TLS.
 
 Check out the [site](https://kueue.sigs.k8s.io/docs/tasks/manage/productization/cert_manager/)
 for more information on installing cert manager with our Helm chart.
 
 ##### Prometheus
 
-Kueue supports prometheus metrics.
+Kueue supports Prometheus metrics.
 Check out the [site](https://kueue.sigs.k8s.io/docs/tasks/manage/productization/prometheus/)
 for more information on installing kueue with metrics using our Helm chart.
 
diff --git a/charts/kueue/templates/crd/kueue.x-k8s.io_clusterqueues.yaml b/charts/kueue/templates/crd/kueue.x-k8s.io_clusterqueues.yaml
index d50212c10..945231a56 100644
--- a/charts/kueue/templates/crd/kueue.x-k8s.io_clusterqueues.yaml
+++ b/charts/kueue/templates/crd/kueue.x-k8s.io_clusterqueues.yaml
@@ -748,7 +748,8 @@ spec:
                   description: |-
                     PendingWorkloadsStatus contains the information exposed about the current
                     status of the pending workloads in the cluster queue.
-                    Deprecated: This field will be removed on v1beta2, use VisibilityOnDemand
+                    Deprecated: This field is no longer effective since v0.14.0, which means Kueue no longer stores and updates information.
+                    You can migrate to VisibilityOnDemand
                     (https://kueue.sigs.k8s.io/docs/tasks/manage/monitor_pending_workloads/pending_workloads_on_demand/)
                     instead.
                   properties:
diff --git a/charts/kueue/templates/crd/kueue.x-k8s.io_workloads.yaml b/charts/kueue/templates/crd/kueue.x-k8s.io_workloads.yaml
index 28800086f..4bc2bf3ae 100644
--- a/charts/kueue/templates/crd/kueue.x-k8s.io_workloads.yaml
+++ b/charts/kueue/templates/crd/kueue.x-k8s.io_workloads.yaml
@@ -8305,6 +8305,15 @@ spec:
                   x-kubernetes-list-map-keys:
                     - type
                   x-kubernetes-list-type: map
+                nodesToReplace:
+                  description: |-
+                    nodesToReplace holds the names of failed nodes running at least one pod of this workload
+                    when Topology-Aware Scheduling is used. This field should not be set by the users.
+                    It indicates Kueue's scheduler is searching for replacements of the failed nodes.
+                    Requires enabling the TASFaliedNodReplacement feature gate.
+                  items:
+                    type: string
+                  type: array
                 nominatedClusterNames:
                   description: |-
                     nominatedClusterNames specifies the list of cluster names that have been nominated for scheduling.
diff --git a/client-go/applyconfiguration/kueue/v1beta1/workloadstatus.go b/client-go/applyconfiguration/kueue/v1beta1/workloadstatus.go
index 769f0db21..38f1c727d 100644
--- a/client-go/applyconfiguration/kueue/v1beta1/workloadstatus.go
+++ b/client-go/applyconfiguration/kueue/v1beta1/workloadstatus.go
@@ -34,6 +34,7 @@ type WorkloadStatusApplyConfiguration struct {
 	SchedulingStats                      *SchedulingStatsApplyConfiguration      `json:"schedulingStats,omitempty"`
 	NominatedClusterNames                []string                                `json:"nominatedClusterNames,omitempty"`
 	ClusterName                          *string                                 `json:"clusterName,omitempty"`
+	NodesToReplace                       []string                                `json:"nodesToReplace,omitempty"`
 }
 
 // WorkloadStatusApplyConfiguration constructs a declarative configuration of the WorkloadStatus type for use with
@@ -143,3 +144,13 @@ func (b *WorkloadStatusApplyConfiguration) WithClusterName(value string) *Worklo
 	b.ClusterName = &value
 	return b
 }
+
+// WithNodesToReplace adds the given value to the NodesToReplace field in the declarative configuration
+// and returns the receiver, so that objects can be build by chaining "With" function invocations.
+// If called multiple times, values provided by each call will be appended to the NodesToReplace field.
+func (b *WorkloadStatusApplyConfiguration) WithNodesToReplace(values ...string) *WorkloadStatusApplyConfiguration {
+	for i := range values {
+		b.NodesToReplace = append(b.NodesToReplace, values[i])
+	}
+	return b
+}
diff --git a/config/components/crd/bases/kueue.x-k8s.io_clusterqueues.yaml b/config/components/crd/bases/kueue.x-k8s.io_clusterqueues.yaml
index c17d9291b..34cc00c78 100644
--- a/config/components/crd/bases/kueue.x-k8s.io_clusterqueues.yaml
+++ b/config/components/crd/bases/kueue.x-k8s.io_clusterqueues.yaml
@@ -746,7 +746,8 @@ spec:
                 description: |-
                   PendingWorkloadsStatus contains the information exposed about the current
                   status of the pending workloads in the cluster queue.
-                  Deprecated: This field will be removed on v1beta2, use VisibilityOnDemand
+                  Deprecated: This field is no longer effective since v0.14.0, which means Kueue no longer stores and updates information.
+                  You can migrate to VisibilityOnDemand
                   (https://kueue.sigs.k8s.io/docs/tasks/manage/monitor_pending_workloads/pending_workloads_on_demand/)
                   instead.
                 properties:
diff --git a/config/components/crd/bases/kueue.x-k8s.io_workloads.yaml b/config/components/crd/bases/kueue.x-k8s.io_workloads.yaml
index bbe767756..0cca33d01 100644
--- a/config/components/crd/bases/kueue.x-k8s.io_workloads.yaml
+++ b/config/components/crd/bases/kueue.x-k8s.io_workloads.yaml
@@ -8787,6 +8787,15 @@ spec:
                 x-kubernetes-list-map-keys:
                 - type
                 x-kubernetes-list-type: map
+              nodesToReplace:
+                description: |-
+                  nodesToReplace holds the names of failed nodes running at least one pod of this workload
+                  when Topology-Aware Scheduling is used. This field should not be set by the users.
+                  It indicates Kueue's scheduler is searching for replacements of the failed nodes.
+                  Requires enabling the TASFaliedNodReplacement feature gate.
+                items:
+                  type: string
+                type: array
               nominatedClusterNames:
                 description: |-
                   nominatedClusterNames specifies the list of cluster names that have been nominated for scheduling.
diff --git a/hack/internal/tools/go.mod b/hack/internal/tools/go.mod
index 2d9680799..30c759605 100644
--- a/hack/internal/tools/go.mod
+++ b/hack/internal/tools/go.mod
@@ -456,7 +456,7 @@ require (
 	gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
 	gopkg.in/inf.v0 v0.9.1 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
-	gotest.tools/gotestsum v1.12.2 // indirect
+	gotest.tools/gotestsum v1.12.3 // indirect
 	helm.sh/helm/v3 v3.18.5 // indirect
 	honnef.co/go/tools v0.6.1 // indirect
 	howett.net/plist v1.0.0 // indirect
diff --git a/hack/internal/tools/go.sum b/hack/internal/tools/go.sum
index a26f59635..8da8abc95 100644
--- a/hack/internal/tools/go.sum
+++ b/hack/internal/tools/go.sum
@@ -1610,8 +1610,8 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gotest.tools/gotestsum v1.12.2 h1:eli4tu9Q2D/ogDsEGSr8XfQfl7mT0JsGOG6DFtUiZ/Q=
-gotest.tools/gotestsum v1.12.2/go.mod h1:kjRtCglPZVsSU0hFHX3M5VWBM6Y63emHuB14ER1/sow=
+gotest.tools/gotestsum v1.12.3 h1:jFwenGJ0RnPkuKh2VzAYl1mDOJgbhobBDeL2W1iEycs=
+gotest.tools/gotestsum v1.12.3/go.mod h1:Y1+e0Iig4xIRtdmYbEV7K7H6spnjc1fX4BOuUhWw2Wk=
 gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
 gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
 helm.sh/helm/v3 v3.18.5 h1:Cc3Z5vd6kDrZq9wO9KxKLNEickiTho6/H/dBNRVSos4=
diff --git a/keps/2349-multikueue-external-custom-job-support/README.md b/keps/2349-multikueue-external-custom-job-support/README.md
new file mode 100644
index 000000000..d9e6aa54a
--- /dev/null
+++ b/keps/2349-multikueue-external-custom-job-support/README.md
@@ -0,0 +1,255 @@
+# KEP-2349: MultiKueue external custom Job support
+
+<!-- toc -->
+- [Summary](#summary)
+- [Motivation](#motivation)
+  - [Goals](#goals)
+  - [Non-Goals](#non-goals)
+- [Proposal](#proposal)
+  - [User Stories](#user-stories)
+  - [Constraints](#constraints)
+  - [Risks and Mitigations](#risks-and-mitigations)
+    - [Risks](#risks)
+    - [Mitigations](#mitigations)
+- [Design Details](#design-details)
+  - [Configurable MultiKueue Adapters](#configurable-multikueue-adapters)
+    - [Job Flow for the Generic Adapter](#job-flow-for-the-generic-adapter)
+  - [Test Plan](#test-plan)
+      - [Prerequisite testing updates](#prerequisite-testing-updates)
+    - [Unit Tests](#unit-tests)
+    - [Integration tests](#integration-tests)
+  - [Graduation Criteria](#graduation-criteria)
+    - [Alpha](#alpha)
+    - [Beta](#beta)
+    - [GA](#ga)
+- [Implementation History](#implementation-history)
+- [Drawbacks](#drawbacks)
+- [Alternatives](#alternatives)
+<!-- /toc -->
+
+## Summary
+This KEP introduces a mechanism to support MultiKueue for custom Jobs. This is achieved by introducing a configurable system that allows administrators to choose between a built-in generic MultiKueue adapter or an external controller for managing custom job types.
+
+## Motivation
+
+Many Kueue adopters have specific CustomResources which might not be public.
+Kueue should give a possibility to manage such custom Jobs across multiple clusters.
+
+### Goals
+
+Give a possibility for external controllers to manage custom Jobs in a MultiKueue environment.
+
+
+### Non-Goals
+
+This KEP does not aim to generalize the Workload synchronization mechanism for kueue-external-controller.
+Even after this feature is supported, the Workload resource synchronization is handled by kueue-controller-manager (MultiKueue).
+## Proposal
+
+This KEP proposes extending MultiKueue to support custom jobs through a configurable mechanism. Administrators will be able to define, for each custom job type (identified by its GroupVersionKind), whether it should be handled by a built-in generic adapter or by an external, multi-cluster-aware controller.
+
+This configuration will be managed via a configmap. Based on this configuration, MultiKueue will either use its generic adapter for a given GVK or expect an external controller to manage the job's lifecycle across clusters, in which case MultiKueue will only be responsible for synchronizing the `Workload` object.
+
+### User Stories
+
+As a cluster administrator I would like to have the ability to schedule Jobs
+which aren't natively supported by Kueue, eg Tekton.
+
+### Constraints
+
+- Fixed Transformation: The generic adapter is limited to a fixed, non-configurable transformation logic.
+
+### Risks and Mitigations
+
+#### Risks
+
+ Configmaps are unstructured by default. They don't provide validation by default unlike CRD. User could make typo mistakes or give invalid syntax in configmap.
+
+#### Mitigations
+
+Configmaps that are not correct should be logged with errors like "Invalid GVK format". We could have a CLI command to validate the adapter logic.
+
+## Design Details
+
+### Configurable MultiKueue Adapters
+
+To support external frameworks, the MultiKueue configuration API will be extended. Administrators will be able to list custom job GVKs that should be handled by a built-in generic adapter.
+
+The following definitions will be added to the `apis/config/v1beta1` package:
+
+```go
+// MultiKueue specifies the multikueue configuration options.
+type MultiKueue struct {
+   .....
+	// ExternalFrameworks is the list of the external frameworks to be supported by the generic MultiKueue adapter.
+	// +optional
+	ExternalFrameworks []MultiKueueExternalFramework `json:"externalFrameworks,omitempty"`
+}
+
+// MultiKueueExternalFramework defines a framework that is not built-in.
+type MultiKueueExternalFramework struct {
+	// Name is the GVK of the resource that are
+    // is managed by external controllers
+    // the expected format is `Kind.version.group.com`.
+	Name string `json:"name"`
+}
+```
+
+This change will be reflected in the `kueue-manager-config` configmap.
+
+Example YAML configuration:
+
+```yaml
+     # In the multiKueue Kueue Config
+     multiKueue:
+       externalFrameworks:
+         - name: "pipelinerun.v1.tekton.dev"
+```
+
+For every entry in `multiKueue.externalFrameworks`, we register a generic MultiKueue adapter. This adapter performs a default set of operations to manage the job on a worker cluster. It assumes a `.spec.managedBy` field in the custom job and will handle removing it before creation on the worker, as well as syncing the `/status` field back from the worker to the management cluster.
+
+The adapter implements the [MultiKueueAdapter interface](https://github.com/kubernetes-sigs/kueue/blob/22e4502335b0116300b3dcc63d237cf8b7ac759a/pkg/controller/jobframework/interface.go#L235C5-L235C6) as follows:
+- *IsJobManagedByKueue*: Reads the local job object and uses a default JSONPath (`.spec.managedBy`) to verify it's managed by MultiKueue.
+- *SyncJob (Create)*: Clones the local job object, removes the `.spec.managedBy` field, adds the standard MultiKueue labels (`prebuilt-workload`, `multikueue-origin`), and creates the resulting object on the worker cluster.
+- *SyncJob (Status Sync)*: Fetches the local and remote job objects and syncs the `/status` field from the remote object to the local one.
+
+A significant benefit of this approach is the potential to replace the implementation of several built-in adapters (e.g., `JobSet`, `RayJob`, `RayCluster`) by registering the generic adapter for their GVKs. This would lead to a reduction in specialized code and improve maintainability.
+
+However, the generic adapter is not a universal solution. It cannot replace adapters for workloads that have unique lifecycle management mechanisms. This is important for maintainers of external frameworks to consider when choosing an implementation path. Notable exceptions include:
+
+- **Job**: The current adapter relies on the `MultiKueueBatchJobWithManagedBy` environment variable. This is a temporary limitation until the `JobManagedBy` feature in Kubernetes reaches General Availability.
+- **Pod**: The Pod adapter uses `schedulingGates` instead of the `managedBy` field. Extending the generic adapter to support this mechanism is out of scope for this KEP.
+
+#### Job Flow for the Generic Adapter
+   1. User: Submits the custom job (e.g., PipelineRun) with `queue-name` and `managedBy` fields to the management cluster.
+   2. An external controller creates a `Workload` object for the job.
+   3. MultiKueue admits the workload once quota is available in a worker, assigning it to that worker cluster.
+   4. MultiKueue's Generic Adapter clones the job, applies default transformations (like removing `managedBy`), and creates it on the worker cluster.
+   5. The Generic Adapter periodically fetches the job's status from the worker and applies it to the original job on the management cluster.
+   6. When the original job is deleted, the MultiKueue adapter removes the corresponding job from the worker cluster.
+
+### Test Plan
+
+[x] I/we understand the owners of the involved components may require updates to
+existing tests to make this code solid enough prior to committing the changes necessary
+to implement this enhancement.
+- We will test the configmap parsing and validation logic.
+- We will test the generic adapter logic.
+
+##### Prerequisite testing updates
+
+#### Unit Tests
+
+Target is to keep same level or increase the coverage for all of the modified packages.
+Cover the critical part of newly created code.
+
+- `<package>`: `<date>` - `<test coverage>`
+
+#### Integration tests
+
+- A test will be added that creates a `ConfigMap` with rules for a mock GVK.
+- We will then create a `Workload` for that mock GVK and verify that the reconciler correctly applies the creation and status sync logic for the generic adapter.
+- A test will verify that a `Workload` for an unconfigured GVK is correctly rejected.
+
+### Graduation Criteria
+
+#### Alpha
+- **Milestone:** v0.14
+- **Feature Gate:** `MultiKueueAdaptersForCustomJobs`
+- Implementation is behind a feature gate.
+- The generic adapter for custom jobs is implemented.
+
+#### Beta
+- **Milestone:** v0.15
+- All major reported bugs are fixed.
+- The feature gate is enabled by default.
+- Re-evaluate the need for supporting custom patches (for different placement of managedBy or status).
+- Re-visit whether support for specifying location of managedBy field is required.
+- Re-evaluate the need for ControllerType field under External Frameworks struct
+
+#### GA
+
+- All reported bugs are fixed.
+- The feature gate is removed.
+
+
+## Implementation History
+
+* 2024-06-20 First draft
+* 2025-07-15 Second draft
+
+
+## Drawbacks
+
+
+## Alternatives
+
+1. Dedicated API for MultiKueue communication between admission check controller and abstraction layer controller.
+
+Reasons to defer:
+- overall complexity, requires a communication protocol like gRPC between MultiKueue AdmissionChecks and external controllers. 
+- more difficult to debug as multiple layers are involved.
+- requires to maintain compatibility between independently compiled binaries.
+
+2. Don't do any code changes, a custom controller can: Instead of having MultiKueue cluster associated with controller name, change the Multikueue cluster status to use a custom active condition for old controllers (controller name) that use it.
+
+Reasons to defer:
+- The complexity of the external controllers which now need to essentially do the role of the MultiKueue Admission Checks, eg. managing the AC state, loading and using secrets
+
+3. Introduce ability to create Multikueue Admission Check controllers with custom set of adapters.
+
+Reasons to defer:
+- it is much harder to use by users as they need to enlist multiple MultiKueue Amission Checks per CQ as initially proposed in https://github.com/kubernetes-sigs/kueue/pull/2458/files#diff-359284c3c284a904713acde8d57992e7dd5020400b955f25b990b7a35b712ae4R173-R175
+- The external admission checks would need to largely repeat the code of the MultiKueue built-in controller
+- Since the solution involves another big controller it is harder to maintain
+
+4. Using AppWrapper: Using AppWrapper was considered as an alternative. However, this approach has several drawbacks for certain loads.
+
+Reasons to defer:
+   - Job requiring status synchronization: There is no out-of-the-box way to propagate the status of the wrapped resource from the worker cluster back to the management cluster. This would require writing a custom controller to handle status synchronization.
+   - Abstraction Layer: It introduces an additional layer of abstraction. Users would need to wrap their custom resources (like Tekton PipelineRun) in an AppWrapper, which complicates the user experience.
+   - PodSpec Requirement: AppWrapper might not be suitable for all custom resources, especially those that do not expose a PodSet in their spec.
+   - Complexity: While a controller could be built to address some of these issues, it would increase the complexity of the overall solution, particularly for CI/CD use cases.
+
+5. Configurable Controller Type for External Frameworks
+
+An alternative approach considered was to allow administrators to specify a `controller` type for each external framework, choosing between the `generic` adapter and an `external` controller.
+
+The configuration API would be extended as follows:
+
+```go
+// ControllerType is the type of controller for an external framework.
+type ControllerType string
+
+const (
+	// GenericController is a built-in generic MultiKueue adapter.
+	GenericController ControllerType = "generic"
+	// ExternalController means an external, multi-cluster aware controller will manage the job.
+	ExternalController ControllerType = "external"
+)
+
+// MultiKueueExternalFramework defines a framework that is not built-in.
+type MultiKueueExternalFramework struct {
+    .....
+    // Controller is the type of controller for this framework. Defaults to "generic".
+    // +optional
+    ControllerType ControllerType `json:"controller_type,omitempty"`
+}
+```
+
+In this model:
+- `generic` (default): Would behave as described in the main proposal.
+- `external`: Would expect an external, multi-cluster aware controller to manage the job. In this mode, MultiKueue would only sync the `Workload` object to the worker cluster. The external controller would be responsible for creating the job on the worker and syncing its status.
+
+**Job Flow for an External Controller**
+   1. User: Submits a custom job (like a Tekton PipelineRun) with a `queue-name` label.
+   2. An external controller creates a corresponding `Workload` object.
+   3. Kueue's scheduler decides when the `Workload` can be admitted based on available quota.
+   4. Upon admission, MultiKueue's only action is to copy the `Workload` object to the designated worker cluster. It does not create the `PipelineRun` on the worker cluster.
+   5. The external controller (e.g., Tekton's external kueue controller) needs to be "multi-cluster aware." It is responsible for:
+       * Watching for `Workload` object updates on worker clusters.
+       * When it sees a `Workload` get scheduled by MultiKueue, it then creates the original Job (e.g., PipelineRun) on the worker cluster to actually run the job.
+       * It is also solely responsible for monitoring the `PipelineRun`'s status on the worker cluster and syncing it back to the `PipelineRun` object on the management cluster.
+
+**Reasons to defer:**
+This approach was deferred to simplify the initial implementation. The focus of this KEP is to provide a robust generic adapter first. Supporting external controllers can be revisited in the future if there is a strong demand for this functionality. It adds complexity to the configuration and implementation that is not necessary for the primary goal of supporting common custom jobs.
diff --git a/keps/2349-multikueue-external-custom-job-support/kep.yaml b/keps/2349-multikueue-external-custom-job-support/kep.yaml
new file mode 100644
index 000000000..057f15c6a
--- /dev/null
+++ b/keps/2349-multikueue-external-custom-job-support/kep.yaml
@@ -0,0 +1,30 @@
+title: MultiKueue external custom Job support
+kep-number: 2349
+authors:
+  - "@khrm"
+status: implementable
+creation-date: 2025-07-15
+reviewers:
+  - "@tenzen-y"
+  - "@mimowo"
+  - "@mbobrovskyi"
+approvers:
+  - "@tenzen-y"
+  - "@mimowo"
+
+see-also:
+  - "/keps/693-multikueue"
+
+# The target maturity stage in the current dev cycle for this KEP.
+stage: alpha
+
+# 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.14"
+
+# The milestone at which this feature was, or is targeted to be, at each stage.
+milestone:
+  alpha: "v0.14"
+feature-gates:
+  - MultiKueueAdaptersForCustomJobs
diff --git a/keps/2724-topology-aware-scheduling/README.md b/keps/2724-topology-aware-scheduling/README.md
index f3c635c98..6b09bf53d 100644
--- a/keps/2724-topology-aware-scheduling/README.md
+++ b/keps/2724-topology-aware-scheduling/README.md
@@ -33,6 +33,8 @@
     - [PodSet Slice size validation](#podset-slice-size-validation)
   - [Internal APIs](#internal-apis)
     - [Node failures](#node-failures)
+      - [Until v0.13](#until-v013)
+      - [Since v0.14](#since-v014)
   - [Implicit defaulting of TAS annotations](#implicit-defaulting-of-tas-annotations)
   - [Computing the assignment](#computing-the-assignment)
     - [Example](#example)
@@ -63,7 +65,6 @@
     - [Drop the topologyAssignment.levels field](#drop-the-topologyassignmentlevels-field)
     - [Rename the topologyAssignment.domains.values field as levelValues](#rename-the-topologyassignmentdomainsvalues-field-as-levelvalues)
   - [Drop dedicated TAS label](#drop-dedicated-tas-label)
-  - [Failed nodes in WorkloadStatus](#failed-nodes-in-workloadstatus)
   - [MostFreeCapacity algorithm](#mostfreecapacity-algorithm)
     - [Example](#example-2)
 <!-- /toc -->
@@ -936,7 +937,8 @@ is neccessary to fit the workload. Since this mechanism is dedicated
 to only replace nodes, it will only work for Topologies which specify
 `kubernetes.io/hostname` at the lowest level.
 
-We propose to introduce a new Annotation at a Workload level:
+##### Until v0.13
+We use an Annotation at a Workload level:
 
 ```golang
 const (
@@ -945,6 +947,23 @@ const (
 	NodeToReplaceAnnotation = "alpha.kueue.x-k8s.io/node-to-replace"
 )
 ```
+The annotation contains the name of (a single) failed node to replace.
+##### Since v0.14
+We propose to remove the Annotation and replace it with new field in Workload status that will it will contain
+a list of failed nodes:
+
+```golang
+type WorkloadStatus struct {
+  (...)
+	// nodeNamesToReplace, if specified, holds the names of failed nodes running at least one pod of this workload.
+	// This field is for internal use, is set by the node failure controler and should not be set by the users.
+	// It is used to signal kueue scheduler to search for replacement of the failed nodes (if the native kube
+	// scheduler cannot do it automatically). Requires enabling the TASFaliedNodReplacement feature gate.
+	//
+	// +optional
+	NodesToReplace []string `json:"nodesToReplace,omitempty"`
+}
+```
 
 Sometimes node failures are only transient and the node might recover, and so reacting
 immediately to NotReady condition could result in unnecessary node replacements.
@@ -1422,28 +1441,6 @@ fulfilled with a dedicated indexed virtual field.
 Increased code complexity which could defer the 0.9 release for the Alpha
 version. We will re-evaluate the need for the label before the Beta release.
 
-### Failed nodes in WorkloadStatus
-
-Alternatively, the information about failed nodes could be stored in a dedicated 
-field in WorkloadStatus.
-
-```golang
-// WorkloadStatus defines the observed state of Workload
-type WorkloadStatus struct {
-  ...
-  // nodesToReplace lists the names of failed nodes running pods associated 
-  // with this workload. This field is populated by the node failure controller.
-  // +optional
-  // +listType=set
-  NodesToReplace []string `json:"nodesToReplace,omitempty"`
-}
-```
-**Reasons for discarding/deferring**
-
-Uncertanity about the final shape of the feature and the required format.
-We will decide on the format of this field based on the feedback from the 
-customers on the MVP.
-
 ### MostFreeCapacity algorithm
 
 Alongside the `BestFit` and `LeastFreeCapacity` algorithms, the `MostFreeCapacity`
diff --git a/keps/77-dynamically-sized-jobs/README.md b/keps/77-dynamically-sized-jobs/README.md
index 592dc5992..ea018051e 100644
--- a/keps/77-dynamically-sized-jobs/README.md
+++ b/keps/77-dynamically-sized-jobs/README.md
@@ -30,13 +30,15 @@
     - [Scale Down](#scale-down)
     - [Scale Up](#scale-up)
   - [Phase 2 – RayCluster WorkloadSlice Support in Single-Cluster Configuration](#phase-2--raycluster-workloadslice-support-in-single-cluster-configuration)
+    - [Scale Down](#scale-down-1)
+    - [Scale Up](#scale-up-1)
   - [Phase 3 – Enabling Workload Slicing for batch/v1.Job in Multi-Cluster Configuration](#phase-3--enabling-workload-slicing-for-batchv1job-in-multi-cluster-configuration)
 - [Additional Details](#additional-details)
   - [Test Plan](#test-plan)
     - [Unit Tests](#unit-tests)
     - [Integration tests](#integration-tests)
-    - [Scale-down](#scale-down-1)
-    - [Scale-Down](#scale-down-2)
+    - [Scale-down](#scale-down-2)
+    - [Scale-Down](#scale-down-3)
     - [Resource Flavor Handling](#resource-flavor-handling)
   - [Graduation Criteria](#graduation-criteria)
   - [PodScheduling Readiness and ResourceQuota](#podscheduling-readiness-and-resourcequota)
@@ -326,6 +328,29 @@ Scaling up and down for `batch/v1.Job` will be the initial phase of the MVP, as
 ### Phase 2 – RayCluster WorkloadSlice Support in Single-Cluster Configuration
 This phase mirrors the steps from Phase 1 but is adapted specifically for RayCluster workloads, taking into account their autoscaling behavior and internal lifecycle management.
 
+
+#### Scale Down
+
+1. Create a `RayCluster` with workload-slice enablement, consisting of a head node and a worker group with 2 replicas. Both the head node and each replica in the worker group request 1 CPU core for a total of 3 CPU cores.
+2. Verify that a corresponding `Workload` is created, containing 2 `PodSets`, and that it is admitted. You should observe 3 pods in the `Running` state: one for the head node and two for the two worker group replicas.
+3. Update the job by reducing the number of replicas in the worker group from 2 to 1.
+4. Confirm that the existing `Workload` is updated accordingly:
+   - `WorkloadSpec.PodSets[0].Count` (for the head node) remains equal to 1.
+   - `WorkloadSpec.PodSets[1].Count` (for the worker group) is equal to 1 (down from 2).
+5. Observe that the number of running pods is reduced, while the remaining pods continue to run uninterrupted.
+6. Also observe that the ClusterQueue reflects the 2 CPUs that the RayCluster uses.
+
+#### Scale Up
+
+1. Create a `RayCluster` with workload-slice enablement, consisting of a head node and a worker group with 1 replica. Both the head node and each replica in the worker group request 1 CPU core.
+2. Verify that a corresponding `Workload` is created and admitted, and that there are 2 pods belonging to the `RayCluster` in the Running state: one for the head node and one for the worker group replica.
+3. Update the job by increasing the number of replicas in the worker group from 1 to 2.
+4. Confirm that a new `Workload` slice is created and admitted, reflecting the increased pod count, while the previous slice is marked as `Finished`. The new `Workload` reflects the current state of the `RayCluster`:
+   - `WorkloadSpec.PodSets[0].Count` (for the head node) is equal to 1.
+   - `WorkloadSpec.PodSets[1].Count` (for the worker group) is equal to 2.
+5. Observe that the total number of running pods increases to 3 to match the updated replica count, with the original pods continuing to run without disruption.
+6. Also observe that the ClusterQueue reflects the 3 CPUs that the RayCluster uses.
+
 ### Phase 3 – Enabling Workload Slicing for batch/v1.Job in Multi-Cluster Configuration
 In this phase, Workload Slicing support for batch/v1.Job will be extended to multi-cluster environments using Kueue’s MultiKueue architecture. 
 When a job is scaled in the management cluster, its corresponding WorkloadSlice will be propagated to the appropriate workload cluster(s), respecting existing cluster assignment and resource flavor constraints. 
diff --git a/pkg/cache/queue/afs_entry_penalties.go b/pkg/cache/queue/afs_entry_penalties.go
index ffa3558d6..99031b2da 100644
--- a/pkg/cache/queue/afs_entry_penalties.go
+++ b/pkg/cache/queue/afs_entry_penalties.go
@@ -35,19 +35,23 @@ func newPenaltyMap() *AfsEntryPenalties {
 	}
 }
 
-func (m *AfsEntryPenalties) Push(lqKey utilqueue.LocalQueueReference, penalty corev1.ResourceList) {
-	m.penalties.Add(lqKey, resource.MergeResourceListKeepSum(m.Peek(lqKey), penalty))
+func (m *AfsEntryPenalties) push(lqKey utilqueue.LocalQueueReference, penalty corev1.ResourceList) {
+	m.Lock()
+	defer m.Unlock()
+	m.penalties.Add(lqKey, resource.MergeResourceListKeepSum(m.peek(lqKey), penalty))
 }
 
-func (m *AfsEntryPenalties) Sub(lqKey utilqueue.LocalQueueReference, penalty corev1.ResourceList) {
+func (m *AfsEntryPenalties) sub(lqKey utilqueue.LocalQueueReference, penalty corev1.ResourceList) {
+	m.Lock()
+	defer m.Unlock()
 	for k, v := range penalty {
 		v.Neg()
 		penalty[k] = v
 	}
-	m.penalties.Add(lqKey, resource.MergeResourceListKeepSum(m.Peek(lqKey), penalty))
+	m.penalties.Add(lqKey, resource.MergeResourceListKeepSum(m.peek(lqKey), penalty))
 }
 
-func (m *AfsEntryPenalties) Peek(lqKey utilqueue.LocalQueueReference) corev1.ResourceList {
+func (m *AfsEntryPenalties) peek(lqKey utilqueue.LocalQueueReference) corev1.ResourceList {
 	penalty, found := m.penalties.Get(lqKey)
 	if !found {
 		return corev1.ResourceList{}
@@ -56,46 +60,25 @@ func (m *AfsEntryPenalties) Peek(lqKey utilqueue.LocalQueueReference) corev1.Res
 	return penalty
 }
 
-func (m *AfsEntryPenalties) WithPenaltyLocked(lqKey utilqueue.LocalQueueReference, fn func(penalty corev1.ResourceList) error) error {
+func (m *AfsEntryPenalties) updateWithPenalty(lqKey utilqueue.LocalQueueReference, fn func(penalty corev1.ResourceList) error) error {
 	m.Lock()
 	defer m.Unlock()
-
 	penalty, found := m.penalties.Get(lqKey)
 	if !found {
 		penalty = corev1.ResourceList{}
 	}
-
-	err := fn(penalty)
-	if err == nil && found {
-		m.penalties.Delete(lqKey)
+	if err := fn(penalty); err != nil {
+		return err
 	}
-
-	return err
+	m.penalties.Delete(lqKey)
+	return nil
 }
 
-func (m *AfsEntryPenalties) HasPendingFor(lqKey utilqueue.LocalQueueReference) bool {
-	m.Lock()
-	defer m.Unlock()
-
+func (m *AfsEntryPenalties) hasPendingFor(lqKey utilqueue.LocalQueueReference) bool {
 	_, found := m.penalties.Get(lqKey)
-
 	return found
 }
 
-func (m *AfsEntryPenalties) HasAny() bool {
-	m.RLock()
-	defer m.RUnlock()
-
-	return m.penalties.Len() > 0
-}
-
-func (m *AfsEntryPenalties) GetPenalties() *utilmaps.SyncMap[utilqueue.LocalQueueReference, corev1.ResourceList] {
+func (m *AfsEntryPenalties) getPenalties() *utilmaps.SyncMap[utilqueue.LocalQueueReference, corev1.ResourceList] {
 	return m.penalties
 }
-
-func (m *AfsEntryPenalties) GetLocalQueueKeysWithPenalties() []utilqueue.LocalQueueReference {
-	m.RLock()
-	defer m.RUnlock()
-
-	return m.penalties.Keys()
-}
diff --git a/pkg/cache/queue/cluster_queue.go b/pkg/cache/queue/cluster_queue.go
index 186769045..ae9ba40f1 100644
--- a/pkg/cache/queue/cluster_queue.go
+++ b/pkg/cache/queue/cluster_queue.go
@@ -39,6 +39,7 @@ import (
 	utilmaps "sigs.k8s.io/kueue/pkg/util/maps"
 	utilpriority "sigs.k8s.io/kueue/pkg/util/priority"
 	utilqueue "sigs.k8s.io/kueue/pkg/util/queue"
+	"sigs.k8s.io/kueue/pkg/util/resource"
 	"sigs.k8s.io/kueue/pkg/workload"
 )
 
@@ -86,6 +87,9 @@ type ClusterQueue struct {
 	clock clock.Clock
 
 	AdmissionScope *kueue.AdmissionScope
+
+	afsEntryPenalties         *utilmaps.SyncMap[utilqueue.LocalQueueReference, corev1.ResourceList]
+	localQueuesInClusterQueue map[utilqueue.LocalQueueReference]bool
 }
 
 func (c *ClusterQueue) GetName() kueue.ClusterQueueReference {
@@ -109,12 +113,14 @@ func newClusterQueue(ctx context.Context, client client.Client, cq *kueue.Cluste
 func newClusterQueueImpl(ctx context.Context, client client.Client, wo workload.Ordering, clock clock.Clock, fsResWeights map[corev1.ResourceName]float64, enableAdmissionFs bool, afsEntryPenalties *utilmaps.SyncMap[utilqueue.LocalQueueReference, corev1.ResourceList]) *ClusterQueue {
 	lessFunc := queueOrderingFunc(ctx, client, wo, fsResWeights, enableAdmissionFs, afsEntryPenalties)
 	return &ClusterQueue{
-		heap:                   *heap.New(workloadKey, lessFunc),
-		inadmissibleWorkloads:  make(map[workload.Reference]*workload.Info),
-		queueInadmissibleCycle: -1,
-		lessFunc:               lessFunc,
-		rwm:                    sync.RWMutex{},
-		clock:                  clock,
+		heap:                      *heap.New(workloadKey, lessFunc),
+		inadmissibleWorkloads:     make(map[workload.Reference]*workload.Info),
+		queueInadmissibleCycle:    -1,
+		lessFunc:                  lessFunc,
+		rwm:                       sync.RWMutex{},
+		clock:                     clock,
+		afsEntryPenalties:         afsEntryPenalties,
+		localQueuesInClusterQueue: make(map[utilqueue.LocalQueueReference]bool),
 	}
 }
 
@@ -330,6 +336,11 @@ func (c *ClusterQueue) PendingInadmissible() int {
 func (c *ClusterQueue) Pop() *workload.Info {
 	c.rwm.Lock()
 	defer c.rwm.Unlock()
+
+	if c.hasPendingPenalties() {
+		c.rebuildAll()
+	}
+
 	c.popCycle++
 	if c.heap.Len() == 0 {
 		c.inflight = nil
@@ -339,6 +350,27 @@ func (c *ClusterQueue) Pop() *workload.Info {
 	return c.inflight
 }
 
+// rebuildAll rebuilds the entire heap. Must be called with lock held.
+func (c *ClusterQueue) rebuildAll() {
+	for _, wl := range c.heap.List() {
+		c.heap.PushOrUpdate(wl)
+	}
+}
+
+func (c *ClusterQueue) hasPendingPenalties() bool {
+	if c.afsEntryPenalties == nil {
+		return false
+	}
+
+	for lqKey := range c.localQueuesInClusterQueue {
+		lqPenalty, hasPenalty := c.afsEntryPenalties.Get(lqKey)
+		if hasPenalty && !resource.IsZero(lqPenalty) {
+			return true
+		}
+	}
+	return false
+}
+
 // Dump produces a dump of the current workloads in the heap of
 // this ClusterQueue. It returns false if the queue is empty,
 // otherwise returns true.
@@ -460,10 +492,14 @@ func queueOrderingFunc(ctx context.Context, c client.Client, wo workload.Orderin
 	}
 }
 
-func (c *ClusterQueue) RebuildAll() {
+func (c *ClusterQueue) addLocalQueue(lqKey utilqueue.LocalQueueReference) {
 	c.rwm.Lock()
 	defer c.rwm.Unlock()
-	for _, wl := range c.heap.List() {
-		c.heap.PushOrUpdate(wl)
-	}
+	c.localQueuesInClusterQueue[lqKey] = true
+}
+
+func (c *ClusterQueue) deleteLocalQueue(lqKey utilqueue.LocalQueueReference) {
+	c.rwm.Lock()
+	defer c.rwm.Unlock()
+	delete(c.localQueuesInClusterQueue, lqKey)
 }
diff --git a/pkg/cache/queue/manager.go b/pkg/cache/queue/manager.go
index 538c0c7b6..dd8a35742 100644
--- a/pkg/cache/queue/manager.go
+++ b/pkg/cache/queue/manager.go
@@ -182,7 +182,7 @@ func (m *Manager) AddClusterQueue(ctx context.Context, cq *kueue.ClusterQueue) e
 
 	var afsEntryPenalties *utilmaps.SyncMap[queue.LocalQueueReference, corev1.ResourceList]
 	if afs.Enabled(m.admissionFairSharingConfig) {
-		afsEntryPenalties = m.afsEntryPenalties.GetPenalties()
+		afsEntryPenalties = m.afsEntryPenalties.getPenalties()
 	}
 	cqImpl, err := newClusterQueue(ctx, m.client, cq, m.workloadOrdering, m.admissionFairSharingConfig, afsEntryPenalties)
 	if err != nil {
@@ -203,6 +203,7 @@ func (m *Manager) AddClusterQueue(ctx context.Context, cq *kueue.ClusterQueue) e
 		if qImpl != nil {
 			added := cqImpl.AddFromLocalQueue(qImpl)
 			addedWorkloads = addedWorkloads || added
+			cqImpl.addLocalQueue(queue.Key(&q))
 		}
 	}
 
@@ -298,6 +299,11 @@ func (m *Manager) AddLocalQueue(ctx context.Context, q *kueue.LocalQueue) error
 	}
 	qImpl := newLocalQueue(q)
 	m.localQueues[key] = qImpl
+
+	if cq := m.hm.ClusterQueue(qImpl.ClusterQueue); cq != nil {
+		cq.addLocalQueue(key)
+	}
+
 	// Iterate through existing workloads, as workloads corresponding to this
 	// queue might have been added earlier.
 	var workloads kueue.WorkloadList
@@ -329,9 +335,12 @@ func (m *Manager) UpdateLocalQueue(q *kueue.LocalQueue) error {
 		oldCQ := m.hm.ClusterQueue(qImpl.ClusterQueue)
 		if oldCQ != nil {
 			oldCQ.DeleteFromLocalQueue(qImpl)
+			oldCQ.deleteLocalQueue(queue.Key(q))
 		}
 		newCQ := m.hm.ClusterQueue(q.Spec.ClusterQueue)
-		if newCQ != nil && newCQ.AddFromLocalQueue(qImpl) {
+		if newCQ != nil {
+			newCQ.AddFromLocalQueue(qImpl)
+			newCQ.addLocalQueue(queue.Key(q))
 			m.Broadcast()
 		}
 	}
@@ -350,6 +359,7 @@ func (m *Manager) DeleteLocalQueue(q *kueue.LocalQueue) {
 	cq := m.hm.ClusterQueue(qImpl.ClusterQueue)
 	if cq != nil {
 		cq.DeleteFromLocalQueue(qImpl)
+		cq.deleteLocalQueue(key)
 	}
 	if features.Enabled(features.LocalQueueMetrics) {
 		namespace, lqName := queue.MustParseLocalQueueReference(key)
@@ -807,46 +817,24 @@ func (m *Manager) queueSecondPass(ctx context.Context, w *kueue.Workload) {
 	}
 }
 
-func (m *Manager) RebuildClusterQueuesWithEntryPenalties() {
-	m.Lock()
-	defer m.Unlock()
-
-	clusterQueuesWithPenalties := sets.New[kueue.ClusterQueueReference]()
-	for _, lqKey := range m.afsEntryPenalties.GetLocalQueueKeysWithPenalties() {
-		if lq, exists := m.localQueues[lqKey]; exists {
-			clusterQueuesWithPenalties.Insert(lq.ClusterQueue)
-		}
-	}
-
-	for cqName := range clusterQueuesWithPenalties {
-		if cq := m.hm.ClusterQueue(cqName); cq != nil {
-			cq.RebuildAll()
-		}
-	}
-}
-
 func (m *Manager) PushEntryPenalty(lqKey queue.LocalQueueReference, penalty corev1.ResourceList) {
-	m.afsEntryPenalties.Push(lqKey, penalty)
+	m.afsEntryPenalties.push(lqKey, penalty)
 }
 
 func (m *Manager) SubEntryPenalty(lqKey queue.LocalQueueReference, penalty corev1.ResourceList) {
-	m.afsEntryPenalties.Sub(lqKey, penalty)
+	m.afsEntryPenalties.sub(lqKey, penalty)
 }
 
-func (m *Manager) WithPenaltyLocked(lqKey queue.LocalQueueReference, fn func(penalty corev1.ResourceList) error) error {
-	return m.afsEntryPenalties.WithPenaltyLocked(lqKey, fn)
+func (m *Manager) UpdateWithPenalty(lqKey queue.LocalQueueReference, fn func(penalty corev1.ResourceList) error) error {
+	return m.afsEntryPenalties.updateWithPenalty(lqKey, fn)
 }
 
 func (m *Manager) HasPendingPenaltyFor(lqKey queue.LocalQueueReference) bool {
-	return m.afsEntryPenalties.HasPendingFor(lqKey)
-}
-
-func (m *Manager) HasAnyEntryPenalty() bool {
-	return m.afsEntryPenalties.HasAny()
+	return m.afsEntryPenalties.hasPendingFor(lqKey)
 }
 
 func (m *Manager) GetAfsEntryPenalties() *utilmaps.SyncMap[queue.LocalQueueReference, corev1.ResourceList] {
-	return m.afsEntryPenalties.GetPenalties()
+	return m.afsEntryPenalties.getPenalties()
 }
 
 type WorkloadUpdateWatcher interface {
diff --git a/pkg/cache/scheduler/tas_flavor_snapshot.go b/pkg/cache/scheduler/tas_flavor_snapshot.go
index 4129b5b6c..eefc4a8ab 100644
--- a/pkg/cache/scheduler/tas_flavor_snapshot.go
+++ b/pkg/cache/scheduler/tas_flavor_snapshot.go
@@ -34,7 +34,6 @@ import (
 	corev1helpers "k8s.io/component-helpers/scheduling/corev1"
 	"k8s.io/utils/ptr"
 
-	kueuealpha "sigs.k8s.io/kueue/apis/kueue/v1alpha1"
 	kueue "sigs.k8s.io/kueue/apis/kueue/v1beta1"
 	"sigs.k8s.io/kueue/pkg/features"
 	"sigs.k8s.io/kueue/pkg/podset"
@@ -511,7 +510,7 @@ func findLeaderAndWorkers(trs FlavorTASRequests) (*TASPodSetRequests, TASPodSetR
 // it return new corrected topologyAssignment, a replacement topologyAssignment used to patched the old, faulty one, and
 // reason if finding fails
 func (s *TASFlavorSnapshot) findReplacementAssignment(tr *TASPodSetRequests, existingAssignment *kueue.TopologyAssignment, wl *kueue.Workload, assumedUsage map[utiltas.TopologyDomainID]resources.Requests) (*kueue.TopologyAssignment, *kueue.TopologyAssignment, string) {
-	nodeToReplace := wl.Annotations[kueuealpha.NodeToReplaceAnnotation]
+	nodeToReplace := wl.Status.NodesToReplace[0]
 	tr.Count = deleteDomain(existingAssignment, nodeToReplace)
 	if isStale, staleDomain := s.IsTopologyAssignmentStale(existingAssignment); isStale {
 		return nil, nil, fmt.Sprintf("Cannot replace the node, because the existing topologyAssignment is invalid, as it contains the stale domain %v", staleDomain)
diff --git a/pkg/controller/admissionchecks/multikueue/workload.go b/pkg/controller/admissionchecks/multikueue/workload.go
index 71f3245dd..d806ea040 100644
--- a/pkg/controller/admissionchecks/multikueue/workload.go
+++ b/pkg/controller/admissionchecks/multikueue/workload.go
@@ -282,7 +282,7 @@ func (w *wlReconciler) multikueueAC(ctx context.Context, local *kueue.Workload)
 	if len(relevantChecks) == 0 {
 		return nil, nil
 	}
-	return workload.FindAdmissionCheck(local.Status.AdmissionChecks, relevantChecks[0]), nil
+	return admissioncheck.FindAdmissionCheck(local.Status.AdmissionChecks, relevantChecks[0]), nil
 }
 
 func (w *wlReconciler) adapter(local *kueue.Workload) (jobframework.MultiKueueAdapter, *metav1.OwnerReference) {
@@ -331,7 +331,7 @@ func (w *wlReconciler) reconcileGroup(ctx context.Context, group *wlGroup) (reco
 	log := ctrl.LoggerFrom(ctx).WithValues("op", "reconcileGroup")
 	log.V(3).Info("Reconcile Workload Group")
 
-	acs := workload.FindAdmissionCheck(group.local.Status.AdmissionChecks, group.acName)
+	acs := admissioncheck.FindAdmissionCheck(group.local.Status.AdmissionChecks, group.acName)
 
 	// 1. delete all remote workloads when finished or the local wl has no reservation
 	if group.IsFinished() || !workload.HasQuotaReservation(group.local) {
@@ -395,7 +395,7 @@ func (w *wlReconciler) reconcileGroup(ctx context.Context, group *wlGroup) (reco
 			}
 		}
 
-		acs := workload.FindAdmissionCheck(group.local.Status.AdmissionChecks, group.acName)
+		acs := admissioncheck.FindAdmissionCheck(group.local.Status.AdmissionChecks, group.acName)
 		if err := group.jobAdapter.SyncJob(ctx, w.client, group.remoteClients[reservingRemote].client, group.controllerKey, group.local.Name, w.origin); err != nil {
 			log.V(2).Error(err, "creating remote controller object", "remote", reservingRemote)
 			// We'll retry this in the next reconcile.
diff --git a/pkg/controller/admissionchecks/provisioning/controller.go b/pkg/controller/admissionchecks/provisioning/controller.go
index 4555477c6..aaa618672 100644
--- a/pkg/controller/admissionchecks/provisioning/controller.go
+++ b/pkg/controller/admissionchecks/provisioning/controller.go
@@ -236,7 +236,7 @@ func (c *Controller) syncOwnedProvisionRequest(
 		if !c.reqIsNeeded(wl, prc) {
 			continue
 		}
-		ac := workload.FindAdmissionCheck(wlInfo.checkStates, checkName)
+		ac := admissioncheck.FindAdmissionCheck(wlInfo.checkStates, checkName)
 		if ac != nil && ac.State == kueue.CheckStateReady {
 			log.V(2).Info("Skip syncing of the ProvReq for admission check which is Ready", "workload", klog.KObj(wl), "admissionCheck", checkName)
 			continue
@@ -593,7 +593,7 @@ func (c *Controller) syncCheckStates(
 			}
 		}
 
-		existingCondition := workload.FindAdmissionCheck(wlPatch.Status.AdmissionChecks, checkState.Name)
+		existingCondition := admissioncheck.FindAdmissionCheck(wlPatch.Status.AdmissionChecks, checkState.Name)
 		if existingCondition != nil && existingCondition.State != checkState.State {
 			message := fmt.Sprintf("Admission check %s updated state from %s to %s", checkState.Name, existingCondition.State, checkState.State)
 			if checkState.Message != "" {
diff --git a/pkg/controller/core/clusterqueue_controller.go b/pkg/controller/core/clusterqueue_controller.go
index c0b23ebe7..036f48a60 100644
--- a/pkg/controller/core/clusterqueue_controller.go
+++ b/pkg/controller/core/clusterqueue_controller.go
@@ -20,7 +20,6 @@ import (
 	"context"
 	"iter"
 	"slices"
-	"time"
 
 	"github.com/go-logr/logr"
 	corev1 "k8s.io/api/core/v1"
@@ -29,7 +28,6 @@ import (
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/types"
 	"k8s.io/apimachinery/pkg/util/sets"
-	"k8s.io/apimachinery/pkg/util/wait"
 	"k8s.io/client-go/util/workqueue"
 	"k8s.io/klog/v2"
 	"k8s.io/utils/clock"
@@ -51,46 +49,37 @@ import (
 	qcache "sigs.k8s.io/kueue/pkg/cache/queue"
 	schdcache "sigs.k8s.io/kueue/pkg/cache/scheduler"
 	"sigs.k8s.io/kueue/pkg/constants"
-	"sigs.k8s.io/kueue/pkg/features"
 	"sigs.k8s.io/kueue/pkg/metrics"
 	"sigs.k8s.io/kueue/pkg/util/resource"
 	utilslices "sigs.k8s.io/kueue/pkg/util/slices"
 	"sigs.k8s.io/kueue/pkg/workload"
 )
 
-const snapshotWorkers = 5
-
 type ClusterQueueUpdateWatcher interface {
 	NotifyClusterQueueUpdate(*kueue.ClusterQueue, *kueue.ClusterQueue)
 }
 
 // ClusterQueueReconciler reconciles a ClusterQueue object
 type ClusterQueueReconciler struct {
-	client                               client.Client
-	log                                  logr.Logger
-	qManager                             *qcache.Manager
-	cache                                *schdcache.Cache
-	snapshotsQueue                       workqueue.TypedInterface[kueue.ClusterQueueReference]
-	snapUpdateCh                         chan event.GenericEvent
-	nonCQObjectUpdateCh                  chan event.TypedGenericEvent[iter.Seq[kueue.ClusterQueueReference]]
-	watchers                             []ClusterQueueUpdateWatcher
-	reportResourceMetrics                bool
-	fairSharingEnabled                   bool
-	queueVisibilityUpdateInterval        time.Duration
-	queueVisibilityClusterQueuesMaxCount int32
-	clock                                clock.Clock
+	client                client.Client
+	log                   logr.Logger
+	qManager              *qcache.Manager
+	cache                 *schdcache.Cache
+	nonCQObjectUpdateCh   chan event.TypedGenericEvent[iter.Seq[kueue.ClusterQueueReference]]
+	watchers              []ClusterQueueUpdateWatcher
+	reportResourceMetrics bool
+	fairSharingEnabled    bool
+	clock                 clock.Clock
 }
 
 var _ reconcile.Reconciler = (*ClusterQueueReconciler)(nil)
 var _ predicate.TypedPredicate[*kueue.ClusterQueue] = (*ClusterQueueReconciler)(nil)
 
 type ClusterQueueReconcilerOptions struct {
-	Watchers                             []ClusterQueueUpdateWatcher
-	ReportResourceMetrics                bool
-	FairSharingEnabled                   bool
-	QueueVisibilityUpdateInterval        time.Duration
-	QueueVisibilityClusterQueuesMaxCount int32
-	clock                                clock.Clock
+	Watchers              []ClusterQueueUpdateWatcher
+	ReportResourceMetrics bool
+	FairSharingEnabled    bool
+	clock                 clock.Clock
 }
 
 // ClusterQueueReconcilerOption configures the reconciler.
@@ -114,22 +103,6 @@ func WithFairSharing(enabled bool) ClusterQueueReconcilerOption {
 	}
 }
 
-// WithQueueVisibilityUpdateInterval specifies the time interval for updates to the structure
-// of the top pending workloads in the queues.
-func WithQueueVisibilityUpdateInterval(interval time.Duration) ClusterQueueReconcilerOption {
-	return func(o *ClusterQueueReconcilerOptions) {
-		o.QueueVisibilityUpdateInterval = interval
-	}
-}
-
-// WithQueueVisibilityClusterQueuesMaxCount indicates the maximal number of pending workloads exposed in the
-// cluster queue status
-func WithQueueVisibilityClusterQueuesMaxCount(value int32) ClusterQueueReconcilerOption {
-	return func(o *ClusterQueueReconcilerOptions) {
-		o.QueueVisibilityClusterQueuesMaxCount = value
-	}
-}
-
 var defaultCQOptions = ClusterQueueReconcilerOptions{
 	clock: realClock,
 }
@@ -145,19 +118,15 @@ func NewClusterQueueReconciler(
 		opt(&options)
 	}
 	return &ClusterQueueReconciler{
-		client:                               client,
-		log:                                  ctrl.Log.WithName("cluster-queue-reconciler"),
-		qManager:                             qMgr,
-		cache:                                cache,
-		snapshotsQueue:                       workqueue.NewTyped[kueue.ClusterQueueReference](),
-		snapUpdateCh:                         make(chan event.GenericEvent, updateChBuffer),
-		nonCQObjectUpdateCh:                  make(chan event.TypedGenericEvent[iter.Seq[kueue.ClusterQueueReference]], updateChBuffer),
-		watchers:                             options.Watchers,
-		reportResourceMetrics:                options.ReportResourceMetrics,
-		fairSharingEnabled:                   options.FairSharingEnabled,
-		queueVisibilityUpdateInterval:        options.QueueVisibilityUpdateInterval,
-		queueVisibilityClusterQueuesMaxCount: options.QueueVisibilityClusterQueuesMaxCount,
-		clock:                                options.clock,
+		client:                client,
+		log:                   ctrl.Log.WithName("cluster-queue-reconciler"),
+		qManager:              qMgr,
+		cache:                 cache,
+		nonCQObjectUpdateCh:   make(chan event.TypedGenericEvent[iter.Seq[kueue.ClusterQueueReference]], updateChBuffer),
+		watchers:              options.Watchers,
+		reportResourceMetrics: options.ReportResourceMetrics,
+		fairSharingEnabled:    options.FairSharingEnabled,
+		clock:                 options.clock,
 	}
 }
 
@@ -539,43 +508,12 @@ func (h *nonCQObjectHandler) Generic(_ context.Context, e event.TypedGenericEven
 	}
 }
 
-type cqSnapshotHandler struct {
-	queueVisibilityUpdateInterval time.Duration
-}
-
-func (h *cqSnapshotHandler) Create(context.Context, event.CreateEvent, workqueue.TypedRateLimitingInterface[reconcile.Request]) {
-}
-
-func (h *cqSnapshotHandler) Update(context.Context, event.UpdateEvent, workqueue.TypedRateLimitingInterface[reconcile.Request]) {
-}
-
-func (h *cqSnapshotHandler) Delete(context.Context, event.DeleteEvent, workqueue.TypedRateLimitingInterface[reconcile.Request]) {
-}
-
-func (h *cqSnapshotHandler) Generic(_ context.Context, e event.GenericEvent, q workqueue.TypedRateLimitingInterface[reconcile.Request]) {
-	cq, isCq := e.Object.(*kueue.ClusterQueue)
-	if !isCq {
-		return
-	}
-	remainingTime := constants.UpdatesBatchPeriod
-	if cq.Status.PendingWorkloadsStatus != nil {
-		remainingTime = max(h.queueVisibilityUpdateInterval-time.Since(cq.Status.PendingWorkloadsStatus.LastChangeTime.Time), constants.UpdatesBatchPeriod)
-	}
-	q.AddAfter(reconcile.Request{
-		NamespacedName: types.NamespacedName{
-			Name: cq.Name,
-		}}, remainingTime)
-}
-
 // SetupWithManager sets up the controller with the Manager.
 func (r *ClusterQueueReconciler) SetupWithManager(mgr ctrl.Manager, cfg *config.Configuration) error {
 	nsHandler := cqNamespaceHandler{
 		qManager: r.qManager,
 		cache:    r.cache,
 	}
-	snapHandler := cqSnapshotHandler{
-		queueVisibilityUpdateInterval: r.queueVisibilityUpdateInterval,
-	}
 	return builder.TypedControllerManagedBy[reconcile.Request](mgr).
 		Named("clusterqueue_controller").
 		WatchesRawSource(source.TypedKind(
@@ -589,7 +527,6 @@ func (r *ClusterQueueReconciler) SetupWithManager(mgr ctrl.Manager, cfg *config.
 			MaxConcurrentReconciles: mgr.GetControllerOptions().GroupKindConcurrency[kueue.GroupVersion.WithKind("ClusterQueue").GroupKind().String()],
 		}).
 		Watches(&corev1.Namespace{}, &nsHandler).
-		WatchesRawSource(source.Channel(r.snapUpdateCh, &snapHandler)).
 		WatchesRawSource(source.Channel(r.nonCQObjectUpdateCh, &nonCQObjectHandler{})).
 		Complete(WithLeadingManager(mgr, r, &kueue.ClusterQueue{}, cfg))
 }
@@ -618,7 +555,6 @@ func (r *ClusterQueueReconciler) updateCqStatusIfChanged(
 	cq.Status.ReservingWorkloads = int32(stats.ReservingWorkloads)
 	cq.Status.AdmittedWorkloads = int32(stats.AdmittedWorkloads)
 	cq.Status.PendingWorkloads = int32(pendingWorkloads)
-	cq.Status.PendingWorkloadsStatus = r.getWorkloadsStatus(cq)
 	meta.SetStatusCondition(&cq.Status.Conditions, metav1.Condition{
 		Type:               kueue.ClusterQueueActive,
 		Status:             conditionStatus,
@@ -642,79 +578,3 @@ func (r *ClusterQueueReconciler) updateCqStatusIfChanged(
 	}
 	return nil
 }
-
-// Taking snapshot of cluster queue is enabled when maxcount non-zero
-func (r *ClusterQueueReconciler) isVisibilityEnabled() bool {
-	return features.Enabled(features.QueueVisibility) && r.queueVisibilityClusterQueuesMaxCount > 0
-}
-
-func (r *ClusterQueueReconciler) getWorkloadsStatus(cq *kueue.ClusterQueue) *kueue.ClusterQueuePendingWorkloadsStatus {
-	if !r.isVisibilityEnabled() {
-		return nil
-	}
-	pendingWorkloads := r.qManager.GetSnapshot(kueue.ClusterQueueReference(cq.Name))
-	if cq.Status.PendingWorkloadsStatus == nil ||
-		cq.Status.PendingWorkloadsStatus.Head == nil ||
-		!equality.Semantic.DeepEqual(cq.Status.PendingWorkloadsStatus.Head, pendingWorkloads) {
-		return &kueue.ClusterQueuePendingWorkloadsStatus{
-			Head:           pendingWorkloads,
-			LastChangeTime: metav1.Time{Time: r.clock.Now()},
-		}
-	}
-	return cq.Status.PendingWorkloadsStatus
-}
-
-func (r *ClusterQueueReconciler) Start(ctx context.Context) error {
-	if !r.isVisibilityEnabled() {
-		return nil
-	}
-
-	defer r.snapshotsQueue.ShutDown()
-
-	for range snapshotWorkers {
-		go wait.UntilWithContext(ctx, r.takeSnapshot, r.queueVisibilityUpdateInterval)
-	}
-
-	go wait.UntilWithContext(ctx, r.enqueueTakeSnapshot, r.queueVisibilityUpdateInterval)
-
-	<-ctx.Done()
-
-	return nil
-}
-
-func (r *ClusterQueueReconciler) enqueueTakeSnapshot(_ context.Context) {
-	for _, cq := range r.qManager.GetClusterQueueNames() {
-		r.snapshotsQueue.Add(cq)
-	}
-}
-
-func (r *ClusterQueueReconciler) takeSnapshot(ctx context.Context) {
-	for r.processNextSnapshot(ctx) {
-	}
-}
-
-func (r *ClusterQueueReconciler) processNextSnapshot(ctx context.Context) bool {
-	log := ctrl.LoggerFrom(ctx).WithName("processNextSnapshot")
-
-	cqName, quit := r.snapshotsQueue.Get()
-	if quit {
-		return false
-	}
-
-	startTime := r.clock.Now()
-	defer func() {
-		log.V(5).Info("Finished snapshot job", "clusterQueue", klog.KRef("", string(cqName)), "elapsed", time.Since(startTime))
-	}()
-
-	defer r.snapshotsQueue.Done(cqName)
-
-	if r.qManager.UpdateSnapshot(cqName, r.queueVisibilityClusterQueuesMaxCount) {
-		log.V(5).Info("Triggering CQ update due to snapshot change", "clusterQueue", klog.KRef("", string(cqName)))
-		r.snapUpdateCh <- event.GenericEvent{Object: &kueue.ClusterQueue{
-			ObjectMeta: metav1.ObjectMeta{
-				Name: string(cqName),
-			},
-		}}
-	}
-	return true
-}
diff --git a/pkg/controller/core/core.go b/pkg/controller/core/core.go
index aa1acaceb..16bf18cbf 100644
--- a/pkg/controller/core/core.go
+++ b/pkg/controller/core/core.go
@@ -67,15 +67,10 @@ func SetupControllers(mgr ctrl.Manager, qManager *qcache.Manager, cc *schdcache.
 		mgr.GetClient(),
 		qManager,
 		cc,
-		WithQueueVisibilityUpdateInterval(queueVisibilityUpdateInterval(cfg)),
 		WithReportResourceMetrics(cfg.Metrics.EnableClusterQueueResources),
-		WithQueueVisibilityClusterQueuesMaxCount(queueVisibilityClusterQueuesMaxCount(cfg)),
 		WithFairSharing(fairSharingEnabled),
 		WithWatchers(watchers...),
 	)
-	if err := mgr.Add(cqRec); err != nil {
-		return "Unable to add ClusterQueue to manager", err
-	}
 	rfRec.AddUpdateWatcher(cqRec)
 	acRec.AddUpdateWatchers(cqRec)
 	if err := cqRec.SetupWithManager(mgr, cfg); err != nil {
@@ -123,17 +118,3 @@ func workloadRetention(cfg *configapi.ObjectRetentionPolicies) *workloadRetentio
 		afterFinished: &cfg.Workloads.AfterFinished.Duration,
 	}
 }
-
-func queueVisibilityUpdateInterval(cfg *configapi.Configuration) time.Duration {
-	if cfg.QueueVisibility != nil {
-		return time.Duration(cfg.QueueVisibility.UpdateIntervalSeconds) * time.Second
-	}
-	return 0
-}
-
-func queueVisibilityClusterQueuesMaxCount(cfg *configapi.Configuration) int32 {
-	if cfg.QueueVisibility != nil && cfg.QueueVisibility.ClusterQueues != nil {
-		return cfg.QueueVisibility.ClusterQueues.MaxCount
-	}
-	return 0
-}
diff --git a/pkg/controller/core/localqueue_controller.go b/pkg/controller/core/localqueue_controller.go
index fb873f0d0..1381b553f 100644
--- a/pkg/controller/core/localqueue_controller.go
+++ b/pkg/controller/core/localqueue_controller.go
@@ -295,7 +295,7 @@ func (r *LocalQueueReconciler) reconcileConsumedUsage(ctx context.Context, lq *k
 	sum := resource.MergeResourceListKeepSum(scaledOldUsage, scaledNewUsage)
 	// Add penalty to the final usage
 	lqKey := utilqueue.Key(lq)
-	err = r.queues.WithPenaltyLocked(lqKey, func(penalty corev1.ResourceList) error {
+	err = r.queues.UpdateWithPenalty(lqKey, func(penalty corev1.ResourceList) error {
 		sum = resource.MergeResourceListKeepSum(sum, penalty)
 
 		// update status
diff --git a/pkg/controller/core/workload_controller.go b/pkg/controller/core/workload_controller.go
index d48437f06..3ef261a8b 100644
--- a/pkg/controller/core/workload_controller.go
+++ b/pkg/controller/core/workload_controller.go
@@ -49,7 +49,6 @@ import (
 	"sigs.k8s.io/controller-runtime/pkg/source"
 
 	config "sigs.k8s.io/kueue/apis/config/v1beta1"
-	kueuealpha "sigs.k8s.io/kueue/apis/kueue/v1alpha1"
 	kueue "sigs.k8s.io/kueue/apis/kueue/v1beta1"
 	qcache "sigs.k8s.io/kueue/pkg/cache/queue"
 	schdcache "sigs.k8s.io/kueue/pkg/cache/scheduler"
@@ -57,7 +56,6 @@ import (
 	"sigs.k8s.io/kueue/pkg/features"
 	"sigs.k8s.io/kueue/pkg/metrics"
 	"sigs.k8s.io/kueue/pkg/util/admissioncheck"
-	clientutil "sigs.k8s.io/kueue/pkg/util/client"
 	utilslices "sigs.k8s.io/kueue/pkg/util/slices"
 	stringsutils "sigs.k8s.io/kueue/pkg/util/strings"
 	"sigs.k8s.io/kueue/pkg/workload"
@@ -186,17 +184,8 @@ func (r *WorkloadReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
 	}
 
 	if workload.IsAdmitted(&wl) && workload.HasNodeToReplace(&wl) {
-		if !workload.HasTopologyAssignmentWithNodeToReplace(&wl) {
-			if err := clientutil.Patch(ctx, r.client, &wl, true, func() (bool, error) {
-				annotations := wl.GetAnnotations()
-				delete(annotations, kueuealpha.NodeToReplaceAnnotation)
-				wl.SetAnnotations(annotations)
-				r.log.V(3).Info("Deleting annotation from Workload", "annotation", kueuealpha.NodeToReplaceAnnotation)
-				return true, nil
-			}); err != nil {
-				return ctrl.Result{}, client.IgnoreNotFound(err)
-			}
-		}
+		log.V(3).Info("Skipping reconcile of a workload with nodes to replace", "nodesToReplace", wl.Status.NodesToReplace)
+		return ctrl.Result{}, nil
 	}
 
 	if workload.IsActive(&wl) {
diff --git a/pkg/controller/jobframework/reconciler.go b/pkg/controller/jobframework/reconciler.go
index 75fa8e0a0..04290201b 100644
--- a/pkg/controller/jobframework/reconciler.go
+++ b/pkg/controller/jobframework/reconciler.go
@@ -464,7 +464,7 @@ func (r *JobReconciler) ReconcileGenericJob(ctx context.Context, req ctrl.Reques
 		if err != nil {
 			if apierrors.IsAlreadyExists(err) {
 				log.V(3).Info("Handling job with no workload found an existing workload")
-				return ctrl.Result{Requeue: true}, nil
+				return ctrl.Result{RequeueAfter: time.Nanosecond}, nil
 			}
 			if IsUnretryableError(err) {
 				log.V(3).Info("Handling job with no workload", "unretryableError", err)
diff --git a/pkg/controller/jobs/deployment/deployment_webhook.go b/pkg/controller/jobs/deployment/deployment_webhook.go
index 515e966d4..5a2b71b59 100644
--- a/pkg/controller/jobs/deployment/deployment_webhook.go
+++ b/pkg/controller/jobs/deployment/deployment_webhook.go
@@ -131,7 +131,7 @@ func (wh *Webhook) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Ob
 	// or if the queue-name has been deleted.
 	isSuspended := oldDeployment.Status.ReadyReplicas == 0
 	if !isSuspended || newQueueName == "" {
-		allErrs = append(allErrs, apivalidation.ValidateImmutableField(oldQueueName, newQueueName, queueNameLabelPath)...)
+		allErrs = append(allErrs, apivalidation.ValidateImmutableField(newQueueName, oldQueueName, queueNameLabelPath)...)
 	}
 	if !isSuspended || jobframework.IsWorkloadPriorityClassNameEmpty(newDeployment.Object()) {
 		allErrs = append(allErrs, jobframework.ValidateUpdateForWorkloadPriorityClassName(oldDeployment.Object(), newDeployment.Object())...)
diff --git a/pkg/controller/jobs/job/job_webhook.go b/pkg/controller/jobs/job/job_webhook.go
index 1596ddbe8..9b110cc10 100644
--- a/pkg/controller/jobs/job/job_webhook.go
+++ b/pkg/controller/jobs/job/job_webhook.go
@@ -19,11 +19,9 @@ package job
 import (
 	"context"
 	"fmt"
-	"slices"
 	"strconv"
 
 	batchv1 "k8s.io/api/batch/v1"
-	corev1 "k8s.io/api/core/v1"
 	apivalidation "k8s.io/apimachinery/pkg/api/validation"
 	"k8s.io/apimachinery/pkg/labels"
 	"k8s.io/apimachinery/pkg/runtime"
@@ -39,6 +37,7 @@ import (
 	"sigs.k8s.io/kueue/pkg/controller/jobframework"
 	"sigs.k8s.io/kueue/pkg/controller/jobframework/webhook"
 	"sigs.k8s.io/kueue/pkg/features"
+	utilpod "sigs.k8s.io/kueue/pkg/util/pod"
 	"sigs.k8s.io/kueue/pkg/workloadslicing"
 )
 
@@ -64,13 +63,7 @@ func applyWorkloadSliceSchedulingGate(job *Job) {
 	if !features.Enabled(features.ElasticJobsViaWorkloadSlices) || !workloadslicing.Enabled(job.Object()) {
 		return
 	}
-	workloadSliceSchedulingGate := corev1.PodSchedulingGate{
-		Name: kueue.ElasticJobSchedulingGate,
-	}
-	if slices.Contains(job.Spec.Template.Spec.SchedulingGates, workloadSliceSchedulingGate) {
-		return
-	}
-	job.Spec.Template.Spec.SchedulingGates = append(job.Spec.Template.Spec.SchedulingGates, workloadSliceSchedulingGate)
+	utilpod.GateTemplate(&job.Spec.Template, kueue.ElasticJobSchedulingGate)
 }
 
 type JobWebhook struct {
diff --git a/pkg/controller/jobs/raycluster/raycluster_webhook.go b/pkg/controller/jobs/raycluster/raycluster_webhook.go
index 02b168732..071478ed8 100644
--- a/pkg/controller/jobs/raycluster/raycluster_webhook.go
+++ b/pkg/controller/jobs/raycluster/raycluster_webhook.go
@@ -19,8 +19,10 @@ package raycluster
 import (
 	"context"
 	"fmt"
+	"slices"
 
 	rayv1 "github.com/ray-project/kuberay/ray-operator/apis/ray/v1"
+	corev1 "k8s.io/api/core/v1"
 	"k8s.io/apimachinery/pkg/labels"
 	"k8s.io/apimachinery/pkg/runtime"
 	"k8s.io/apimachinery/pkg/util/validation/field"
@@ -35,7 +37,9 @@ import (
 	"sigs.k8s.io/kueue/pkg/controller/jobframework"
 	"sigs.k8s.io/kueue/pkg/controller/jobframework/webhook"
 	"sigs.k8s.io/kueue/pkg/features"
+	utilpod "sigs.k8s.io/kueue/pkg/util/pod"
 	"sigs.k8s.io/kueue/pkg/util/podset"
+	"sigs.k8s.io/kueue/pkg/workloadslicing"
 )
 
 var (
@@ -87,6 +91,20 @@ func (w *RayClusterWebhook) Default(ctx context.Context, obj runtime.Object) err
 		return err
 	}
 	jobframework.ApplyDefaultForManagedBy(job, w.queues, w.cache, log)
+
+	rjob := obj.(*rayv1.RayCluster)
+
+	if isAnElasticJob(rjob) {
+		// Ensure that the PodSchedulingGate is present in the RayCluster's pod Templates for its Head and all its Workers
+		utilpod.GateTemplate(&job.Spec.HeadGroupSpec.Template, kueuebeta.ElasticJobSchedulingGate)
+
+		for index := range job.Spec.WorkerGroupSpecs {
+			wgs := &job.Spec.WorkerGroupSpecs[index]
+
+			utilpod.GateTemplate(&wgs.Template, kueuebeta.ElasticJobSchedulingGate)
+		}
+	}
+
 	return nil
 }
 
@@ -106,6 +124,11 @@ func (w *RayClusterWebhook) ValidateCreate(ctx context.Context, obj runtime.Obje
 	return nil, validationErrs.ToAggregate()
 }
 
+// returns whether the RayCluster is an elastic job or not
+func isAnElasticJob(job *rayv1.RayCluster) bool {
+	return features.Enabled(features.ElasticJobsViaWorkloadSlices) && workloadslicing.Enabled(job.GetObjectMeta())
+}
+
 func (w *RayClusterWebhook) validateCreate(job *rayv1.RayCluster) (field.ErrorList, error) {
 	var allErrors field.ErrorList
 	kueueJob := (*RayCluster)(job)
@@ -114,10 +137,11 @@ func (w *RayClusterWebhook) validateCreate(job *rayv1.RayCluster) (field.ErrorLi
 		spec := &job.Spec
 		specPath := field.NewPath("spec")
 
-		// TODO revisit once Support dynamically sized (elastic) jobs #77 is implemented
-		// Should not use auto scaler. Once the resources are reserved by queue the cluster should do it's best to use them.
-		if ptr.Deref(spec.EnableInTreeAutoscaling, false) {
-			allErrors = append(allErrors, field.Invalid(specPath.Child("enableInTreeAutoscaling"), spec.EnableInTreeAutoscaling, "a kueue managed job should not use autoscaling"))
+		if isAnElasticJob(job) {
+			allErrors = append(allErrors, validateElasticJob(job)...)
+		} else if ptr.Deref(spec.EnableInTreeAutoscaling, false) {
+			// Should not use auto scaler. Once the resources are reserved by queue the cluster should do its best to use them.
+			allErrors = append(allErrors, field.Invalid(specPath.Child("enableInTreeAutoscaling"), spec.EnableInTreeAutoscaling, "a kueue managed job can use autoscaling only when the ElasticJobsViaWorkloadSlices feature gate is on and the job is an elastic job"))
 		}
 
 		// Should limit the worker count to 8 - 1 (max podSets num - cluster head)
@@ -145,6 +169,30 @@ func (w *RayClusterWebhook) validateCreate(job *rayv1.RayCluster) (field.ErrorLi
 	return allErrors, nil
 }
 
+func validateElasticJob(job *rayv1.RayCluster) field.ErrorList {
+	allErrors := field.ErrorList{}
+
+	specPath := field.NewPath("spec")
+
+	workloadSliceSchedulingGate := corev1.PodSchedulingGate{
+		Name: kueuebeta.ElasticJobSchedulingGate,
+	}
+
+	for index := range job.Spec.WorkerGroupSpecs {
+		wgs := &job.Spec.WorkerGroupSpecs[index]
+
+		if !slices.Contains(wgs.Template.Spec.SchedulingGates, workloadSliceSchedulingGate) {
+			allErrors = append(allErrors, field.Invalid(specPath.Child("workerGroupSpecs").Index(index).Child("template").Child("spec").Child("schedulingGates"), wgs.Template.Spec.SchedulingGates, "an elastic job must have the ElasticJobSchedulingGate"))
+		}
+	}
+
+	if !slices.Contains(job.Spec.HeadGroupSpec.Template.Spec.SchedulingGates, workloadSliceSchedulingGate) {
+		allErrors = append(allErrors, field.Invalid(specPath.Child("headGroupSpec").Child("template").Child("spec").Child("schedulingGates"), job.Spec.HeadGroupSpec.Template.Spec.SchedulingGates, "an elastic job must have the ElasticJobSchedulingGate"))
+	}
+
+	return allErrors
+}
+
 func (w *RayClusterWebhook) validateTopologyRequest(rayJob *RayCluster) (field.ErrorList, error) {
 	var allErrs field.ErrorList
 
diff --git a/pkg/controller/jobs/rayjob/rayjob_webhook.go b/pkg/controller/jobs/rayjob/rayjob_webhook.go
index d5cf7fdae..e9f3c0658 100644
--- a/pkg/controller/jobs/rayjob/rayjob_webhook.go
+++ b/pkg/controller/jobs/rayjob/rayjob_webhook.go
@@ -124,7 +124,7 @@ func (w *RayJobWebhook) validateCreate(job *rayv1.RayJob) (field.ErrorList, erro
 		clusterSpec := spec.RayClusterSpec
 		clusterSpecPath := specPath.Child("rayClusterSpec")
 
-		// Should not use auto scaler. Once the resources are reserved by queue the cluster should do it's best to use them.
+		// Should not use auto scaler. Once the resources are reserved by queue the cluster should do its best to use them.
 		if ptr.Deref(clusterSpec.EnableInTreeAutoscaling, false) {
 			allErrors = append(allErrors, field.Invalid(clusterSpecPath.Child("enableInTreeAutoscaling"), clusterSpec.EnableInTreeAutoscaling, "a kueue managed job should not use autoscaling"))
 		}
diff --git a/pkg/controller/jobs/statefulset/statefulset_webhook.go b/pkg/controller/jobs/statefulset/statefulset_webhook.go
index a5cf14395..bfb97b07d 100644
--- a/pkg/controller/jobs/statefulset/statefulset_webhook.go
+++ b/pkg/controller/jobs/statefulset/statefulset_webhook.go
@@ -142,7 +142,7 @@ func (wh *Webhook) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Ob
 	// or if the queue-name has been deleted.
 	isSuspended := oldStatefulSet.Status.ReadyReplicas == 0
 	if !isSuspended || newQueueName == "" {
-		allErrs = append(allErrs, apivalidation.ValidateImmutableField(oldQueueName, newQueueName, queueNameLabelPath)...)
+		allErrs = append(allErrs, apivalidation.ValidateImmutableField(newQueueName, oldQueueName, queueNameLabelPath)...)
 	}
 	if !isSuspended || jobframework.IsWorkloadPriorityClassNameEmpty(newStatefulSet.Object()) {
 		allErrs = append(allErrs, jobframework.ValidateUpdateForWorkloadPriorityClassName(
diff --git a/pkg/controller/tas/node_failure_controller.go b/pkg/controller/tas/node_failure_controller.go
index 47a19d55c..fd12c3248 100644
--- a/pkg/controller/tas/node_failure_controller.go
+++ b/pkg/controller/tas/node_failure_controller.go
@@ -20,6 +20,8 @@ import (
 	"context"
 	"errors"
 	"fmt"
+	"slices"
+	"strings"
 	"time"
 
 	"github.com/go-logr/logr"
@@ -42,19 +44,17 @@ import (
 	"sigs.k8s.io/controller-runtime/pkg/source"
 
 	config "sigs.k8s.io/kueue/apis/config/v1beta1"
-	kueuealpha "sigs.k8s.io/kueue/apis/kueue/v1alpha1"
 	kueue "sigs.k8s.io/kueue/apis/kueue/v1beta1"
 	"sigs.k8s.io/kueue/pkg/controller/core"
 	"sigs.k8s.io/kueue/pkg/controller/tas/indexer"
 	"sigs.k8s.io/kueue/pkg/features"
-	clientutil "sigs.k8s.io/kueue/pkg/util/client"
 	utilpod "sigs.k8s.io/kueue/pkg/util/pod"
 	utiltas "sigs.k8s.io/kueue/pkg/util/tas"
 	"sigs.k8s.io/kueue/pkg/workload"
 )
 
 const (
-	nodeMultipleFailuresEvictionMessageFormat = "Workload eviction triggered due to multiple TAS assigned node failures, including: %s, %s"
+	nodeMultipleFailuresEvictionMessageFormat = "Workload eviction triggered due to multiple TAS assigned node failures, including: %s"
 	podTerminationCheckPeriod                 = 1 * time.Second
 )
 
@@ -83,7 +83,7 @@ func (r *nodeFailureReconciler) Reconcile(ctx context.Context, req ctrl.Request)
 		if err != nil {
 			return ctrl.Result{}, err
 		}
-		return ctrl.Result{}, r.patchWorkloadsForNodeToReplace(ctx, req.Name, affectedWorkloads)
+		return ctrl.Result{}, r.handleFailedNode(ctx, req.Name, affectedWorkloads)
 	}
 	readyCondition := utiltas.GetNodeCondition(&node, corev1.NodeReady)
 	if readyCondition.Status == corev1.ConditionTrue {
@@ -91,7 +91,7 @@ func (r *nodeFailureReconciler) Reconcile(ctx context.Context, req ctrl.Request)
 		if err != nil {
 			return ctrl.Result{}, err
 		}
-		return ctrl.Result{}, r.removeNodeToReplaceAnnotation(ctx, req.Name, affectedWorkloads)
+		return ctrl.Result{}, r.handleHealthyNode(ctx, req.Name, affectedWorkloads)
 	}
 	if features.Enabled(features.TASReplaceNodeOnPodTermination) {
 		return r.reconcileForReplaceNodeOnPodTermination(ctx, req.Name)
@@ -105,7 +105,7 @@ func (r *nodeFailureReconciler) Reconcile(ctx context.Context, req ctrl.Request)
 	if err != nil {
 		return ctrl.Result{}, err
 	}
-	patchErr := r.patchWorkloadsForNodeToReplace(ctx, req.Name, affectedWorkloads)
+	patchErr := r.handleFailedNode(ctx, req.Name, affectedWorkloads)
 	return ctrl.Result{}, patchErr
 }
 
@@ -218,13 +218,15 @@ func (r *nodeFailureReconciler) getWorkloadsForImmediateReplacement(ctx context.
 	return affectedWorkloads, nil
 }
 
-// evictWorkload idempotently evicts the workload when the node has failed.
+// evictWorkloadIfNeeded idempotently evicts the workload when the node has failed.
 // It returns whether the node was evicted, and whether an error was encountered.
-func (r *nodeFailureReconciler) evictWorkload(ctx context.Context, log logr.Logger, wl *kueue.Workload, nodeName string) (bool, error) {
-	if failedNode, ok := wl.Annotations[kueuealpha.NodeToReplaceAnnotation]; ok && failedNode != nodeName && !workload.IsEvicted(wl) {
-		log = log.WithValues("failedNode", failedNode)
+func (r *nodeFailureReconciler) evictWorkloadIfNeeded(ctx context.Context, wl *kueue.Workload, nodeName string) (bool, error) {
+	nodesToReplace := wl.Status.NodesToReplace
+	if len(nodesToReplace) > 0 && !slices.Contains(nodesToReplace, nodeName) && !workload.IsEvicted(wl) {
+		log := r.log.WithValues("failedNodes", nodesToReplace)
 		log.V(3).Info("Evicting workload due to multiple node failures")
-		evictionMsg := fmt.Sprintf(nodeMultipleFailuresEvictionMessageFormat, failedNode, nodeName)
+		allFailedNodes := append(slices.Clone(nodesToReplace), nodeName)
+		evictionMsg := fmt.Sprintf(nodeMultipleFailuresEvictionMessageFormat, strings.Join(allFailedNodes, ", "))
 		if evictionErr := workload.Evict(ctx, r.client, r.recorder, wl, kueue.WorkloadEvictedDueToNodeFailures, "", evictionMsg, r.clock); evictionErr != nil {
 			log.V(2).Error(evictionErr, "Failed to complete eviction process")
 			return false, evictionErr
@@ -235,9 +237,9 @@ func (r *nodeFailureReconciler) evictWorkload(ctx context.Context, log logr.Logg
 	return false, nil
 }
 
-// patchWorkloadsForNodeToReplace finds workloads with pods on the specified node
+// handleFailedNode finds workloads with pods on the specified node
 // and patches their status to indicate the node is to replace.
-func (r *nodeFailureReconciler) patchWorkloadsForNodeToReplace(ctx context.Context, nodeName string, affectedWorkloads sets.Set[types.NamespacedName]) error {
+func (r *nodeFailureReconciler) handleFailedNode(ctx context.Context, nodeName string, affectedWorkloads sets.Set[types.NamespacedName]) error {
 	var workloadProcessingErrors []error
 	for wlKey := range affectedWorkloads {
 		log := r.log.WithValues("workload", wlKey, "nodeName", nodeName)
@@ -252,46 +254,19 @@ func (r *nodeFailureReconciler) patchWorkloadsForNodeToReplace(ctx context.Conte
 			}
 			continue
 		}
-
-		// evict workload when annotation present.
-		evictedNow, err := r.evictWorkload(ctx, log, &wl, nodeName)
+		// evict workload when workload already has a different node marked for replacement
+		evictedNow, err := r.evictWorkloadIfNeeded(ctx, &wl, nodeName)
 		if err != nil {
 			workloadProcessingErrors = append(workloadProcessingErrors, err)
 			continue
 		}
-		// re-fetch workload if we evicted it.
-		if evictedNow {
-			if err := r.client.Get(ctx, wlKey, &wl); err != nil {
-				log.V(2).Error(err, "Failed to re-fetch workload after eviction")
+		if !evictedNow && !workload.IsEvicted(&wl) {
+			if err := r.addNodeToReplace(ctx, wl, nodeName); err != nil {
+				log.V(2).Error(err, "Failed to add node to nodesToReplace")
 				workloadProcessingErrors = append(workloadProcessingErrors, err)
 				continue
 			}
 		}
-
-		// update annotations.
-		err = clientutil.Patch(ctx, r.client, &wl, true, func() (bool, error) {
-			if wl.Annotations == nil {
-				wl.Annotations = make(map[string]string)
-			}
-			failedNode, ok := wl.Annotations[kueuealpha.NodeToReplaceAnnotation]
-			if !ok {
-				log.V(4).Info(fmt.Sprintf("Adding node to %s annotation", kueuealpha.NodeToReplaceAnnotation))
-				wl.Annotations[kueuealpha.NodeToReplaceAnnotation] = nodeName
-				return true, nil
-			}
-			if evictedNow || workload.IsEvicted(&wl) {
-				log.V(4).Info(fmt.Sprintf("Removing node from %s annotation", kueuealpha.NodeToReplaceAnnotation), "failedNode", failedNode)
-				delete(wl.Annotations, kueuealpha.NodeToReplaceAnnotation)
-				return true, nil
-			}
-			return false, nil
-		})
-		if err != nil {
-			log.V(2).Error(err, "Failed to patch workload annotation")
-			workloadProcessingErrors = append(workloadProcessingErrors, err)
-			continue
-		}
-		log.V(3).Info("Successfully patched workload annotation", "nodesToReplaceAnnotation", wl.Annotations[kueuealpha.NodeToReplaceAnnotation])
 	}
 	if len(workloadProcessingErrors) > 0 {
 		return errors.Join(workloadProcessingErrors...)
@@ -308,48 +283,56 @@ func (r *nodeFailureReconciler) reconcileForReplaceNodeOnPodTermination(ctx cont
 		return ctrl.Result{RequeueAfter: podTerminationCheckPeriod}, nil
 	default:
 		r.log.V(3).Info("Node is not ready and has only terminating or failed pods. Marking as failed immediately", "nodeName", nodeName)
-		patchErr := r.patchWorkloadsForNodeToReplace(ctx, nodeName, workloads)
+		patchErr := r.handleFailedNode(ctx, nodeName, workloads)
 		return ctrl.Result{}, patchErr
 	}
 }
 
-// removeNodeToReplaceAnnotation finds workloads with the specified node in the NodeToReplaceAnnotation
-// and removes the annotation
-func (r *nodeFailureReconciler) removeNodeToReplaceAnnotation(ctx context.Context, nodeName string, affectedWorkloads sets.Set[types.NamespacedName]) error {
+// handleHealthyNode clears the nodesToReplace field for each of the specified workloads.
+func (r *nodeFailureReconciler) handleHealthyNode(ctx context.Context, nodeName string, affectedWorkloads sets.Set[types.NamespacedName]) error {
 	var workloadProcessingErrors []error
-	log := ctrl.LoggerFrom(ctx)
 	for wlKey := range affectedWorkloads {
-		log = log.WithValues("workload", wlKey)
-		// fetch workload.
 		var wl kueue.Workload
 		if err := r.client.Get(ctx, wlKey, &wl); err != nil {
 			if apierrors.IsNotFound(err) {
-				log.V(4).Info("Workload not found, skipping")
+				r.log.V(4).Info("Workload not found, skipping")
 			} else {
-				log.Error(err, "Failed to get workload")
+				r.log.Error(err, "Failed to get workload")
 				workloadProcessingErrors = append(workloadProcessingErrors, err)
 			}
 			continue
 		}
 
-		if wl.Annotations != nil && wl.Annotations[kueuealpha.NodeToReplaceAnnotation] != nodeName {
+		if !slices.Contains(wl.Status.NodesToReplace, nodeName) {
 			continue
 		}
 
-		err := clientutil.Patch(ctx, r.client, &wl, true, func() (bool, error) {
-			log.V(4).Info(fmt.Sprintf("Removing node from %s annotation", kueuealpha.NodeToReplaceAnnotation), "failedNode", nodeName)
-			delete(wl.Annotations, kueuealpha.NodeToReplaceAnnotation)
-			return true, nil
-		})
-		if err != nil {
-			log.Error(err, "Failed to patch workload annotation")
+		r.log.V(4).Info("Remove node from nodesToReplace", "nodeName", nodeName)
+		if err := r.removeNodeToReplace(ctx, wl, nodeName); err != nil {
+			r.log.Error(err, "Failed to patch workload status")
 			workloadProcessingErrors = append(workloadProcessingErrors, err)
 			continue
 		}
-		log.V(3).Info("Successfully cleared the NodeToReplace annotation")
+		r.log.V(3).Info("Successfully removed node from the nodesToReplace field", "nodeName", nodeName)
 	}
 	if len(workloadProcessingErrors) > 0 {
 		return errors.Join(workloadProcessingErrors...)
 	}
 	return nil
 }
+
+func (r *nodeFailureReconciler) removeNodeToReplace(ctx context.Context, wl kueue.Workload, nodeName string) error {
+	if slices.Contains(wl.Status.NodesToReplace, nodeName) {
+		wl.Status.NodesToReplace = slices.DeleteFunc(wl.Status.NodesToReplace, func(n string) bool { return n == nodeName })
+		return workload.ApplyAdmissionStatus(ctx, r.client, &wl, true, r.clock)
+	}
+	return nil
+}
+
+func (r *nodeFailureReconciler) addNodeToReplace(ctx context.Context, wl kueue.Workload, nodeName string) error {
+	if !slices.Contains(wl.Status.NodesToReplace, nodeName) {
+		wl.Status.NodesToReplace = append(wl.Status.NodesToReplace, nodeName)
+		return workload.ApplyAdmissionStatus(ctx, r.client, &wl, true, r.clock)
+	}
+	return nil
+}
diff --git a/pkg/features/kube_features.go b/pkg/features/kube_features.go
index 99e3db500..a2451634e 100644
--- a/pkg/features/kube_features.go
+++ b/pkg/features/kube_features.go
@@ -35,12 +35,6 @@ const (
 	// Enables partial admission.
 	PartialAdmission featuregate.Feature = "PartialAdmission"
 
-	// owner: @stuton
-	// kep: https://github.com/kubernetes-sigs/kueue/tree/main/keps/168-pending-workloads-visibility
-	//
-	// Enables queue visibility.
-	QueueVisibility featuregate.Feature = "QueueVisibility"
-
 	// owner: @KunWuLuan
 	// kep: https://github.com/kubernetes-sigs/kueue/tree/main/keps/582-preempt-based-on-flavor-order
 	//
@@ -204,10 +198,7 @@ var defaultVersionedFeatureGates = map[featuregate.Feature]featuregate.Versioned
 		{Version: version.MustParse("0.4"), Default: false, PreRelease: featuregate.Alpha},
 		{Version: version.MustParse("0.5"), Default: true, PreRelease: featuregate.Beta},
 	},
-	QueueVisibility: {
-		{Version: version.MustParse("0.5"), Default: false, PreRelease: featuregate.Alpha},
-		{Version: version.MustParse("0.9"), Default: false, PreRelease: featuregate.Deprecated},
-	},
+
 	FlavorFungibility: {
 		{Version: version.MustParse("0.5"), Default: true, PreRelease: featuregate.Beta},
 	},
diff --git a/pkg/scheduler/flavorassigner/flavorassigner.go b/pkg/scheduler/flavorassigner/flavorassigner.go
index c657c0b52..45c2b0cb1 100644
--- a/pkg/scheduler/flavorassigner/flavorassigner.go
+++ b/pkg/scheduler/flavorassigner/flavorassigner.go
@@ -541,7 +541,7 @@ func (a *FlavorAssigner) assignFlavors(log logr.Logger, counts []int32) Assignme
 				// No need to compute again.
 				continue
 			}
-			flavors, status := a.findFlavorForPodSetResource(log, psIDs, requests, resName, assignment.Usage.Quota)
+			flavors, status := a.findFlavorForPodSets(log, psIDs, requests, resName, assignment.Usage.Quota)
 			if status.IsError() || len(flavors) == 0 {
 				groupFlavors = nil
 				groupStatus = *status
@@ -618,12 +618,12 @@ func (a *Assignment) append(requests resources.Requests, psAssignment *PodSetAss
 	a.LastState.LastTriedFlavorIdx = append(a.LastState.LastTriedFlavorIdx, flavorIdx)
 }
 
-// findFlavorForPodSetResource finds the flavor which can satisfy the podSet request
+// findFlavorForPodSets finds the flavor which can satisfy all the PodSet requests
 // for all resources in the same group as resName.
 // Returns the chosen flavor, along with the information about resources that need to be borrowed.
 // If the flavor cannot be immediately assigned, it returns a status with
 // reasons or failure.
-func (a *FlavorAssigner) findFlavorForPodSetResource(
+func (a *FlavorAssigner) findFlavorForPodSets(
 	log logr.Logger,
 	psIDs []int,
 	requests resources.Requests,
@@ -657,43 +657,12 @@ func (a *FlavorAssigner) findFlavorForPodSetResource(
 	for ; idx < len(resourceGroup.Flavors); idx++ {
 		attemptedFlavorIdx = idx
 		fName := resourceGroup.Flavors[idx]
-		flavor, exist := a.resourceFlavors[fName]
-		if !exist {
-			log.Error(nil, "Flavor not found", "Flavor", fName)
-			status.appendf("flavor %s not found", fName)
-			continue
-		}
 
-		var flavorUnmatchMessage *string
-		for psIdx, psID := range psIDs {
-			if features.Enabled(features.TopologyAwareScheduling) {
-				ps := &a.wl.Obj.Spec.PodSets[psID]
-				flavorUnmatchMessage = checkPodSetAndFlavorMatchForTAS(a.cq, ps, flavor)
-				if flavorUnmatchMessage != nil {
-					log.Error(nil, *flavorUnmatchMessage)
-					break
-				}
-			}
-			podSpec := podSets[psIdx].Template.Spec
-			taint, untolerated := corev1helpers.FindMatchingUntoleratedTaint(flavor.Spec.NodeTaints, append(podSpec.Tolerations, flavor.Spec.Tolerations...), func(t *corev1.Taint) bool {
-				return t.Effect == corev1.TaintEffectNoSchedule || t.Effect == corev1.TaintEffectNoExecute
-			})
-			if untolerated {
-				flavorUnmatchMessage = ptr.To(fmt.Sprintf("untolerated taint %s in flavor %s", taint, fName))
-				break
+		if fit, err := a.checkFlavorForPodSets(log, fName, psIDs, podSets, selectors, status); !fit {
+			if err != nil {
+				status.err = err
+				return nil, status
 			}
-			selector := selectors[psIdx]
-			if match, err := selector.Match(&corev1.Node{ObjectMeta: metav1.ObjectMeta{Labels: flavor.Spec.NodeLabels}}); !match || err != nil {
-				if err != nil {
-					status.err = err
-					return nil, status
-				}
-				flavorUnmatchMessage = ptr.To(fmt.Sprintf("flavor %s doesn't match node affinity", fName))
-				break
-			}
-		}
-		if flavorUnmatchMessage != nil {
-			status.reasons = append(status.reasons, *flavorUnmatchMessage)
 			continue
 		}
 		assignments := make(ResourceAssignment, len(requests))
@@ -776,6 +745,51 @@ func (a *FlavorAssigner) findFlavorForPodSetResource(
 	return bestAssignment, status
 }
 
+func (a *FlavorAssigner) checkFlavorForPodSets(
+	log logr.Logger,
+	flavorName kueue.ResourceFlavorReference,
+	psIDs []int,
+	podSets []*kueue.PodSet,
+	selectors []nodeaffinity.RequiredNodeAffinity,
+	status *Status,
+) (bool, error) {
+	flavor, exist := a.resourceFlavors[flavorName]
+	if !exist {
+		log.Error(nil, "Flavor not found", "Flavor", flavorName)
+		status.appendf("flavor %s not found", flavorName)
+		return false, nil
+	}
+
+	for psIdx, psID := range psIDs {
+		if features.Enabled(features.TopologyAwareScheduling) {
+			ps := &a.wl.Obj.Spec.PodSets[psID]
+			if message := checkPodSetAndFlavorMatchForTAS(a.cq, ps, flavor); message != nil {
+				log.Error(nil, *message)
+				status.appendf("%s", *message)
+				return false, nil
+			}
+		}
+		podSpec := podSets[psIdx].Template.Spec
+		taint, untolerated := corev1helpers.FindMatchingUntoleratedTaint(flavor.Spec.NodeTaints, append(podSpec.Tolerations, flavor.Spec.Tolerations...), func(t *corev1.Taint) bool {
+			return t.Effect == corev1.TaintEffectNoSchedule || t.Effect == corev1.TaintEffectNoExecute
+		})
+		if untolerated {
+			status.appendf("untolerated taint %s in flavor %s", taint, flavorName)
+			return false, nil
+		}
+		selector := selectors[psIdx]
+		if match, err := selector.Match(&corev1.Node{ObjectMeta: metav1.ObjectMeta{Labels: flavor.Spec.NodeLabels}}); !match || err != nil {
+			if err != nil {
+				status.err = err
+				return false, err
+			}
+			status.appendf("flavor %s doesn't match node affinity", flavorName)
+			return false, nil
+		}
+	}
+	return true, nil
+}
+
 func shouldTryNextFlavor(representativeMode granularMode, flavorFungibility kueue.FlavorFungibility) bool {
 	policyPreempt := flavorFungibility.WhenCanPreempt
 	policyBorrow := flavorFungibility.WhenCanBorrow
diff --git a/pkg/scheduler/flavorassigner/tas_flavorassigner.go b/pkg/scheduler/flavorassigner/tas_flavorassigner.go
index 770af894e..0456f6399 100644
--- a/pkg/scheduler/flavorassigner/tas_flavorassigner.go
+++ b/pkg/scheduler/flavorassigner/tas_flavorassigner.go
@@ -19,10 +19,10 @@ package flavorassigner
 import (
 	"errors"
 	"fmt"
+	"slices"
 
 	"k8s.io/utils/ptr"
 
-	kueuealpha "sigs.k8s.io/kueue/apis/kueue/v1alpha1"
 	kueue "sigs.k8s.io/kueue/apis/kueue/v1beta1"
 	schdcache "sigs.k8s.io/kueue/pkg/cache/scheduler"
 	"sigs.k8s.io/kueue/pkg/workload"
@@ -60,9 +60,9 @@ func (psa *PodSetAssignment) HasFailedNode(wl *workload.Info) bool {
 	if !workload.HasNodeToReplace(wl.Obj) {
 		return false
 	}
-	failedNode := wl.Obj.Annotations[kueuealpha.NodeToReplaceAnnotation]
+	nodesToReplace := wl.Obj.Status.NodesToReplace
 	for _, domain := range psa.TopologyAssignment.Domains {
-		if domain.Values[len(domain.Values)-1] == failedNode {
+		if slices.Contains(nodesToReplace, domain.Values[len(domain.Values)-1]) {
 			return true
 		}
 	}
diff --git a/pkg/scheduler/scheduler.go b/pkg/scheduler/scheduler.go
index d788dc493..a4d767fa5 100644
--- a/pkg/scheduler/scheduler.go
+++ b/pkg/scheduler/scheduler.go
@@ -38,7 +38,6 @@ import (
 	"sigs.k8s.io/controller-runtime/pkg/client"
 
 	config "sigs.k8s.io/kueue/apis/config/v1beta1"
-	kueuealpha "sigs.k8s.io/kueue/apis/kueue/v1alpha1"
 	kueue "sigs.k8s.io/kueue/apis/kueue/v1beta1"
 	qcache "sigs.k8s.io/kueue/pkg/cache/queue"
 	schdcache "sigs.k8s.io/kueue/pkg/cache/scheduler"
@@ -194,12 +193,6 @@ func (s *Scheduler) schedule(ctx context.Context) wait.SpeedSignal {
 	log := ctrl.LoggerFrom(ctx).WithValues("schedulingCycle", s.schedulingCycle)
 	ctx = ctrl.LoggerInto(ctx, log)
 
-	var snapshotOpts []schdcache.SnapshotOption
-	if afs.Enabled(s.admissionFairSharing) {
-		s.queues.RebuildClusterQueuesWithEntryPenalties()
-		snapshotOpts = append(snapshotOpts, schdcache.WithAfsEntryPenalties(s.queues.GetAfsEntryPenalties()))
-	}
-
 	// 1. Get the heads from the queues, including their desired clusterQueue.
 	// This operation blocks while the queues are empty.
 	headWorkloads := s.queues.Heads(ctx)
@@ -210,6 +203,10 @@ func (s *Scheduler) schedule(ctx context.Context) wait.SpeedSignal {
 	startTime := s.clock.Now()
 
 	// 2. Take a snapshot of the cache.
+	var snapshotOpts []schdcache.SnapshotOption
+	if afs.Enabled(s.admissionFairSharing) {
+		snapshotOpts = append(snapshotOpts, schdcache.WithAfsEntryPenalties(s.queues.GetAfsEntryPenalties()))
+	}
 	snapshot, err := s.cache.Snapshot(ctx, snapshotOpts...)
 	if err != nil {
 		log.Error(err, "failed to build snapshot for scheduling")
@@ -565,13 +562,10 @@ func (s *Scheduler) getInitialAssignments(log logr.Logger, wl *workload.Info, sn
 
 func (s *Scheduler) evictWorkloadAfterFailedTASReplacement(ctx context.Context, log logr.Logger, wl *kueue.Workload) error {
 	log.V(3).Info("Evicting workload after failed try to find a node replacement; TASFailedNodeReplacementFailFast enabled")
-	msg := fmt.Sprintf("Workload was evicted as there was no replacement for a failed node: %s", workload.NodeToReplace(wl))
+	msg := fmt.Sprintf("Workload was evicted as there was no replacement for a failed node: %s", wl.Status.NodesToReplace[0])
 	if err := workload.Evict(ctx, s.client, s.recorder, wl, kueue.WorkloadEvictedDueToNodeFailures, "", msg, s.clock); err != nil {
 		return err
 	}
-	if err := workload.RemoveAnnotation(ctx, s.client, wl, kueuealpha.NodeToReplaceAnnotation); err != nil {
-		return fmt.Errorf("failed to remove annotation for node replacement %s", kueuealpha.NodeToReplaceAnnotation)
-	}
 	return nil
 }
 
@@ -630,6 +624,11 @@ func (s *Scheduler) admit(ctx context.Context, e *entry, cq *schdcache.ClusterQu
 		s.queues.NotifyWorkloadUpdateWatchers(e.Obj, newWorkload)
 	}
 
+	if features.Enabled(features.TopologyAwareScheduling) && len(e.Obj.Status.NodesToReplace) > 0 {
+		log.V(5).Info("Clearing the topology assignment recovery field from the workload status after successful recovery")
+		newWorkload.Status.NodesToReplace = nil
+	}
+
 	s.admissionRoutineWrapper.Run(func() {
 		err := s.applyAdmission(ctx, newWorkload)
 		if err == nil {
diff --git a/pkg/util/admissioncheck/admissioncheck.go b/pkg/util/admissioncheck/admissioncheck.go
index b7db98faa..ea0d05fb4 100644
--- a/pkg/util/admissioncheck/admissioncheck.go
+++ b/pkg/util/admissioncheck/admissioncheck.go
@@ -172,3 +172,14 @@ func NewAdmissionChecks(cq *kueue.ClusterQueue) map[kueue.AdmissionCheckReferenc
 	}
 	return checks
 }
+
+// FindAdmissionCheck - returns a pointer to the check identified by checkName if found in checks.
+func FindAdmissionCheck(checks []kueue.AdmissionCheckState, checkName kueue.AdmissionCheckReference) *kueue.AdmissionCheckState {
+	for i := range checks {
+		if checks[i].Name == checkName {
+			return &checks[i]
+		}
+	}
+
+	return nil
+}
diff --git a/pkg/util/pod/pod.go b/pkg/util/pod/pod.go
index 7837e447c..fdfbf4260 100644
--- a/pkg/util/pod/pod.go
+++ b/pkg/util/pod/pod.go
@@ -32,13 +32,13 @@ import (
 
 // HasGate checks if the pod has a scheduling gate with a specified name.
 func HasGate(pod *corev1.Pod, gateName string) bool {
-	return gateIndex(pod, gateName) >= 0
+	return gateIndex(&pod.Spec, gateName) >= 0
 }
 
 // Ungate removes scheduling gate from the Pod if present.
 // Returns true if the pod has been updated and false otherwise.
 func Ungate(pod *corev1.Pod, gateName string) bool {
-	if idx := gateIndex(pod, gateName); idx >= 0 {
+	if idx := gateIndex(&pod.Spec, gateName); idx >= 0 {
 		pod.Spec.SchedulingGates = slices.Delete(pod.Spec.SchedulingGates, idx, idx+1)
 		return true
 	}
@@ -48,8 +48,20 @@ func Ungate(pod *corev1.Pod, gateName string) bool {
 // Gate adds scheduling gate from the Pod if present.
 // Returns true if the pod has been updated and false otherwise.
 func Gate(pod *corev1.Pod, gateName string) bool {
-	if !HasGate(pod, gateName) {
-		pod.Spec.SchedulingGates = append(pod.Spec.SchedulingGates, corev1.PodSchedulingGate{
+	return gateSpec(&pod.Spec, gateName)
+}
+
+// GateTemplate adds scheduling gate to the PodTemplate.
+// Returns true if the PodTemplate has been updated and false otherwise.
+func GateTemplate(template *corev1.PodTemplateSpec, gateName string) bool {
+	return gateSpec(&template.Spec, gateName)
+}
+
+// Gate adds scheduling gate to the PodSpec.
+// Returns true if the PodSpec has been updated and false otherwise.
+func gateSpec(podSpec *corev1.PodSpec, gateName string) bool {
+	if gateIndex(podSpec, gateName) < 0 {
+		podSpec.SchedulingGates = append(podSpec.SchedulingGates, corev1.PodSchedulingGate{
 			Name: gateName,
 		})
 		return true
@@ -59,8 +71,8 @@ func Gate(pod *corev1.Pod, gateName string) bool {
 
 // gateIndex returns the index of the Kueue scheduling gate for corev1.Pod.
 // If the scheduling gate is not found, returns -1.
-func gateIndex(p *corev1.Pod, gateName string) int {
-	return slices.IndexFunc(p.Spec.SchedulingGates, func(g corev1.PodSchedulingGate) bool {
+func gateIndex(spec *corev1.PodSpec, gateName string) int {
+	return slices.IndexFunc(spec.SchedulingGates, func(g corev1.PodSchedulingGate) bool {
 		return g.Name == gateName
 	})
 }
diff --git a/pkg/util/resource/resource.go b/pkg/util/resource/resource.go
index 836e8745f..dcb283a39 100644
--- a/pkg/util/resource/resource.go
+++ b/pkg/util/resource/resource.go
@@ -115,3 +115,17 @@ func MulByFloat(q corev1.ResourceList, f float64) corev1.ResourceList {
 	}
 	return ret
 }
+
+func IsZero(rl corev1.ResourceList) bool {
+	if len(rl) != 0 {
+		return false
+	}
+
+	for _, qty := range rl {
+		if !qty.IsZero() {
+			return false
+		}
+	}
+
+	return true
+}
diff --git a/pkg/webhooks/workload_webhook.go b/pkg/webhooks/workload_webhook.go
index e72170077..af6184ca1 100644
--- a/pkg/webhooks/workload_webhook.go
+++ b/pkg/webhooks/workload_webhook.go
@@ -301,10 +301,8 @@ func validateAdmissionUpdate(new, old *kueue.Admission, path *field.Path) field.
 		if len(new.PodSetAssignments) != len(old.PodSetAssignments) {
 			return apivalidation.ValidateImmutableField(new, old, path)
 		}
-		// Allow to update (set) TopologyAssignment when DelayedTopologyRequest
-		// transitions from Pending to Ready.
+		// Allow to update (set) TopologyAssignments
 		for i := range new.PodSetAssignments {
-			// allow to update TopologyAssignments
 			old.PodSetAssignments[i].TopologyAssignment = new.PodSetAssignments[i].TopologyAssignment
 			old.PodSetAssignments[i].DelayedTopologyRequest = new.PodSetAssignments[i].DelayedTopologyRequest
 		}
diff --git a/pkg/workload/admissionchecks.go b/pkg/workload/admissionchecks.go
index 9e65dd087..44fadfda1 100644
--- a/pkg/workload/admissionchecks.go
+++ b/pkg/workload/admissionchecks.go
@@ -25,6 +25,7 @@ import (
 	"k8s.io/utils/clock"
 
 	kueue "sigs.k8s.io/kueue/apis/kueue/v1beta1"
+	"sigs.k8s.io/kueue/pkg/util/admissioncheck"
 )
 
 // SyncAdmittedCondition sync the state of the Admitted condition based on the
@@ -81,17 +82,6 @@ func SyncAdmittedCondition(w *kueue.Workload, now time.Time) bool {
 	return apimeta.SetStatusCondition(&w.Status.Conditions, newCondition)
 }
 
-// FindAdmissionCheck - returns a pointer to the check identified by checkName if found in checks.
-func FindAdmissionCheck(checks []kueue.AdmissionCheckState, checkName kueue.AdmissionCheckReference) *kueue.AdmissionCheckState {
-	for i := range checks {
-		if checks[i].Name == checkName {
-			return &checks[i]
-		}
-	}
-
-	return nil
-}
-
 // resetChecksOnEviction sets all AdmissionChecks to Pending
 func resetChecksOnEviction(w *kueue.Workload, now time.Time) {
 	checks := w.Status.AdmissionChecks
@@ -113,7 +103,7 @@ func SetAdmissionCheckState(checks *[]kueue.AdmissionCheckState, newCheck kueue.
 	if checks == nil {
 		return
 	}
-	existingCondition := FindAdmissionCheck(*checks, newCheck.Name)
+	existingCondition := admissioncheck.FindAdmissionCheck(*checks, newCheck.Name)
 	if existingCondition == nil {
 		if newCheck.LastTransitionTime.IsZero() {
 			newCheck.LastTransitionTime = metav1.NewTime(clock.Now())
diff --git a/pkg/workload/workload.go b/pkg/workload/workload.go
index a10c58369..765462252 100644
--- a/pkg/workload/workload.go
+++ b/pkg/workload/workload.go
@@ -42,7 +42,6 @@ import (
 	"sigs.k8s.io/controller-runtime/pkg/log"
 
 	config "sigs.k8s.io/kueue/apis/config/v1beta1"
-	kueuealpha "sigs.k8s.io/kueue/apis/kueue/v1alpha1"
 	kueue "sigs.k8s.io/kueue/apis/kueue/v1beta1"
 	"sigs.k8s.io/kueue/pkg/constants"
 	"sigs.k8s.io/kueue/pkg/features"
@@ -826,6 +825,7 @@ func admissionStatusPatch(w *kueue.Workload, wlCopy *kueue.Workload) {
 	}
 	wlCopy.Status.ClusterName = w.Status.ClusterName
 	wlCopy.Status.NominatedClusterNames = w.Status.NominatedClusterNames
+	wlCopy.Status.NodesToReplace = w.Status.NodesToReplace
 }
 
 func admissionChecksStatusPatch(w *kueue.Workload, wlCopy *kueue.Workload, c clock.Clock) {
@@ -968,34 +968,19 @@ func HasConditionWithTypeAndReason(w *kueue.Workload, cond *metav1.Condition) bo
 }
 
 func HasNodeToReplace(w *kueue.Workload) bool {
-	if w == nil {
-		return false
-	}
-	annotations := w.GetAnnotations()
-	_, found := annotations[kueuealpha.NodeToReplaceAnnotation]
-	return found
-}
-
-func NodeToReplace(w *kueue.Workload) string {
-	if !HasNodeToReplace(w) {
-		return ""
-	}
-	annotations := w.GetAnnotations()
-	return annotations[kueuealpha.NodeToReplaceAnnotation]
+	return w != nil && len(w.Status.NodesToReplace) > 0
 }
 
 func HasTopologyAssignmentWithNodeToReplace(w *kueue.Workload) bool {
 	if !HasNodeToReplace(w) || !IsAdmitted(w) {
 		return false
 	}
-	annotations := w.GetAnnotations()
-	failedNode := annotations[kueuealpha.NodeToReplaceAnnotation]
 	for _, psa := range w.Status.Admission.PodSetAssignments {
 		if psa.TopologyAssignment == nil {
 			continue
 		}
 		for _, domain := range psa.TopologyAssignment.Domains {
-			if domain.Values[len(domain.Values)-1] == failedNode {
+			if slices.Contains(w.Status.NodesToReplace, domain.Values[len(domain.Values)-1]) {
 				return true
 			}
 		}
@@ -1110,6 +1095,7 @@ func prepareForEviction(w *kueue.Workload, now time.Time, reason, message string
 	SetEvictedCondition(w, reason, message)
 	resetClusterNomination(w)
 	resetChecksOnEviction(w, now)
+	resetNodesToReplace(w)
 }
 
 func resetClusterNomination(w *kueue.Workload) {
@@ -1117,6 +1103,10 @@ func resetClusterNomination(w *kueue.Workload) {
 	w.Status.NominatedClusterNames = nil
 }
 
+func resetNodesToReplace(w *kueue.Workload) {
+	w.Status.NodesToReplace = nil
+}
+
 func reportEvictedWorkload(recorder record.EventRecorder, wl *kueue.Workload, cqName kueue.ClusterQueueReference, reason, underlyingCause, message string) {
 	metrics.ReportEvictedWorkloads(cqName, reason, underlyingCause)
 	if podsReadyToEvictionTime := workloadsWithPodsReadyToEvictedTime(wl); podsReadyToEvictionTime != nil {
diff --git a/site/content/en/docs/concepts/elastic_workload.md b/site/content/en/docs/concepts/elastic_workload.md
index 9bffc0ff9..ab81ceaed 100644
--- a/site/content/en/docs/concepts/elastic_workload.md
+++ b/site/content/en/docs/concepts/elastic_workload.md
@@ -62,7 +62,9 @@ metadata:
 
 ## Limitations
 
-* Currently available only for `batch/v1.Job` workloads.
+* Currently available only for the following workloads: 
+   * `batch/v1.Job`
+   * `ray.io/v1.RayCluster`
 * 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:
diff --git a/site/content/en/docs/contribution_guidelines/testing.md b/site/content/en/docs/contribution_guidelines/testing.md
index 9c0109f07..b07dbf3dd 100644
--- a/site/content/en/docs/contribution_guidelines/testing.md
+++ b/site/content/en/docs/contribution_guidelines/testing.md
@@ -122,7 +122,7 @@ or from VSCode.
 ### Use Ginkgo --focus arg
 ```shell
 GINKGO_ARGS="--focus=Scheduler" make test-integration
-GINKGO_ARGS="--focus=Creating a Pod requesting TAS" make test-e2e
+GINKGO_ARGS="--focus='Creating a Pod requesting TAS'" make test-e2e
 ```
 ### Use ginkgo.FIt
 If you want to focus on specific tests, you can change
diff --git a/site/content/en/docs/installation/_index.md b/site/content/en/docs/installation/_index.md
index 79b141178..d07424898 100644
--- a/site/content/en/docs/installation/_index.md
+++ b/site/content/en/docs/installation/_index.md
@@ -42,7 +42,7 @@ Use [kube-prometheus](https://github.com/prometheus-operator/kube-prometheus)
 if you don't have your own monitoring system.
 
 The webhook server in kueue uses an internal cert management for provisioning certificates. If you want to use
-a third-party one, e.g. [cert-manager](https://github.com/cert-manager/cert-manager), follow the [cert manage guide](/docs/tasks/manage/installation).
+a third-party one, e.g. [cert-manager](https://github.com/cert-manager/cert-manager), follow the [cert manager guide](/docs/tasks/manage/installation).
 
 [feature_gate]: https://kubernetes.io/docs/reference/command-line-tools-reference/feature-gates/
 
@@ -302,8 +302,6 @@ spec:
 | `ProvisioningACC`              | `false` | Alpha      | 0.5   | 0.6   |
 | `ProvisioningACC`              | `true`  | Beta       | 0.7   |       |
 | `ProvisioningACC`              | `true`  | GA         | 0.14  |       |
-| `QueueVisibility`              | `false` | Alpha      | 0.5   | 0.9   |
-| `QueueVisibility`              | `false` | Deprecated | 0.9   |       |
 | `TASProfileMostFreeCapacity`   | `false` | Deprecated | 0.11  | 0.13  |
 | `TASProfileLeastFreeCapacity`  | `false` | Deprecated | 0.11  |       |
 | `TASProfileMixed`              | `false` | Deprecated | 0.11  |       |
diff --git a/site/content/en/docs/reference/components-tools/feature-gate-removed.md b/site/content/en/docs/reference/components-tools/feature-gate-removed.md
index ff21c8106..1c54db2df 100644
--- a/site/content/en/docs/reference/components-tools/feature-gate-removed.md
+++ b/site/content/en/docs/reference/components-tools/feature-gate-removed.md
@@ -23,7 +23,7 @@ In the following table:
   is removed.
 
 | Feature                           | Default | Stage      | From | To   |
-| --------------------------------- |---------|------------|------|------|
+|-----------------------------------|---------|------------|------|------|
 | `AdmissionCheckValidationRules`   | `false` | Deprecated | 0.9  | 0.12 |
 | `KeepQuotaForProvReqRetry`        | `false` | Deprecated | 0.9  | 0.12 |
 | `MultiplePreemptions`             | `false` | Alpha      | 0.8  | 0.8  |
@@ -31,4 +31,6 @@ In the following table:
 | `MultiplePreemptions`             | `true`  | GA         | 0.10 | 0.13 |
 | `WorkloadResourceRequestsSummary` | `false` | Alpha      | 0.9  | 0.10 |
 | `WorkloadResourceRequestsSummary` | `true`  | Beta       | 0.10 | 0.11 |
-| `WorkloadResourceRequestsSummary` | `true`  | GA         | 0.11 | 0.13 |
\ No newline at end of file
+| `WorkloadResourceRequestsSummary` | `true`  | GA         | 0.11 | 0.13 |
+| `QueueVisibility`                 | `false` | Alpha      | 0.5  | 0.9  |
+| `QueueVisibility`                 | `false` | Deprecated | 0.9  | 0.14 |
\ No newline at end of file
diff --git a/site/content/en/docs/reference/kueue.v1beta1.md b/site/content/en/docs/reference/kueue.v1beta1.md
index 88bcda4d4..b03443fd2 100644
--- a/site/content/en/docs/reference/kueue.v1beta1.md
+++ b/site/content/en/docs/reference/kueue.v1beta1.md
@@ -1127,7 +1127,8 @@ current state.</p>
 <td>
    <p>PendingWorkloadsStatus contains the information exposed about the current
 status of the pending workloads in the cluster queue.
-Deprecated: This field will be removed on v1beta2, use VisibilityOnDemand
+Deprecated: This field is no longer effective since v0.14.0, which means Kueue no longer stores and updates information.
+You can migrate to VisibilityOnDemand
 (https://kueue.sigs.k8s.io/docs/tasks/manage/monitor_pending_workloads/pending_workloads_on_demand/)
 instead.</p>
 </td>
@@ -3191,6 +3192,16 @@ This field is optional.</p>
 This field is reset after the Workload is evicted.</p>
 </td>
 </tr>
+<tr><td><code>nodesToReplace</code><br/>
+<code>[]string</code>
+</td>
+<td>
+   <p>nodesToReplace holds the names of failed nodes running at least one pod of this workload
+when Topology-Aware Scheduling is used. This field should not be set by the users.
+It indicates Kueue's scheduler is searching for replacements of the failed nodes.
+Requires enabling the TASFaliedNodReplacement feature gate.</p>
+</td>
+</tr>
 </tbody>
 </table>
   
\ No newline at end of file
diff --git a/site/content/en/docs/tasks/run/rayclusters.md b/site/content/en/docs/tasks/run/rayclusters.md
index 5afed9d4a..7d2e846bb 100644
--- a/site/content/en/docs/tasks/run/rayclusters.md
+++ b/site/content/en/docs/tasks/run/rayclusters.md
@@ -65,7 +65,22 @@ Note that a RayCluster will hold resource quotas while it exists. For optimal re
 
 ### c. Limitations
 - Limited Worker Groups: Because a Kueue workload can have a maximum of 8 PodSets, the maximum number of `spec.workerGroupSpecs` is 7
-- In-Tree Autoscaling Disabled: Kueue manages resource allocation for the RayCluster; therefore, the cluster's internal autoscaling mechanisms need to be disabled
+- In-Tree Autoscaling Constraints: Autoscaling is only supported for [elastic](/docs/concepts/elastic_workload) RayCluster objects. To enable in-tree autoscaling:
+
+  1. Activate the `ElasticJobsViaWorkloadSlices` feature gate.
+  2. Annotate the RayCluster object with:
+
+     ```yaml
+     metadata:
+       annotations:
+         kueue.x-k8s.io/elastic-job: "true"
+     ```
+  3. Enable the Ray autoscaler of your RayCluster object by setting:
+
+     ```yaml
+     spec:
+       enableInTreeAutoscaling: true
+     ```
 
 ## Example RayCluster
 
diff --git a/site/content/zh-CN/docs/contribution_guidelines/testing.md b/site/content/zh-CN/docs/contribution_guidelines/testing.md
index c91c21b73..b8d00b702 100644
--- a/site/content/zh-CN/docs/contribution_guidelines/testing.md
+++ b/site/content/zh-CN/docs/contribution_guidelines/testing.md
@@ -122,7 +122,7 @@ func TestValidateClusterQueue(t *testing.T) {
 ### 使用 Ginkgo --focus 参数 {#use-ginkgo-focus-arg}
 ```shell
 GINKGO_ARGS="--focus=Scheduler" make test-integration
-GINKGO_ARGS="--focus=Creating a Pod requesting TAS" make test-e2e
+GINKGO_ARGS="--focus='Creating a Pod requesting TAS'" make test-e2e
 ```
 ### 使用 ginkgo.FIt {#use-ginkgo-fit}
 如果你想专注于特定测试，可以将这些测试的
diff --git a/site/content/zh-CN/docs/installation/_index.md b/site/content/zh-CN/docs/installation/_index.md
index 974a12416..5b1b901e4 100644
--- a/site/content/zh-CN/docs/installation/_index.md
+++ b/site/content/zh-CN/docs/installation/_index.md
@@ -302,8 +302,6 @@ spec:
 | `ProvisioningACC`              | `false` | Alpha      | 0.5      | 0.6      |
 | `ProvisioningACC`              | `true`  | Beta       | 0.7      |          |
 | `ProvisioningACC`              | `true`  | GA         | 0.14     |          |
-| `QueueVisibility`              | `false` | Alpha      | 0.5      | 0.9      |
-| `QueueVisibility`              | `false` | Deprecated | 0.9      |          |
 | `TASProfileMostFreeCapacity`   | `false` | Deprecated | 0.11     | 0.13     |
 | `TASProfileLeastFreeCapacity`  | `false` | Deprecated | 0.11     |          |
 | `TASProfileMixed`              | `false` | Deprecated | 0.11     |          |



Test patch:
diff --git a/pkg/cache/scheduler/tas_cache_test.go b/pkg/cache/scheduler/tas_cache_test.go
index 14122e09c..20dce4798 100644
--- a/pkg/cache/scheduler/tas_cache_test.go
+++ b/pkg/cache/scheduler/tas_cache_test.go
@@ -17,7 +17,6 @@ limitations under the License.
 package scheduler
 
 import (
-	"sort"
 	"testing"
 
 	"github.com/google/go-cmp/cmp"
@@ -31,7 +30,6 @@ import (
 	tasindexer "sigs.k8s.io/kueue/pkg/controller/tas/indexer"
 	"sigs.k8s.io/kueue/pkg/features"
 	"sigs.k8s.io/kueue/pkg/resources"
-	utiltas "sigs.k8s.io/kueue/pkg/util/tas"
 	utiltesting "sigs.k8s.io/kueue/pkg/util/testing"
 	testingnode "sigs.k8s.io/kueue/pkg/util/testingjobs/node"
 	testingpod "sigs.k8s.io/kueue/pkg/util/testingjobs/pod"
@@ -60,12 +58,12 @@ func TestFindTopologyAssignments(t *testing.T) {
 	//   /      \             /      \
 	//  r1       r2          r1       r2
 	//  |      /  |  \       |         |
-	//  x1    x2  x3  x4     x5       x6
+	//  x3    x5  x1  x6     x2       x4
 	defaultNodes := []corev1.Node{
-		*testingnode.MakeNode("b1-r1-x1").
+		*testingnode.MakeNode("b1-r1-x3").
 			Label(tasBlockLabel, "b1").
 			Label(tasRackLabel, "r1").
-			Label(corev1.LabelHostname, "x1").
+			Label(corev1.LabelHostname, "x3").
 			StatusAllocatable(corev1.ResourceList{
 				corev1.ResourceCPU:    resource.MustParse("1"),
 				corev1.ResourceMemory: resource.MustParse("1Gi"),
@@ -73,10 +71,10 @@ func TestFindTopologyAssignments(t *testing.T) {
 			}).
 			Ready().
 			Obj(),
-		*testingnode.MakeNode("b1-r2-x2").
+		*testingnode.MakeNode("b1-r2-x5").
 			Label(tasBlockLabel, "b1").
 			Label(tasRackLabel, "r2").
-			Label(corev1.LabelHostname, "x2").
+			Label(corev1.LabelHostname, "x5").
 			StatusAllocatable(corev1.ResourceList{
 				corev1.ResourceCPU:    resource.MustParse("1"),
 				corev1.ResourceMemory: resource.MustParse("1Gi"),
@@ -84,10 +82,10 @@ func TestFindTopologyAssignments(t *testing.T) {
 			}).
 			Ready().
 			Obj(),
-		*testingnode.MakeNode("b1-r2-x3").
+		*testingnode.MakeNode("b1-r2-x1").
 			Label(tasBlockLabel, "b1").
 			Label(tasRackLabel, "r2").
-			Label(corev1.LabelHostname, "x3").
+			Label(corev1.LabelHostname, "x1").
 			StatusAllocatable(corev1.ResourceList{
 				corev1.ResourceCPU:    resource.MustParse("1"),
 				corev1.ResourceMemory: resource.MustParse("1Gi"),
@@ -95,10 +93,10 @@ func TestFindTopologyAssignments(t *testing.T) {
 			}).
 			Ready().
 			Obj(),
-		*testingnode.MakeNode("b1-r2-x4").
+		*testingnode.MakeNode("b1-r2-x6").
 			Label(tasBlockLabel, "b1").
 			Label(tasRackLabel, "r2").
-			Label(corev1.LabelHostname, "x4").
+			Label(corev1.LabelHostname, "x6").
 			StatusAllocatable(corev1.ResourceList{
 				corev1.ResourceCPU:    resource.MustParse("1"),
 				corev1.ResourceMemory: resource.MustParse("1Gi"),
@@ -106,10 +104,10 @@ func TestFindTopologyAssignments(t *testing.T) {
 			}).
 			Ready().
 			Obj(),
-		*testingnode.MakeNode("b2-r2-x5").
+		*testingnode.MakeNode("b2-r2-x2").
 			Label(tasBlockLabel, "b2").
 			Label(tasRackLabel, "r1").
-			Label(corev1.LabelHostname, "x5").
+			Label(corev1.LabelHostname, "x2").
 			StatusAllocatable(corev1.ResourceList{
 				corev1.ResourceCPU:    resource.MustParse("1"),
 				corev1.ResourceMemory: resource.MustParse("1Gi"),
@@ -117,10 +115,10 @@ func TestFindTopologyAssignments(t *testing.T) {
 			}).
 			Ready().
 			Obj(),
-		*testingnode.MakeNode("b2-r2-x6").
+		*testingnode.MakeNode("b2-r2-x4").
 			Label(tasBlockLabel, "b2").
 			Label(tasRackLabel, "r2").
-			Label(corev1.LabelHostname, "x6").
+			Label(corev1.LabelHostname, "x4").
 			StatusAllocatable(corev1.ResourceList{
 				corev1.ResourceCPU:    resource.MustParse("2"),
 				corev1.ResourceMemory: resource.MustParse("4Gi"),
@@ -134,12 +132,12 @@ func TestFindTopologyAssignments(t *testing.T) {
 	//       |             |
 	//       r1           r1
 	//     /  |  \       /  \
-	//   x1  x2  x3     x4  x5
+	//   x3  x5  x1     x6  x2
 	scatteredNodes := []corev1.Node{
-		*testingnode.MakeNode("b1-r1-x1").
+		*testingnode.MakeNode("b1-r1-x3").
 			Label(tasBlockLabel, "b1").
 			Label(tasRackLabel, "r1").
-			Label(corev1.LabelHostname, "x1").
+			Label(corev1.LabelHostname, "x3").
 			StatusAllocatable(corev1.ResourceList{
 				corev1.ResourceCPU:    resource.MustParse("4"),
 				corev1.ResourceMemory: resource.MustParse("1Gi"),
@@ -147,10 +145,10 @@ func TestFindTopologyAssignments(t *testing.T) {
 			}).
 			Ready().
 			Obj(),
-		*testingnode.MakeNode("b1-r1-x2").
+		*testingnode.MakeNode("b1-r1-x5").
 			Label(tasBlockLabel, "b1").
 			Label(tasRackLabel, "r1").
-			Label(corev1.LabelHostname, "x2").
+			Label(corev1.LabelHostname, "x5").
 			StatusAllocatable(corev1.ResourceList{
 				corev1.ResourceCPU:    resource.MustParse("1"),
 				corev1.ResourceMemory: resource.MustParse("1Gi"),
@@ -158,10 +156,10 @@ func TestFindTopologyAssignments(t *testing.T) {
 			}).
 			Ready().
 			Obj(),
-		*testingnode.MakeNode("b1-r1-x3").
+		*testingnode.MakeNode("b1-r1-x1").
 			Label(tasBlockLabel, "b1").
 			Label(tasRackLabel, "r1").
-			Label(corev1.LabelHostname, "x3").
+			Label(corev1.LabelHostname, "x1").
 			StatusAllocatable(corev1.ResourceList{
 				corev1.ResourceCPU:    resource.MustParse("1"),
 				corev1.ResourceMemory: resource.MustParse("1Gi"),
@@ -169,10 +167,10 @@ func TestFindTopologyAssignments(t *testing.T) {
 			}).
 			Ready().
 			Obj(),
-		*testingnode.MakeNode("b2-r1-x4").
+		*testingnode.MakeNode("b2-r1-x6").
 			Label(tasBlockLabel, "b2").
 			Label(tasRackLabel, "r1").
-			Label(corev1.LabelHostname, "x4").
+			Label(corev1.LabelHostname, "x6").
 			StatusAllocatable(corev1.ResourceList{
 				corev1.ResourceCPU:    resource.MustParse("2"),
 				corev1.ResourceMemory: resource.MustParse("1Gi"),
@@ -180,10 +178,10 @@ func TestFindTopologyAssignments(t *testing.T) {
 			}).
 			Ready().
 			Obj(),
-		*testingnode.MakeNode("b2-r1-x5").
+		*testingnode.MakeNode("b2-r1-x2").
 			Label(tasBlockLabel, "b2").
 			Label(tasRackLabel, "r1").
-			Label(corev1.LabelHostname, "x5").
+			Label(corev1.LabelHostname, "x2").
 			StatusAllocatable(corev1.ResourceList{
 				corev1.ResourceCPU:    resource.MustParse("1"),
 				corev1.ResourceMemory: resource.MustParse("1Gi"),
@@ -197,11 +195,11 @@ func TestFindTopologyAssignments(t *testing.T) {
 	//	   /     \           /     \
 	//	 r1      r2        r1      r2
 	//	 |    /  |  \      |        |
-	//	x1  x2  x3  x4    x5       x6
-	multipodNodeset := []corev1.Node{*testingnode.MakeNode("b1-r1-x1").
+	//	x3  x5  x1  x6    x2       x4
+	multipodNodeset := []corev1.Node{*testingnode.MakeNode("b1-r1-x3").
 		Label(tasBlockLabel, "b1").
 		Label(tasRackLabel, "r1").
-		Label(corev1.LabelHostname, "x1").
+		Label(corev1.LabelHostname, "x3").
 		StatusAllocatable(corev1.ResourceList{
 			corev1.ResourceCPU:    resource.MustParse("10"),
 			corev1.ResourceMemory: resource.MustParse("1Gi"),
@@ -209,10 +207,10 @@ func TestFindTopologyAssignments(t *testing.T) {
 		}).
 		Ready().
 		Obj(),
-		*testingnode.MakeNode("b1-r2-x2").
+		*testingnode.MakeNode("b1-r2-x5").
 			Label(tasBlockLabel, "b1").
 			Label(tasRackLabel, "r2").
-			Label(corev1.LabelHostname, "x2").
+			Label(corev1.LabelHostname, "x5").
 			StatusAllocatable(corev1.ResourceList{
 				corev1.ResourceCPU:    resource.MustParse("10"),
 				corev1.ResourceMemory: resource.MustParse("1Gi"),
@@ -220,10 +218,10 @@ func TestFindTopologyAssignments(t *testing.T) {
 			}).
 			Ready().
 			Obj(),
-		*testingnode.MakeNode("b1-r2-x3").
+		*testingnode.MakeNode("b1-r2-x1").
 			Label(tasBlockLabel, "b1").
 			Label(tasRackLabel, "r2").
-			Label(corev1.LabelHostname, "x3").
+			Label(corev1.LabelHostname, "x1").
 			StatusAllocatable(corev1.ResourceList{
 				corev1.ResourceCPU:    resource.MustParse("10"),
 				corev1.ResourceMemory: resource.MustParse("1Gi"),
@@ -231,10 +229,10 @@ func TestFindTopologyAssignments(t *testing.T) {
 			}).
 			Ready().
 			Obj(),
-		*testingnode.MakeNode("b1-r2-x4").
+		*testingnode.MakeNode("b1-r2-x6").
 			Label(tasBlockLabel, "b1").
 			Label(tasRackLabel, "r2").
-			Label(corev1.LabelHostname, "x4").
+			Label(corev1.LabelHostname, "x6").
 			StatusAllocatable(corev1.ResourceList{
 				corev1.ResourceCPU:    resource.MustParse("10"),
 				corev1.ResourceMemory: resource.MustParse("1Gi"),
@@ -242,10 +240,10 @@ func TestFindTopologyAssignments(t *testing.T) {
 			}).
 			Ready().
 			Obj(),
-		*testingnode.MakeNode("b2-r1-x5").
+		*testingnode.MakeNode("b2-r1-x2").
 			Label(tasBlockLabel, "b2").
 			Label(tasRackLabel, "r1").
-			Label(corev1.LabelHostname, "x5").
+			Label(corev1.LabelHostname, "x2").
 			StatusAllocatable(corev1.ResourceList{
 				corev1.ResourceCPU:    resource.MustParse("10"),
 				corev1.ResourceMemory: resource.MustParse("1Gi"),
@@ -253,10 +251,10 @@ func TestFindTopologyAssignments(t *testing.T) {
 			}).
 			Ready().
 			Obj(),
-		*testingnode.MakeNode("b2-r2-x6").
+		*testingnode.MakeNode("b2-r2-x4").
 			Label(tasBlockLabel, "b2").
 			Label(tasRackLabel, "r2").
-			Label(corev1.LabelHostname, "x6").
+			Label(corev1.LabelHostname, "x4").
 			StatusAllocatable(corev1.ResourceList{
 				corev1.ResourceCPU:    resource.MustParse("20"),
 				corev1.ResourceMemory: resource.MustParse("4Gi"),
@@ -283,12 +281,12 @@ func TestFindTopologyAssignments(t *testing.T) {
 	//       /        \             /      \
 	//      r1         r2          r1       r2
 	//     /  \      /   \        /   \    /   \
-	//    x1   x2   x3    x4     x5   x6  x7    x6
+	//    x3   x5   x1    x6     x2   x4  x7    x4
 	binaryTreesNodes := []corev1.Node{
-		*testingnode.MakeNode("b1-r1-x1").
+		*testingnode.MakeNode("b1-r1-x3").
 			Label(tasBlockLabel, "b1").
 			Label(tasRackLabel, "r1").
-			Label(corev1.LabelHostname, "x1").
+			Label(corev1.LabelHostname, "x3").
 			StatusAllocatable(corev1.ResourceList{
 				corev1.ResourceCPU:    resource.MustParse("1"),
 				corev1.ResourceMemory: resource.MustParse("1Gi"),
@@ -296,10 +294,10 @@ func TestFindTopologyAssignments(t *testing.T) {
 			}).
 			Ready().
 			Obj(),
-		*testingnode.MakeNode("b1-r1-x2").
+		*testingnode.MakeNode("b1-r1-x5").
 			Label(tasBlockLabel, "b1").
 			Label(tasRackLabel, "r1").
-			Label(corev1.LabelHostname, "x2").
+			Label(corev1.LabelHostname, "x5").
 			StatusAllocatable(corev1.ResourceList{
 				corev1.ResourceCPU:    resource.MustParse("1"),
 				corev1.ResourceMemory: resource.MustParse("1Gi"),
@@ -307,10 +305,10 @@ func TestFindTopologyAssignments(t *testing.T) {
 			}).
 			Ready().
 			Obj(),
-		*testingnode.MakeNode("b1-r2-x3").
+		*testingnode.MakeNode("b1-r2-x1").
 			Label(tasBlockLabel, "b1").
 			Label(tasRackLabel, "r2").
-			Label(corev1.LabelHostname, "x3").
+			Label(corev1.LabelHostname, "x1").
 			StatusAllocatable(corev1.ResourceList{
 				corev1.ResourceCPU:    resource.MustParse("1"),
 				corev1.ResourceMemory: resource.MustParse("1Gi"),
@@ -318,10 +316,10 @@ func TestFindTopologyAssignments(t *testing.T) {
 			}).
 			Ready().
 			Obj(),
-		*testingnode.MakeNode("b1-r2-x4").
+		*testingnode.MakeNode("b1-r2-x6").
 			Label(tasBlockLabel, "b1").
 			Label(tasRackLabel, "r2").
-			Label(corev1.LabelHostname, "x4").
+			Label(corev1.LabelHostname, "x6").
 			StatusAllocatable(corev1.ResourceList{
 				corev1.ResourceCPU:    resource.MustParse("1"),
 				corev1.ResourceMemory: resource.MustParse("1Gi"),
@@ -329,10 +327,10 @@ func TestFindTopologyAssignments(t *testing.T) {
 			}).
 			Ready().
 			Obj(),
-		*testingnode.MakeNode("b2-r1-x5").
+		*testingnode.MakeNode("b2-r1-x2").
 			Label(tasBlockLabel, "b2").
 			Label(tasRackLabel, "r1").
-			Label(corev1.LabelHostname, "x5").
+			Label(corev1.LabelHostname, "x2").
 			StatusAllocatable(corev1.ResourceList{
 				corev1.ResourceCPU:    resource.MustParse("1"),
 				corev1.ResourceMemory: resource.MustParse("1Gi"),
@@ -340,10 +338,10 @@ func TestFindTopologyAssignments(t *testing.T) {
 			}).
 			Ready().
 			Obj(),
-		*testingnode.MakeNode("b2-r1-x6").
+		*testingnode.MakeNode("b2-r1-x4").
 			Label(tasBlockLabel, "b2").
 			Label(tasRackLabel, "r1").
-			Label(corev1.LabelHostname, "x6").
+			Label(corev1.LabelHostname, "x4").
 			StatusAllocatable(corev1.ResourceList{
 				corev1.ResourceCPU:    resource.MustParse("1"),
 				corev1.ResourceMemory: resource.MustParse("1Gi"),
@@ -384,70 +382,70 @@ func TestFindTopologyAssignments(t *testing.T) {
 		podSets            []PodSetTestCase
 	}{
 		"minimize the number of used racks before optimizing the number of nodes; BestFit": {
-			// Solution by optimizing the number of racks then nodes: [r3]: [x3,x4,x5,x6]
-			// Solution by optimizing the number of nodes: [r1,r2]: [x1,x2]
+			// Solution by optimizing the number of racks then nodes: [r3]: [x1,x6,x2,x4]
+			// Solution by optimizing the number of nodes: [r1,r2]: [x3,x5]
 			//
 			//       b1
 			//   /   |    \
 			//  r1   r2   r3
 			//  |     |    |   \   \     \
-			// x1:2,x2:2,x3:1,x4:1,x5:1,x6:1
+			// x3:2,x5:2,x1:1,x6:1,x2:1,x4:1
 			//
 			nodes: []corev1.Node{
-				*testingnode.MakeNode("b1-r1-x1").
+				*testingnode.MakeNode("b1-r1-x3").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x1").
+					Label(corev1.LabelHostname, "x3").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("2"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r2-x2").
+				*testingnode.MakeNode("b1-r2-x5").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r2").
-					Label(corev1.LabelHostname, "x2").
+					Label(corev1.LabelHostname, "x5").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("2"),
 						corev1.ResourcePods: resource.MustParse("20"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r3-x3").
+				*testingnode.MakeNode("b1-r3-x1").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r3").
-					Label(corev1.LabelHostname, "x3").
+					Label(corev1.LabelHostname, "x1").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("1"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r3-x4").
+				*testingnode.MakeNode("b1-r3-x6").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r3").
-					Label(corev1.LabelHostname, "x4").
+					Label(corev1.LabelHostname, "x6").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("1"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r3-x5").
+				*testingnode.MakeNode("b1-r3-x2").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r3").
-					Label(corev1.LabelHostname, "x5").
+					Label(corev1.LabelHostname, "x2").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("1"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r3-x6").
+				*testingnode.MakeNode("b1-r3-x4").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r3").
-					Label(corev1.LabelHostname, "x6").
+					Label(corev1.LabelHostname, "x4").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("1"),
 						corev1.ResourcePods: resource.MustParse("10"),
@@ -470,19 +468,19 @@ func TestFindTopologyAssignments(t *testing.T) {
 						{
 							Count: 1,
 							Values: []string{
-								"x3",
+								"x1",
 							},
 						},
 						{
 							Count: 1,
 							Values: []string{
-								"x4",
+								"x2",
 							},
 						},
 						{
 							Count: 1,
 							Values: []string{
-								"x5",
+								"x4",
 							},
 						},
 						{
@@ -501,33 +499,33 @@ func TestFindTopologyAssignments(t *testing.T) {
 			//         |
 			//        r1
 			//    /    |    \
-			// x1:2, x2:1, x3:1
+			// x3:2, x5:1, x1:1
 			//
 			nodes: []corev1.Node{
-				*testingnode.MakeNode("b1-r1-x1").
+				*testingnode.MakeNode("b1-r1-x3").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x1").
+					Label(corev1.LabelHostname, "x3").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("2"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r1-x2").
+				*testingnode.MakeNode("b1-r1-x5").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x2").
+					Label(corev1.LabelHostname, "x5").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("1"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r1-x3").
+				*testingnode.MakeNode("b1-r1-x1").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x3").
+					Label(corev1.LabelHostname, "x1").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("1"),
 						corev1.ResourcePods: resource.MustParse("10"),
@@ -550,13 +548,13 @@ func TestFindTopologyAssignments(t *testing.T) {
 						{
 							Count: 1,
 							Values: []string{
-								"x3",
+								"x1",
 							},
 						},
 						{
 							Count: 1,
 							Values: []string{
-								"x2",
+								"x5",
 							},
 						},
 					},
@@ -569,32 +567,32 @@ func TestFindTopologyAssignments(t *testing.T) {
 			//         |
 			//        r1
 			//    /    |    \
-			// x1:2, x2:1, x3:1
+			// x3:2, x5:1, x1:1
 			nodes: []corev1.Node{
-				*testingnode.MakeNode("b1-r1-x1").
+				*testingnode.MakeNode("b1-r1-x3").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x1").
+					Label(corev1.LabelHostname, "x3").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("2"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r1-x2").
+				*testingnode.MakeNode("b1-r1-x5").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x2").
+					Label(corev1.LabelHostname, "x5").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("1"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r1-x3").
+				*testingnode.MakeNode("b1-r1-x1").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x3").
+					Label(corev1.LabelHostname, "x1").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("1"),
 						corev1.ResourcePods: resource.MustParse("10"),
@@ -617,7 +615,7 @@ func TestFindTopologyAssignments(t *testing.T) {
 						{
 							Count: 2,
 							Values: []string{
-								"x1",
+								"x3",
 							},
 						},
 					},
@@ -641,7 +639,7 @@ func TestFindTopologyAssignments(t *testing.T) {
 						{
 							Count: 2,
 							Values: []string{
-								"x4",
+								"x6",
 							},
 						},
 					},
@@ -663,13 +661,13 @@ func TestFindTopologyAssignments(t *testing.T) {
 						{
 							Count: 4,
 							Values: []string{
-								"x1",
+								"x3",
 							},
 						},
 						{
 							Count: 2,
 							Values: []string{
-								"x4",
+								"x6",
 							},
 						},
 					},
@@ -693,13 +691,13 @@ func TestFindTopologyAssignments(t *testing.T) {
 						{
 							Count: 4,
 							Values: []string{
-								"x1",
+								"x3",
 							},
 						},
 						{
 							Count: 2,
 							Values: []string{
-								"x4",
+								"x6",
 							},
 						},
 					},
@@ -723,7 +721,7 @@ func TestFindTopologyAssignments(t *testing.T) {
 						{
 							Count: 1,
 							Values: []string{
-								"x1",
+								"x3",
 							},
 						},
 					},
@@ -747,7 +745,7 @@ func TestFindTopologyAssignments(t *testing.T) {
 						{
 							Count: 1,
 							Values: []string{
-								"x1",
+								"x3",
 							},
 						},
 					},
@@ -772,7 +770,7 @@ func TestFindTopologyAssignments(t *testing.T) {
 						{
 							Count: 1,
 							Values: []string{
-								"x1",
+								"x3",
 							},
 						},
 					},
@@ -797,25 +795,25 @@ func TestFindTopologyAssignments(t *testing.T) {
 						{
 							Count: 1,
 							Values: []string{
-								"x1",
+								"x3",
 							},
 						},
 						{
 							Count: 1,
 							Values: []string{
-								"x2",
+								"x5",
 							},
 						},
 						{
 							Count: 1,
 							Values: []string{
-								"x3",
+								"x1",
 							},
 						},
 						{
 							Count: 1,
 							Values: []string{
-								"x4",
+								"x6",
 							},
 						},
 					},
@@ -839,7 +837,7 @@ func TestFindTopologyAssignments(t *testing.T) {
 						{
 							Count: 1,
 							Values: []string{
-								"x1",
+								"x3",
 							},
 						},
 					},
@@ -864,7 +862,7 @@ func TestFindTopologyAssignments(t *testing.T) {
 						{
 							Count: 1,
 							Values: []string{
-								"x1",
+								"x3",
 							},
 						},
 					},
@@ -888,7 +886,7 @@ func TestFindTopologyAssignments(t *testing.T) {
 						{
 							Count: 1,
 							Values: []string{
-								"x1",
+								"x3",
 							},
 						},
 					},
@@ -913,7 +911,7 @@ func TestFindTopologyAssignments(t *testing.T) {
 						{
 							Count: 2,
 							Values: []string{
-								"x6",
+								"x4",
 							},
 						},
 					},
@@ -938,7 +936,7 @@ func TestFindTopologyAssignments(t *testing.T) {
 						{
 							Count: 2,
 							Values: []string{
-								"x6",
+								"x4",
 							},
 						},
 					},
@@ -978,7 +976,7 @@ func TestFindTopologyAssignments(t *testing.T) {
 						{
 							Count: 1,
 							Values: []string{
-								"x1",
+								"x3",
 							},
 						},
 					},
@@ -1028,7 +1026,7 @@ func TestFindTopologyAssignments(t *testing.T) {
 						{
 							Count: 1,
 							Values: []string{
-								"x1",
+								"x3",
 							},
 						},
 					},
@@ -1198,7 +1196,7 @@ func TestFindTopologyAssignments(t *testing.T) {
 						{
 							Count: 1,
 							Values: []string{
-								"x5",
+								"x2",
 							},
 						},
 					},
@@ -1223,13 +1221,13 @@ func TestFindTopologyAssignments(t *testing.T) {
 						{
 							Count: 1,
 							Values: []string{
-								"x5",
+								"x2",
 							},
 						},
 						{
 							Count: 1,
 							Values: []string{
-								"x6",
+								"x4",
 							},
 						},
 					},
@@ -1283,17 +1281,17 @@ func TestFindTopologyAssignments(t *testing.T) {
 					},
 					Domains: []kueue.TopologyDomainAssignment{
 						{
-							Count: 3,
+							Count: 1,
 							Values: []string{
 								"b1",
-								"r2",
+								"r1",
 							},
 						},
 						{
-							Count: 1,
+							Count: 3,
 							Values: []string{
 								"b1",
-								"r1",
+								"r2",
 							},
 						},
 					},
@@ -1315,17 +1313,17 @@ func TestFindTopologyAssignments(t *testing.T) {
 					Levels: defaultTwoLevels,
 					Domains: []kueue.TopologyDomainAssignment{
 						{
-							Count: 3,
+							Count: 1,
 							Values: []string{
 								"b1",
-								"r2",
+								"r1",
 							},
 						},
 						{
-							Count: 1,
+							Count: 3,
 							Values: []string{
 								"b1",
-								"r1",
+								"r2",
 							},
 						},
 					},
@@ -1400,17 +1398,17 @@ func TestFindTopologyAssignments(t *testing.T) {
 					Levels: defaultTwoLevels,
 					Domains: []kueue.TopologyDomainAssignment{
 						{
-							Count: 3,
+							Count: 1,
 							Values: []string{
 								"b1",
-								"r2",
+								"r1",
 							},
 						},
 						{
-							Count: 1,
+							Count: 3,
 							Values: []string{
 								"b1",
-								"r1",
+								"r2",
 							},
 						},
 					},
@@ -1432,24 +1430,24 @@ func TestFindTopologyAssignments(t *testing.T) {
 					Levels: defaultTwoLevels,
 					Domains: []kueue.TopologyDomainAssignment{
 						{
-							Count: 3,
+							Count: 1,
 							Values: []string{
 								"b1",
-								"r2",
+								"r1",
 							},
 						},
 						{
-							Count: 2,
+							Count: 3,
 							Values: []string{
-								"b2",
+								"b1",
 								"r2",
 							},
 						},
 						{
-							Count: 1,
+							Count: 2,
 							Values: []string{
-								"b1",
-								"r1",
+								"b2",
+								"r2",
 							},
 						},
 					},
@@ -1471,24 +1469,24 @@ func TestFindTopologyAssignments(t *testing.T) {
 					Levels: defaultTwoLevels,
 					Domains: []kueue.TopologyDomainAssignment{
 						{
-							Count: 3,
+							Count: 1,
 							Values: []string{
 								"b1",
-								"r2",
+								"r1",
 							},
 						},
 						{
-							Count: 2,
+							Count: 3,
 							Values: []string{
-								"b2",
+								"b1",
 								"r2",
 							},
 						},
 						{
-							Count: 1,
+							Count: 2,
 							Values: []string{
-								"b1",
-								"r1",
+								"b2",
+								"r2",
 							},
 						},
 					},
@@ -1511,9 +1509,9 @@ func TestFindTopologyAssignments(t *testing.T) {
 		},
 		"only nodes with matching labels are considered; no matching node; BestFit": {
 			nodes: []corev1.Node{
-				*testingnode.MakeNode("b1-r1-x1").
+				*testingnode.MakeNode("b1-r1-x3").
 					Label("zone", "zone-a").
-					Label(corev1.LabelHostname, "x1").
+					Label(corev1.LabelHostname, "x3").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:    resource.MustParse("1"),
 						corev1.ResourceMemory: resource.MustParse("1Gi"),
@@ -1538,9 +1536,9 @@ func TestFindTopologyAssignments(t *testing.T) {
 		},
 		"only nodes with matching labels are considered; matching node is found; BestFit": {
 			nodes: []corev1.Node{
-				*testingnode.MakeNode("b1-r1-x1").
+				*testingnode.MakeNode("b1-r1-x3").
 					Label("zone", "zone-a").
-					Label(corev1.LabelHostname, "x1").
+					Label(corev1.LabelHostname, "x3").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:    resource.MustParse("1"),
 						corev1.ResourceMemory: resource.MustParse("1Gi"),
@@ -1564,7 +1562,7 @@ func TestFindTopologyAssignments(t *testing.T) {
 						{
 							Count: 1,
 							Values: []string{
-								"x1",
+								"x3",
 							},
 						},
 					},
@@ -1576,7 +1574,7 @@ func TestFindTopologyAssignments(t *testing.T) {
 		},
 		"only nodes with matching levels are considered; no host label on node; BestFit": {
 			nodes: []corev1.Node{
-				*testingnode.MakeNode("b1-r1-x1").
+				*testingnode.MakeNode("b1-r1-x3").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
 					// the node doesn't have the 'kubernetes.io/hostname' required by topology
@@ -1603,8 +1601,8 @@ func TestFindTopologyAssignments(t *testing.T) {
 		"don't consider unscheduled Pods when computing capacity; BestFit": {
 			// the Pod is not scheduled (no NodeName set, so is not blocking capacity)
 			nodes: []corev1.Node{
-				*testingnode.MakeNode("x1").
-					Label(corev1.LabelHostname, "x1").
+				*testingnode.MakeNode("x3").
+					Label(corev1.LabelHostname, "x3").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:    resource.MustParse("1"),
 						corev1.ResourceMemory: resource.MustParse("1Gi"),
@@ -1633,7 +1631,7 @@ func TestFindTopologyAssignments(t *testing.T) {
 						{
 							Count: 1,
 							Values: []string{
-								"x1",
+								"x3",
 							},
 						},
 					},
@@ -1642,8 +1640,8 @@ func TestFindTopologyAssignments(t *testing.T) {
 		},
 		"don't consider terminal pods when computing the capacity; BestFit": {
 			nodes: []corev1.Node{
-				*testingnode.MakeNode("x1").
-					Label(corev1.LabelHostname, "x1").
+				*testingnode.MakeNode("x3").
+					Label(corev1.LabelHostname, "x3").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:    resource.MustParse("1"),
 						corev1.ResourceMemory: resource.MustParse("1Gi"),
@@ -1653,11 +1651,11 @@ func TestFindTopologyAssignments(t *testing.T) {
 					Obj(),
 			},
 			pods: []corev1.Pod{
-				*testingpod.MakePod("test-failed", "test-ns").NodeName("x1").
+				*testingpod.MakePod("test-failed", "test-ns").NodeName("x3").
 					Request(corev1.ResourceCPU, "600m").
 					StatusPhase(corev1.PodFailed).
 					Obj(),
-				*testingpod.MakePod("test-succeeded", "test-ns").NodeName("x1").
+				*testingpod.MakePod("test-succeeded", "test-ns").NodeName("x3").
 					Request(corev1.ResourceCPU, "600m").
 					StatusPhase(corev1.PodSucceeded).
 					Obj(),
@@ -1677,7 +1675,7 @@ func TestFindTopologyAssignments(t *testing.T) {
 						{
 							Count: 1,
 							Values: []string{
-								"x1",
+								"x3",
 							},
 						},
 					},
@@ -1685,10 +1683,10 @@ func TestFindTopologyAssignments(t *testing.T) {
 			}},
 		},
 		"include usage from pending scheduled non-TAS pods, blocked assignment; BestFit": {
-			// there is not enough free capacity on the only node x1
+			// there is not enough free capacity on the only node x3
 			nodes: []corev1.Node{
-				*testingnode.MakeNode("x1").
-					Label(corev1.LabelHostname, "x1").
+				*testingnode.MakeNode("x3").
+					Label(corev1.LabelHostname, "x3").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:    resource.MustParse("1"),
 						corev1.ResourceMemory: resource.MustParse("1Gi"),
@@ -1698,7 +1696,7 @@ func TestFindTopologyAssignments(t *testing.T) {
 					Obj(),
 			},
 			pods: []corev1.Pod{
-				*testingpod.MakePod("test-pending", "test-ns").NodeName("x1").
+				*testingpod.MakePod("test-pending", "test-ns").NodeName("x3").
 					StatusPhase(corev1.PodPending).
 					Request(corev1.ResourceCPU, "600m").
 					Obj(),
@@ -1716,10 +1714,10 @@ func TestFindTopologyAssignments(t *testing.T) {
 			}},
 		},
 		"include usage from running non-TAS pods, blocked assignment; BestFit": {
-			// there is not enough free capacity on the only node x1
+			// there is not enough free capacity on the only node x3
 			nodes: []corev1.Node{
-				*testingnode.MakeNode("x1").
-					Label(corev1.LabelHostname, "x1").
+				*testingnode.MakeNode("x3").
+					Label(corev1.LabelHostname, "x3").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:    resource.MustParse("1"),
 						corev1.ResourceMemory: resource.MustParse("1Gi"),
@@ -1729,7 +1727,7 @@ func TestFindTopologyAssignments(t *testing.T) {
 					Obj(),
 			},
 			pods: []corev1.Pod{
-				*testingpod.MakePod("test-running", "test-ns").NodeName("x1").
+				*testingpod.MakePod("test-running", "test-ns").NodeName("x3").
 					StatusPhase(corev1.PodRunning).
 					Request(corev1.ResourceCPU, "600m").
 					Obj(),
@@ -1747,11 +1745,11 @@ func TestFindTopologyAssignments(t *testing.T) {
 			}},
 		},
 		"include usage from running non-TAS pods, found free capacity on another node; BestFit": {
-			// there is not enough free capacity on the node x1 as the
-			// assignments lends on the free x2
+			// there is not enough free capacity on the node x3 as the
+			// assignments lends on the free x5
 			nodes: []corev1.Node{
-				*testingnode.MakeNode("x1").
-					Label(corev1.LabelHostname, "x1").
+				*testingnode.MakeNode("x3").
+					Label(corev1.LabelHostname, "x3").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:    resource.MustParse("1"),
 						corev1.ResourceMemory: resource.MustParse("1Gi"),
@@ -1759,8 +1757,8 @@ func TestFindTopologyAssignments(t *testing.T) {
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("x2").
-					Label(corev1.LabelHostname, "x2").
+				*testingnode.MakeNode("x5").
+					Label(corev1.LabelHostname, "x5").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:    resource.MustParse("1"),
 						corev1.ResourceMemory: resource.MustParse("1Gi"),
@@ -1770,7 +1768,7 @@ func TestFindTopologyAssignments(t *testing.T) {
 					Obj(),
 			},
 			pods: []corev1.Pod{
-				*testingpod.MakePod("test-pod", "test-ns").NodeName("x1").
+				*testingpod.MakePod("test-pod", "test-ns").NodeName("x3").
 					Request(corev1.ResourceCPU, "600m").
 					Obj(),
 			},
@@ -1789,7 +1787,7 @@ func TestFindTopologyAssignments(t *testing.T) {
 						{
 							Count: 1,
 							Values: []string{
-								"x2",
+								"x5",
 							},
 						},
 					},
@@ -1798,9 +1796,9 @@ func TestFindTopologyAssignments(t *testing.T) {
 		},
 		"no assignment as node is not ready; BestFit": {
 			nodes: []corev1.Node{
-				*testingnode.MakeNode("b1-r1-x1").
+				*testingnode.MakeNode("b1-r1-x3").
 					Label("zone", "zone-a").
-					Label(corev1.LabelHostname, "x1").
+					Label(corev1.LabelHostname, "x3").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:    resource.MustParse("1"),
 						corev1.ResourceMemory: resource.MustParse("1Gi"),
@@ -1830,9 +1828,9 @@ func TestFindTopologyAssignments(t *testing.T) {
 		},
 		"no assignment as node is unschedulable; BestFit": {
 			nodes: []corev1.Node{
-				*testingnode.MakeNode("b1-r1-x1").
+				*testingnode.MakeNode("b1-r1-x3").
 					Label("zone", "zone-a").
-					Label(corev1.LabelHostname, "x1").
+					Label(corev1.LabelHostname, "x3").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:    resource.MustParse("1"),
 						corev1.ResourceMemory: resource.MustParse("1Gi"),
@@ -1859,9 +1857,9 @@ func TestFindTopologyAssignments(t *testing.T) {
 		},
 		"skip node which has untolerated taint; BestFit": {
 			nodes: []corev1.Node{
-				*testingnode.MakeNode("x1").
+				*testingnode.MakeNode("x3").
 					Label("zone", "zone-a").
-					Label(corev1.LabelHostname, "x1").
+					Label(corev1.LabelHostname, "x3").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:    resource.MustParse("1"),
 						corev1.ResourceMemory: resource.MustParse("1Gi"),
@@ -1892,9 +1890,9 @@ func TestFindTopologyAssignments(t *testing.T) {
 		},
 		"allow to schedule on node with tolerated taint; BestFit": {
 			nodes: []corev1.Node{
-				*testingnode.MakeNode("b1-r1-x1").
+				*testingnode.MakeNode("b1-r1-x3").
 					Label("zone", "zone-a").
-					Label(corev1.LabelHostname, "x1").
+					Label(corev1.LabelHostname, "x3").
 					Taints(corev1.Taint{
 						Key:    "example.com/gpu",
 						Value:  "present",
@@ -1923,7 +1921,7 @@ func TestFindTopologyAssignments(t *testing.T) {
 						{
 							Count: 1,
 							Values: []string{
-								"x1",
+								"x3",
 							},
 						},
 					},
@@ -1942,9 +1940,9 @@ func TestFindTopologyAssignments(t *testing.T) {
 		},
 		"no assignment as node does not have enough allocatable pods (.status.allocatable['pods']); BestFit": {
 			nodes: []corev1.Node{
-				*testingnode.MakeNode("b1-r1-x1").
+				*testingnode.MakeNode("b1-r1-x3").
 					Label("zone", "zone-a").
-					Label(corev1.LabelHostname, "x1").
+					Label(corev1.LabelHostname, "x3").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("1000m"),
 						corev1.ResourcePods: resource.MustParse("1"),
@@ -1954,7 +1952,7 @@ func TestFindTopologyAssignments(t *testing.T) {
 			},
 			pods: []corev1.Pod{
 				*testingpod.MakePod("test-running", "test-ns").
-					NodeName("b1-r1-x1").
+					NodeName("b1-r1-x3").
 					StatusPhase(corev1.PodRunning).
 					Request(corev1.ResourceCPU, "300m").
 					Obj(),
@@ -1976,9 +1974,9 @@ func TestFindTopologyAssignments(t *testing.T) {
 		},
 		"skip node which doesn't match node selector, missing label; BestFit": {
 			nodes: []corev1.Node{
-				*testingnode.MakeNode("x1").
+				*testingnode.MakeNode("x3").
 					Label("zone", "zone-a").
-					Label(corev1.LabelHostname, "x1").
+					Label(corev1.LabelHostname, "x3").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:    resource.MustParse("1"),
 						corev1.ResourceMemory: resource.MustParse("1Gi"),
@@ -2008,9 +2006,9 @@ func TestFindTopologyAssignments(t *testing.T) {
 		},
 		"skip node which doesn't match node selector, label exists, value doesn't match; BestFit": {
 			nodes: []corev1.Node{
-				*testingnode.MakeNode("x1").
+				*testingnode.MakeNode("x3").
 					Label("zone", "zone-a").
-					Label(corev1.LabelHostname, "x1").
+					Label(corev1.LabelHostname, "x3").
 					Label("custom-label-1", "value-1").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:    resource.MustParse("1"),
@@ -2040,9 +2038,9 @@ func TestFindTopologyAssignments(t *testing.T) {
 		},
 		"allow to schedule on node which matches node; BestFit": {
 			nodes: []corev1.Node{
-				*testingnode.MakeNode("b1-r1-x1").
+				*testingnode.MakeNode("b1-r1-x3").
 					Label("zone", "zone-a").
-					Label(corev1.LabelHostname, "x1").
+					Label(corev1.LabelHostname, "x3").
 					Label("custom-label-1", "value-1").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:    resource.MustParse("1"),
@@ -2051,9 +2049,9 @@ func TestFindTopologyAssignments(t *testing.T) {
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r1-x2").
+				*testingnode.MakeNode("b1-r1-x5").
 					Label("zone", "zone-a").
-					Label(corev1.LabelHostname, "x2").
+					Label(corev1.LabelHostname, "x5").
 					Label("custom-label-1", "value-2").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:    resource.MustParse("1"),
@@ -2082,7 +2080,7 @@ func TestFindTopologyAssignments(t *testing.T) {
 						{
 							Count: 1,
 							Values: []string{
-								"x2",
+								"x5",
 							},
 						},
 					},
@@ -2097,33 +2095,33 @@ func TestFindTopologyAssignments(t *testing.T) {
 			//         |
 			//        r1
 			//    /    |    \
-			// x1:3, x2:3, x3:3
+			// x3:3, x5:3, x1:3
 			//
 			nodes: []corev1.Node{
-				*testingnode.MakeNode("b1-r1-x1").
+				*testingnode.MakeNode("b1-r1-x3").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x1").
+					Label(corev1.LabelHostname, "x3").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("3"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r1-x2").
+				*testingnode.MakeNode("b1-r1-x5").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x2").
+					Label(corev1.LabelHostname, "x5").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("3"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r1-x3").
+				*testingnode.MakeNode("b1-r1-x1").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x3").
+					Label(corev1.LabelHostname, "x1").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("3"),
 						corev1.ResourcePods: resource.MustParse("10"),
@@ -2148,19 +2146,19 @@ func TestFindTopologyAssignments(t *testing.T) {
 						{
 							Count: 2,
 							Values: []string{
-								"x3",
+								"x1",
 							},
 						},
 						{
 							Count: 2,
 							Values: []string{
-								"x2",
+								"x3",
 							},
 						},
 						{
 							Count: 2,
 							Values: []string{
-								"x1",
+								"x5",
 							},
 						},
 					},
@@ -2172,43 +2170,43 @@ func TestFindTopologyAssignments(t *testing.T) {
 			//            |
 			//           r1
 			//    /    /    \    \
-			// x1:6  x2:5   x3:4  x4:2
+			// x3:6  x5:5   x1:4  x6:2
 			//
 			nodes: []corev1.Node{
-				*testingnode.MakeNode("b1-r1-x1").
+				*testingnode.MakeNode("b1-r1-x3").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x1").
+					Label(corev1.LabelHostname, "x3").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("6"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r1-x2").
+				*testingnode.MakeNode("b1-r1-x5").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x2").
+					Label(corev1.LabelHostname, "x5").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("5"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r1-x3").
+				*testingnode.MakeNode("b1-r1-x1").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x3").
+					Label(corev1.LabelHostname, "x1").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("4"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r1-x4").
+				*testingnode.MakeNode("b1-r1-x6").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x4").
+					Label(corev1.LabelHostname, "x6").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("2"),
 						corev1.ResourcePods: resource.MustParse("10"),
@@ -2231,13 +2229,13 @@ func TestFindTopologyAssignments(t *testing.T) {
 					Levels: defaultOneLevel,
 					Domains: []kueue.TopologyDomainAssignment{
 						{
-							Count: 6,
+							Count: 4,
 							Values: []string{
 								"x1",
 							},
 						},
 						{
-							Count: 4,
+							Count: 6,
 							Values: []string{
 								"x3",
 							},
@@ -2245,7 +2243,7 @@ func TestFindTopologyAssignments(t *testing.T) {
 						{
 							Count: 2,
 							Values: []string{
-								"x4",
+								"x6",
 							},
 						},
 					},
@@ -2257,33 +2255,33 @@ func TestFindTopologyAssignments(t *testing.T) {
 			//         |
 			//        r1
 			//    /    |    \
-			// x1:3, x2:2, x3:2
+			// x3:3, x5:2, x1:2
 			//
 			nodes: []corev1.Node{
-				*testingnode.MakeNode("b1-r1-x1").
+				*testingnode.MakeNode("b1-r1-x3").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x1").
+					Label(corev1.LabelHostname, "x3").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("3"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r1-x2").
+				*testingnode.MakeNode("b1-r1-x5").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x2").
+					Label(corev1.LabelHostname, "x5").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("2"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r1-x3").
+				*testingnode.MakeNode("b1-r1-x1").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x3").
+					Label(corev1.LabelHostname, "x1").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("2"),
 						corev1.ResourcePods: resource.MustParse("10"),
@@ -2308,13 +2306,13 @@ func TestFindTopologyAssignments(t *testing.T) {
 						{
 							Count: 2,
 							Values: []string{
-								"x2",
+								"x1",
 							},
 						},
 						{
 							Count: 2,
 							Values: []string{
-								"x3",
+								"x5",
 							},
 						},
 					},
@@ -2327,62 +2325,62 @@ func TestFindTopologyAssignments(t *testing.T) {
 			//    /       \          |
 			//   r1        r2       r1
 			//  / \     /  / \     /  \
-			// x1 x2  x3 x4  x5   x6   x7
+			// x3 x5  x1 x6  x2   x4   x7
 			nodes: []corev1.Node{
-				*testingnode.MakeNode("b1-r1-x1").
+				*testingnode.MakeNode("b1-r1-x3").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x1").
+					Label(corev1.LabelHostname, "x3").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("1"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r1-x2").
+				*testingnode.MakeNode("b1-r1-x5").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x2").
+					Label(corev1.LabelHostname, "x5").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("1"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r2-x3").
+				*testingnode.MakeNode("b1-r2-x1").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r2").
-					Label(corev1.LabelHostname, "x3").
+					Label(corev1.LabelHostname, "x1").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("1"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r2-x4").
+				*testingnode.MakeNode("b1-r2-x6").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r2").
-					Label(corev1.LabelHostname, "x4").
+					Label(corev1.LabelHostname, "x6").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("1"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r2-x5").
+				*testingnode.MakeNode("b1-r2-x2").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r2").
-					Label(corev1.LabelHostname, "x5").
+					Label(corev1.LabelHostname, "x2").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("1"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b2-r1-x6").
+				*testingnode.MakeNode("b2-r1-x4").
 					Label(tasBlockLabel, "b2").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x6").
+					Label(corev1.LabelHostname, "x4").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("1"),
 						corev1.ResourcePods: resource.MustParse("10"),
@@ -2417,25 +2415,25 @@ func TestFindTopologyAssignments(t *testing.T) {
 						{
 							Count: 1,
 							Values: []string{
-								"x1",
+								"x3",
 							},
 						},
 						{
 							Count: 1,
 							Values: []string{
-								"x2",
+								"x5",
 							},
 						},
 						{
 							Count: 1,
 							Values: []string{
-								"x3",
+								"x1",
 							},
 						},
 						{
 							Count: 1,
 							Values: []string{
-								"x4",
+								"x2",
 							},
 						},
 					},
@@ -2461,19 +2459,19 @@ func TestFindTopologyAssignments(t *testing.T) {
 						{
 							Count: 1,
 							Values: []string{
-								"x2",
+								"x1",
 							},
 						},
 						{
 							Count: 1,
 							Values: []string{
-								"x3",
+								"x5",
 							},
 						},
 						{
 							Count: 2,
 							Values: []string{
-								"x6",
+								"x4",
 							},
 						},
 					},
@@ -2485,33 +2483,33 @@ func TestFindTopologyAssignments(t *testing.T) {
 			//         |
 			//        r1
 			//    /    |    \
-			// x1:4, x2:3, x3:2
+			// x3:4, x5:3, x1:2
 			//
 			nodes: []corev1.Node{
-				*testingnode.MakeNode("b1-r1-x1").
+				*testingnode.MakeNode("b1-r1-x3").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x1").
+					Label(corev1.LabelHostname, "x3").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("4"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r1-x2").
+				*testingnode.MakeNode("b1-r1-x5").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x2").
+					Label(corev1.LabelHostname, "x5").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("3"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r1-x3").
+				*testingnode.MakeNode("b1-r1-x1").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x3").
+					Label(corev1.LabelHostname, "x1").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("2"),
 						corev1.ResourcePods: resource.MustParse("10"),
@@ -2534,13 +2532,13 @@ func TestFindTopologyAssignments(t *testing.T) {
 					Levels: defaultOneLevel,
 					Domains: []kueue.TopologyDomainAssignment{
 						{
-							Count: 4,
+							Count: 2,
 							Values: []string{
 								"x1",
 							},
 						},
 						{
-							Count: 2,
+							Count: 4,
 							Values: []string{
 								"x3",
 							},
@@ -2554,33 +2552,33 @@ func TestFindTopologyAssignments(t *testing.T) {
 			//         |
 			//        r1
 			//    /    |    \
-			// x1:4, x2:3, x3:2
+			// x3:4, x5:3, x1:2
 			//
 			nodes: []corev1.Node{
-				*testingnode.MakeNode("b1-r1-x1").
+				*testingnode.MakeNode("b1-r1-x3").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x1").
+					Label(corev1.LabelHostname, "x3").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("4"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r1-x2").
+				*testingnode.MakeNode("b1-r1-x5").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x2").
+					Label(corev1.LabelHostname, "x5").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("3"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r1-x3").
+				*testingnode.MakeNode("b1-r1-x1").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x3").
+					Label(corev1.LabelHostname, "x1").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("2"),
 						corev1.ResourcePods: resource.MustParse("10"),
@@ -2605,13 +2603,13 @@ func TestFindTopologyAssignments(t *testing.T) {
 						{
 							Count: 2,
 							Values: []string{
-								"x2",
+								"x1",
 							},
 						},
 						{
 							Count: 2,
 							Values: []string{
-								"x3",
+								"x5",
 							},
 						},
 					},
@@ -2625,53 +2623,53 @@ func TestFindTopologyAssignments(t *testing.T) {
 			//         |                 |
 			//        r1                r1
 			//    /    |    \        /   |
-			// x1:4, x2:3, x3:2   x4:4  x5:2
+			// x3:4, x5:3, x1:2   x6:4  x2:2
 			//
 			nodes: []corev1.Node{
-				*testingnode.MakeNode("b1-r1-x1").
+				*testingnode.MakeNode("b1-r1-x3").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x1").
+					Label(corev1.LabelHostname, "x3").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("4"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r1-x2").
+				*testingnode.MakeNode("b1-r1-x5").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x2").
+					Label(corev1.LabelHostname, "x5").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("3"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r1-x3").
+				*testingnode.MakeNode("b1-r1-x1").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x3").
+					Label(corev1.LabelHostname, "x1").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("2"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b2-r1-x4").
+				*testingnode.MakeNode("b2-r1-x6").
 					Label(tasBlockLabel, "b2").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x4").
+					Label(corev1.LabelHostname, "x6").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("4"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b2-r1-x5").
+				*testingnode.MakeNode("b2-r1-x2").
 					Label(tasBlockLabel, "b2").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x5").
+					Label(corev1.LabelHostname, "x2").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("2"),
 						corev1.ResourcePods: resource.MustParse("10"),
@@ -2696,19 +2694,19 @@ func TestFindTopologyAssignments(t *testing.T) {
 						{
 							Count: 2,
 							Values: []string{
-								"x2",
+								"x1",
 							},
 						},
 						{
-							Count: 2,
+							Count: 4,
 							Values: []string{
 								"x3",
 							},
 						},
 						{
-							Count: 4,
+							Count: 2,
 							Values: []string{
-								"x1",
+								"x5",
 							},
 						},
 					},
@@ -2722,43 +2720,43 @@ func TestFindTopologyAssignments(t *testing.T) {
 			//         |                 |
 			//        r1                r1
 			//    /    |    \            |
-			// x1:3, x2:3, x3:3   		x4:6
+			// x3:3, x5:3, x1:3   		x6:6
 			//
 			nodes: []corev1.Node{
-				*testingnode.MakeNode("b1-r1-x1").
+				*testingnode.MakeNode("b1-r1-x3").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x1").
+					Label(corev1.LabelHostname, "x3").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("3"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r1-x2").
+				*testingnode.MakeNode("b1-r1-x5").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x2").
+					Label(corev1.LabelHostname, "x5").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("3"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r1-x3").
+				*testingnode.MakeNode("b1-r1-x1").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x3").
+					Label(corev1.LabelHostname, "x1").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("3"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b2-r1-x4").
+				*testingnode.MakeNode("b2-r1-x6").
 					Label(tasBlockLabel, "b2").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x4").
+					Label(corev1.LabelHostname, "x6").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("6"),
 						corev1.ResourcePods: resource.MustParse("10"),
@@ -2789,13 +2787,13 @@ func TestFindTopologyAssignments(t *testing.T) {
 						{
 							Count: 3,
 							Values: []string{
-								"x2",
+								"x3",
 							},
 						},
 						{
 							Count: 6,
 							Values: []string{
-								"x4",
+								"x6",
 							},
 						},
 					},
@@ -2808,32 +2806,32 @@ func TestFindTopologyAssignments(t *testing.T) {
 			//     /    |    \
 			//   r1    r2    r3
 			//   |      |     |
-			//   x1:2  x2:2  x3:2
+			//   x3:2  x5:2  x1:2
 			nodes: []corev1.Node{
-				*testingnode.MakeNode("b1-r1-x1").
+				*testingnode.MakeNode("b1-r1-x3").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x1").
+					Label(corev1.LabelHostname, "x3").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("2"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r2-x2").
+				*testingnode.MakeNode("b1-r2-x5").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r2").
-					Label(corev1.LabelHostname, "x2").
+					Label(corev1.LabelHostname, "x5").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("2"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r3-x3").
+				*testingnode.MakeNode("b1-r3-x1").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r3").
-					Label(corev1.LabelHostname, "x3").
+					Label(corev1.LabelHostname, "x1").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("2"),
 						corev1.ResourcePods: resource.MustParse("10"),
@@ -2861,42 +2859,42 @@ func TestFindTopologyAssignments(t *testing.T) {
 			//     /    /    \    \
 			//   r1    r2    r3    r4
 			//   |      |     |     |
-			//   x1:3  x2:1  x3:1  x4:1
+			//   x3:3  x5:1  x1:1  x6:1
 			nodes: []corev1.Node{
-				*testingnode.MakeNode("b1-r1-x1").
+				*testingnode.MakeNode("b1-r1-x3").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x1").
+					Label(corev1.LabelHostname, "x3").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("3"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r2-x2").
+				*testingnode.MakeNode("b1-r2-x5").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r2").
-					Label(corev1.LabelHostname, "x2").
+					Label(corev1.LabelHostname, "x5").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("1"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r3-x3").
+				*testingnode.MakeNode("b1-r3-x1").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r3").
-					Label(corev1.LabelHostname, "x3").
+					Label(corev1.LabelHostname, "x1").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("1"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r4-x4").
+				*testingnode.MakeNode("b1-r4-x6").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r4").
-					Label(corev1.LabelHostname, "x4").
+					Label(corev1.LabelHostname, "x6").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("1"),
 						corev1.ResourcePods: resource.MustParse("10"),
@@ -2924,52 +2922,52 @@ func TestFindTopologyAssignments(t *testing.T) {
 			//    /    |    \      |    \
 			//   r1    r2    r3    r4    r5
 			//    |    |     |     |     |
-			//   x1:2  x2:2  x3:2  x4:3  x5:3
+			//   x3:2  x5:2  x1:2  x6:3  x2:3
 			nodes: []corev1.Node{
-				*testingnode.MakeNode("b1-r1-x1").
+				*testingnode.MakeNode("b1-r1-x3").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x1").
+					Label(corev1.LabelHostname, "x3").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("2"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r2-x2").
+				*testingnode.MakeNode("b1-r2-x5").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r2").
-					Label(corev1.LabelHostname, "x2").
+					Label(corev1.LabelHostname, "x5").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("2"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r3-x3").
+				*testingnode.MakeNode("b1-r3-x1").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r3").
-					Label(corev1.LabelHostname, "x3").
+					Label(corev1.LabelHostname, "x1").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("2"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b2-r4-x4").
+				*testingnode.MakeNode("b2-r4-x6").
 					Label(tasBlockLabel, "b2").
 					Label(tasRackLabel, "r4").
-					Label(corev1.LabelHostname, "x4").
+					Label(corev1.LabelHostname, "x6").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("3"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b2-r5-x5").
+				*testingnode.MakeNode("b2-r5-x2").
 					Label(tasBlockLabel, "b2").
 					Label(tasRackLabel, "r5").
-					Label(corev1.LabelHostname, "x5").
+					Label(corev1.LabelHostname, "x2").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("3"),
 						corev1.ResourcePods: resource.MustParse("10"),
@@ -2994,13 +2992,13 @@ func TestFindTopologyAssignments(t *testing.T) {
 						{
 							Count: 3,
 							Values: []string{
-								"x4",
+								"x6",
 							},
 						},
 						{
 							Count: 3,
 							Values: []string{
-								"x5",
+								"x2",
 							},
 						},
 					},
@@ -3059,33 +3057,33 @@ func TestFindTopologyAssignments(t *testing.T) {
 			//         |
 			//        r1
 			//    /    |    \
-			// x1:3, x2:3, x3:3
+			// x3:3, x5:3, x1:3
 			//
 			nodes: []corev1.Node{
-				*testingnode.MakeNode("b1-r1-x1").
+				*testingnode.MakeNode("b1-r1-x3").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x1").
+					Label(corev1.LabelHostname, "x3").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("3"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r1-x2").
+				*testingnode.MakeNode("b1-r1-x5").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x2").
+					Label(corev1.LabelHostname, "x5").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("3"),
 						corev1.ResourcePods: resource.MustParse("10"),
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r1-x3").
+				*testingnode.MakeNode("b1-r1-x1").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x3").
+					Label(corev1.LabelHostname, "x1").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("3"),
 						corev1.ResourcePods: resource.MustParse("10"),
@@ -3109,19 +3107,19 @@ func TestFindTopologyAssignments(t *testing.T) {
 						{
 							Count: 2,
 							Values: []string{
-								"x3",
+								"x1",
 							},
 						},
 						{
 							Count: 2,
 							Values: []string{
-								"x2",
+								"x3",
 							},
 						},
 						{
 							Count: 2,
 							Values: []string{
-								"x1",
+								"x5",
 							},
 						},
 					},
@@ -3146,13 +3144,13 @@ func TestFindTopologyAssignments(t *testing.T) {
 						{
 							Count: 4,
 							Values: []string{
-								"x1",
+								"x3",
 							},
 						},
 						{
 							Count: 2,
 							Values: []string{
-								"x4",
+								"x6",
 							},
 						},
 					},
@@ -3177,19 +3175,19 @@ func TestFindTopologyAssignments(t *testing.T) {
 						{
 							Count: 1,
 							Values: []string{
-								"x2",
+								"x1",
 							},
 						},
 						{
 							Count: 1,
 							Values: []string{
-								"x3",
+								"x5",
 							},
 						},
 						{
 							Count: 2,
 							Values: []string{
-								"x6",
+								"x4",
 							},
 						},
 					},
@@ -3611,13 +3609,13 @@ func TestFindTopologyAssignments(t *testing.T) {
 			//        |               |
 			//       r1              r2
 			//    /   |   \       /   |   \
-			//  x1   x2   x3    x4   x5   x6
+			//  x3   x5   x1    x6   x2   x4
 			//
 			nodes: []corev1.Node{
-				*testingnode.MakeNode("b1-r1-x1").
+				*testingnode.MakeNode("b1-r1-x3").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x1").
+					Label(corev1.LabelHostname, "x3").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("2"),
 						corev1.ResourcePods: resource.MustParse("10"),
@@ -3625,10 +3623,10 @@ func TestFindTopologyAssignments(t *testing.T) {
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r1-x2").
+				*testingnode.MakeNode("b1-r1-x5").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x2").
+					Label(corev1.LabelHostname, "x5").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("2"),
 						corev1.ResourcePods: resource.MustParse("10"),
@@ -3636,10 +3634,10 @@ func TestFindTopologyAssignments(t *testing.T) {
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r1-x3").
+				*testingnode.MakeNode("b1-r1-x1").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x3").
+					Label(corev1.LabelHostname, "x1").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("2"),
 						corev1.ResourcePods: resource.MustParse("10"),
@@ -3647,10 +3645,10 @@ func TestFindTopologyAssignments(t *testing.T) {
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b2-r4-x4").
+				*testingnode.MakeNode("b2-r4-x6").
 					Label(tasBlockLabel, "b2").
 					Label(tasRackLabel, "r4").
-					Label(corev1.LabelHostname, "x4").
+					Label(corev1.LabelHostname, "x6").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("1"),
 						corev1.ResourcePods: resource.MustParse("10"),
@@ -3658,10 +3656,10 @@ func TestFindTopologyAssignments(t *testing.T) {
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b2-r5-x5").
+				*testingnode.MakeNode("b2-r5-x2").
 					Label(tasBlockLabel, "b2").
 					Label(tasRackLabel, "r5").
-					Label(corev1.LabelHostname, "x5").
+					Label(corev1.LabelHostname, "x2").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("2"),
 						corev1.ResourcePods: resource.MustParse("10"),
@@ -3669,10 +3667,10 @@ func TestFindTopologyAssignments(t *testing.T) {
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b2-r6-x6").
+				*testingnode.MakeNode("b2-r6-x4").
 					Label(tasBlockLabel, "b2").
 					Label(tasRackLabel, "r6").
-					Label(corev1.LabelHostname, "x6").
+					Label(corev1.LabelHostname, "x4").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("2"),
 						corev1.ResourcePods: resource.MustParse("10"),
@@ -3722,13 +3720,13 @@ func TestFindTopologyAssignments(t *testing.T) {
 							{
 								Count: 1,
 								Values: []string{
-									"x2",
+									"x3",
 								},
 							},
 							{
 								Count: 1,
 								Values: []string{
-									"x3",
+									"x5",
 								},
 							},
 						},
@@ -3741,13 +3739,13 @@ func TestFindTopologyAssignments(t *testing.T) {
 			//        /   \             /    \
 			//      r1     r2         r3     r4
 			//    /  |     |  \     /  |     |  \
-			//  x1  x2    x3  x4  x5   x6   x7   x8
+			//  x3  x5    x1  x6  x2   x4   x7   x8
 			//
 			nodes: []corev1.Node{
-				*testingnode.MakeNode("b1-r1-x1").
+				*testingnode.MakeNode("b1-r1-x3").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x1").
+					Label(corev1.LabelHostname, "x3").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("1"),
 						corev1.ResourcePods: resource.MustParse("10"),
@@ -3755,10 +3753,10 @@ func TestFindTopologyAssignments(t *testing.T) {
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r1-x2").
+				*testingnode.MakeNode("b1-r1-x5").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r1").
-					Label(corev1.LabelHostname, "x2").
+					Label(corev1.LabelHostname, "x5").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("1"),
 						corev1.ResourcePods: resource.MustParse("10"),
@@ -3766,10 +3764,10 @@ func TestFindTopologyAssignments(t *testing.T) {
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r2-x3").
+				*testingnode.MakeNode("b1-r2-x1").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r2").
-					Label(corev1.LabelHostname, "x3").
+					Label(corev1.LabelHostname, "x1").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("1"),
 						corev1.ResourcePods: resource.MustParse("10"),
@@ -3777,10 +3775,10 @@ func TestFindTopologyAssignments(t *testing.T) {
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b1-r2-x4").
+				*testingnode.MakeNode("b1-r2-x6").
 					Label(tasBlockLabel, "b1").
 					Label(tasRackLabel, "r2").
-					Label(corev1.LabelHostname, "x4").
+					Label(corev1.LabelHostname, "x6").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("1"),
 						corev1.ResourcePods: resource.MustParse("10"),
@@ -3788,10 +3786,10 @@ func TestFindTopologyAssignments(t *testing.T) {
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b2-r3-x5").
+				*testingnode.MakeNode("b2-r3-x2").
 					Label(tasBlockLabel, "b2").
 					Label(tasRackLabel, "r3").
-					Label(corev1.LabelHostname, "x5").
+					Label(corev1.LabelHostname, "x2").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("1"),
 						corev1.ResourcePods: resource.MustParse("10"),
@@ -3799,10 +3797,10 @@ func TestFindTopologyAssignments(t *testing.T) {
 					}).
 					Ready().
 					Obj(),
-				*testingnode.MakeNode("b2-r3-x6").
+				*testingnode.MakeNode("b2-r3-x4").
 					Label(tasBlockLabel, "b2").
 					Label(tasRackLabel, "r3").
-					Label(corev1.LabelHostname, "x6").
+					Label(corev1.LabelHostname, "x4").
 					StatusAllocatable(corev1.ResourceList{
 						corev1.ResourceCPU:  resource.MustParse("1"),
 						corev1.ResourcePods: resource.MustParse("10"),
@@ -3852,7 +3850,7 @@ func TestFindTopologyAssignments(t *testing.T) {
 							{
 								Count: 1,
 								Values: []string{
-									"x1",
+									"x3",
 								},
 							},
 						},
@@ -3875,13 +3873,13 @@ func TestFindTopologyAssignments(t *testing.T) {
 							{
 								Count: 1,
 								Values: []string{
-									"x2",
+									"x5",
 								},
 							},
 							{
 								Count: 1,
 								Values: []string{
-									"x3",
+									"x1",
 								},
 							},
 						},
@@ -3951,7 +3949,7 @@ func TestFindTopologyAssignments(t *testing.T) {
 					wantAssignment: &kueue.TopologyAssignment{
 						Levels: []string{corev1.LabelHostname},
 						Domains: []kueue.TopologyDomainAssignment{
-							{Count: 9, Values: []string{"x5"}},
+							{Count: 9, Values: []string{"x2"}},
 						},
 					},
 				},
@@ -3967,7 +3965,7 @@ func TestFindTopologyAssignments(t *testing.T) {
 					wantAssignment: &kueue.TopologyAssignment{
 						Levels: []string{corev1.LabelHostname},
 						Domains: []kueue.TopologyDomainAssignment{
-							{Count: 2, Values: []string{"x1"}},
+							{Count: 2, Values: []string{"x3"}},
 						},
 					},
 				},
@@ -4072,7 +4070,7 @@ func TestFindTopologyAssignments(t *testing.T) {
 					wantAssignment: &kueue.TopologyAssignment{
 						Levels: []string{corev1.LabelHostname},
 						Domains: []kueue.TopologyDomainAssignment{
-							{Count: 8, Values: []string{"x5"}},
+							{Count: 8, Values: []string{"x2"}},
 						},
 					},
 				},
@@ -4088,7 +4086,7 @@ func TestFindTopologyAssignments(t *testing.T) {
 					wantAssignment: &kueue.TopologyAssignment{
 						Levels: []string{corev1.LabelHostname},
 						Domains: []kueue.TopologyDomainAssignment{
-							{Count: 2, Values: []string{"x5"}},
+							{Count: 2, Values: []string{"x2"}},
 						},
 					},
 				},
@@ -4159,9 +4157,6 @@ func TestFindTopologyAssignments(t *testing.T) {
 					FailureReason: ps.wantReason,
 				}
 				if ps.wantAssignment != nil {
-					sort.Slice(ps.wantAssignment.Domains, func(i, j int) bool {
-						return utiltas.DomainID(ps.wantAssignment.Domains[i].Values) < utiltas.DomainID(ps.wantAssignment.Domains[j].Values)
-					})
 					wantPodSetResult.TopologyAssignment = ps.wantAssignment
 				}
 				wantResult[kueue.PodSetReference(ps.podSetName)] = wantPodSetResult
diff --git a/pkg/controller/core/clusterqueue_controller_test.go b/pkg/controller/core/clusterqueue_controller_test.go
index ea880ca44..beb644012 100644
--- a/pkg/controller/core/clusterqueue_controller_test.go
+++ b/pkg/controller/core/clusterqueue_controller_test.go
@@ -17,22 +17,18 @@ limitations under the License.
 package core
 
 import (
-	"context"
 	"testing"
-	"time"
 
 	"github.com/google/go-cmp/cmp"
 	"github.com/google/go-cmp/cmp/cmpopts"
 	corev1 "k8s.io/api/core/v1"
 	"k8s.io/apimachinery/pkg/api/resource"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/apimachinery/pkg/util/wait"
 	"k8s.io/utils/ptr"
 
 	kueue "sigs.k8s.io/kueue/apis/kueue/v1beta1"
 	qcache "sigs.k8s.io/kueue/pkg/cache/queue"
 	schdcache "sigs.k8s.io/kueue/pkg/cache/scheduler"
-	"sigs.k8s.io/kueue/pkg/features"
 	"sigs.k8s.io/kueue/pkg/metrics"
 	utiltesting "sigs.k8s.io/kueue/pkg/util/testing"
 	testingmetrics "sigs.k8s.io/kueue/pkg/util/testing/metrics"
@@ -518,90 +514,3 @@ func TestRecordResourceMetrics(t *testing.T) {
 		})
 	}
 }
-
-func TestClusterQueuePendingWorkloadsStatus(t *testing.T) {
-	cqName := "test-cq"
-	lqName := "test-lq"
-	const lowPrio, highPrio = 0, 100
-	defaultWls := &kueue.WorkloadList{
-		Items: []kueue.Workload{
-			*utiltesting.MakeWorkload("one", "").Queue(kueue.LocalQueueName(lqName)).Priority(highPrio).Obj(),
-			*utiltesting.MakeWorkload("two", "").Queue(kueue.LocalQueueName(lqName)).Priority(lowPrio).Obj(),
-		},
-	}
-	testCases := map[string]struct {
-		queueVisibilityUpdateInterval        time.Duration
-		queueVisibilityClusterQueuesMaxCount int32
-		wantPendingWorkloadsStatus           *kueue.ClusterQueuePendingWorkloadsStatus
-		enableQueueVisibility                bool
-	}{
-		"queue visibility is disabled": {},
-		"queue visibility is disabled but maxcount is provided": {
-			queueVisibilityClusterQueuesMaxCount: 2,
-		},
-		"queue visibility is enabled": {
-			queueVisibilityClusterQueuesMaxCount: 2,
-			queueVisibilityUpdateInterval:        10 * time.Millisecond,
-			enableQueueVisibility:                true,
-			wantPendingWorkloadsStatus: &kueue.ClusterQueuePendingWorkloadsStatus{
-				Head: []kueue.ClusterQueuePendingWorkload{
-					{Name: "one"}, {Name: "two"},
-				},
-			},
-		},
-		"verify the head of pending workloads when the number of pending workloads exceeds MaxCount": {
-			queueVisibilityClusterQueuesMaxCount: 1,
-			queueVisibilityUpdateInterval:        10 * time.Millisecond,
-			enableQueueVisibility:                true,
-			wantPendingWorkloadsStatus: &kueue.ClusterQueuePendingWorkloadsStatus{
-				Head: []kueue.ClusterQueuePendingWorkload{
-					{Name: "one"},
-				},
-			},
-		},
-	}
-	for name, tc := range testCases {
-		t.Run(name, func(t *testing.T) {
-			features.SetFeatureGateDuringTest(t, features.QueueVisibility, tc.enableQueueVisibility)
-
-			cq := utiltesting.MakeClusterQueue(cqName).
-				QueueingStrategy(kueue.StrictFIFO).Obj()
-			lq := utiltesting.MakeLocalQueue(lqName, "").
-				ClusterQueue(cqName).Obj()
-
-			cl := utiltesting.NewClientBuilder().WithLists(defaultWls).WithObjects(lq, cq).WithStatusSubresource(lq, cq).
-				Build()
-			cCache := schdcache.New(cl)
-			qManager := qcache.NewManager(cl, cCache)
-			ctx, _ := utiltesting.ContextWithLog(t)
-			if err := qManager.AddClusterQueue(ctx, cq); err != nil {
-				t.Fatalf("Inserting clusterQueue in manager: %v", err)
-			}
-			if err := qManager.AddLocalQueue(ctx, lq); err != nil {
-				t.Fatalf("Inserting localQueue in manager: %v", err)
-			}
-
-			r := NewClusterQueueReconciler(
-				cl,
-				qManager,
-				cCache,
-				WithQueueVisibilityUpdateInterval(tc.queueVisibilityUpdateInterval),
-				WithQueueVisibilityClusterQueuesMaxCount(tc.queueVisibilityClusterQueuesMaxCount),
-			)
-
-			go func() {
-				if err := r.Start(ctx); err != nil {
-					t.Errorf("error starting the cluster queue reconciler: %v", err)
-				}
-			}()
-
-			diff := ""
-			if err := wait.PollUntilContextTimeout(ctx, time.Second, 10*time.Second, false, func(ctx context.Context) (done bool, err error) {
-				diff = cmp.Diff(tc.wantPendingWorkloadsStatus, r.getWorkloadsStatus(cq), cmpopts.IgnoreFields(kueue.ClusterQueuePendingWorkloadsStatus{}, "LastChangeTime"))
-				return diff == "", nil
-			}); err != nil {
-				t.Fatalf("Failed to get the expected pending workloads status, last diff=%s", diff)
-			}
-		})
-	}
-}
diff --git a/pkg/controller/jobs/raycluster/raycluster_webhook_test.go b/pkg/controller/jobs/raycluster/raycluster_webhook_test.go
index 7db59b4a3..bc929b27b 100644
--- a/pkg/controller/jobs/raycluster/raycluster_webhook_test.go
+++ b/pkg/controller/jobs/raycluster/raycluster_webhook_test.go
@@ -149,7 +149,7 @@ func TestValidateCreate(t *testing.T) {
 				WithEnableAutoscaling(ptr.To(true)).
 				Obj(),
 			wantErr: field.ErrorList{
-				field.Invalid(field.NewPath("spec", "enableInTreeAutoscaling"), ptr.To(true), "a kueue managed job should not use autoscaling"),
+				field.Invalid(field.NewPath("spec", "enableInTreeAutoscaling"), ptr.To(true), "a kueue managed job can use autoscaling only when the ElasticJobsViaWorkloadSlices feature gate is on and the job is an elastic job"),
 			}.ToAggregate(),
 		},
 		"invalid managed - too many worker groups": {
diff --git a/pkg/controller/tas/node_failure_controller_test.go b/pkg/controller/tas/node_failure_controller_test.go
index d9385810b..a6c399e60 100644
--- a/pkg/controller/tas/node_failure_controller_test.go
+++ b/pkg/controller/tas/node_failure_controller_test.go
@@ -75,11 +75,8 @@ func TestNodeFailureReconciler(t *testing.T) {
 		Admitted(true).
 		Obj()
 
-	workloadWithAnnotation := baseWorkload.DeepCopy()
-	workloadWithAnnotation.Annotations = map[string]string{
-		kueuealpha.NodeToReplaceAnnotation: nodeName,
-	}
-
+	workloadWithNodeToReplace := baseWorkload.DeepCopy()
+	workloadWithNodeToReplace.Status.NodesToReplace = []string{nodeName}
 	workloadWithTwoNodes := utiltesting.MakeWorkload(wlName, nsName).
 		Finalizers(kueue.ResourceInUseFinalizerName).
 		PodSets(*utiltesting.MakePodSet(kueue.DefaultPodSetName, 2).Request(corev1.ResourceCPU, "1").Obj()).
@@ -135,7 +132,7 @@ func TestNodeFailureReconciler(t *testing.T) {
 		initObjs          []client.Object
 		reconcileRequests []reconcile.Request
 		advanceClock      time.Duration
-		wantFailedNode    string
+		wantFailedNodes   []string
 		wantRequeue       time.Duration
 		wantEvictedCond   *metav1.Condition
 		featureGates      []featuregate.Feature
@@ -150,19 +147,19 @@ func TestNodeFailureReconciler(t *testing.T) {
 				basePod.DeepCopy(),
 			},
 			reconcileRequests: []reconcile.Request{{NamespacedName: types.NamespacedName{Name: nodeName}}},
-			wantFailedNode:    "",
+			wantFailedNodes:   nil,
 		},
-		"Node becomes healthy, annotation is removed": {
+		"Node becomes healthy, it is removed from the list of nodes to replace": {
 			initObjs: []client.Object{
 				baseNode.Clone().StatusConditions(corev1.NodeCondition{
 					Type:               corev1.NodeReady,
 					Status:             corev1.ConditionTrue,
 					LastTransitionTime: now}).Obj(),
-				workloadWithAnnotation.DeepCopy(),
+				workloadWithNodeToReplace.DeepCopy(),
 				basePod.DeepCopy(),
 			},
 			reconcileRequests: []reconcile.Request{{NamespacedName: types.NamespacedName{Name: nodeName}}},
-			wantFailedNode:    "",
+			wantFailedNodes:   nil,
 		},
 
 		"Node Found and Unhealthy (NotReady), delay not passed - not marked as unavailable": {
@@ -175,7 +172,7 @@ func TestNodeFailureReconciler(t *testing.T) {
 				basePod.DeepCopy(),
 			},
 			reconcileRequests: []reconcile.Request{{NamespacedName: types.NamespacedName{Name: nodeName}}},
-			wantFailedNode:    "",
+			wantFailedNodes:   nil,
 			wantRequeue:       NodeFailureDelay,
 		},
 		"Node Found and Unhealthy (NotReady), delay passed - marked as unavailable": {
@@ -188,7 +185,7 @@ func TestNodeFailureReconciler(t *testing.T) {
 				basePod.DeepCopy(),
 			},
 			reconcileRequests: []reconcile.Request{{NamespacedName: types.NamespacedName{Name: nodeName}}},
-			wantFailedNode:    nodeName,
+			wantFailedNodes:   []string{nodeName},
 		},
 		"Node NotReady, pod terminating, marked as unavailable": {
 			featureGates: []featuregate.Feature{features.TASReplaceNodeOnPodTermination},
@@ -201,7 +198,7 @@ func TestNodeFailureReconciler(t *testing.T) {
 				terminatingPod,
 			},
 			reconcileRequests: []reconcile.Request{{NamespacedName: types.NamespacedName{Name: nodeName}}},
-			wantFailedNode:    nodeName,
+			wantFailedNodes:   []string{nodeName},
 		},
 		"Node NotReady, pod failed, marked as unavailable": {
 			featureGates: []featuregate.Feature{features.TASReplaceNodeOnPodTermination},
@@ -214,7 +211,7 @@ func TestNodeFailureReconciler(t *testing.T) {
 				failedPod,
 			},
 			reconcileRequests: []reconcile.Request{{NamespacedName: types.NamespacedName{Name: nodeName}}},
-			wantFailedNode:    nodeName,
+			wantFailedNodes:   []string{nodeName},
 		},
 		"Node NotReady, pod failed, ReplaceNodeOnPodTermination feature gate off, requeued": {
 			initObjs: []client.Object{
@@ -226,7 +223,7 @@ func TestNodeFailureReconciler(t *testing.T) {
 				failedPod,
 			},
 			reconcileRequests: []reconcile.Request{{NamespacedName: types.NamespacedName{Name: nodeName}}},
-			wantFailedNode:    "",
+			wantFailedNodes:   nil,
 			wantRequeue:       NodeFailureDelay,
 		},
 		"Node NotReady, pod running, not marked as unavailable, requeued": {
@@ -249,7 +246,7 @@ func TestNodeFailureReconciler(t *testing.T) {
 				basePod.DeepCopy(),
 			},
 			reconcileRequests: []reconcile.Request{{NamespacedName: types.NamespacedName{Name: nodeName}}},
-			wantFailedNode:    nodeName,
+			wantFailedNodes:   []string{nodeName},
 		},
 		"Two Nodes Unhealthy (NotReady), delay passed - workload evicted": {
 			featureGates: []featuregate.Feature{features.TASFailedNodeReplacement},
@@ -263,23 +260,24 @@ func TestNodeFailureReconciler(t *testing.T) {
 					Status:             corev1.ConditionFalse,
 					LastTransitionTime: earlierTime}).Obj(),
 				workloadWithTwoNodes.DeepCopy(),
-				testingpod.MakePod("pod1", nsName).Annotation(kueuealpha.WorkloadAnnotation, wlName).Label(kueuealpha.TASLabel, "true").NodeName(nodeName).Obj(),
-				testingpod.MakePod("pod2", nsName).Annotation(kueuealpha.WorkloadAnnotation, wlName).Label(kueuealpha.TASLabel, "true").NodeName(nodeName2).Obj(),
+				testingpod.MakePod("pod1", nsName).Annotation(kueuealpha.WorkloadAnnotation, wlName).NodeName(nodeName).Obj(),
+				testingpod.MakePod("pod2", nsName).Annotation(kueuealpha.WorkloadAnnotation, wlName).NodeName(nodeName2).Obj(),
 			},
 			reconcileRequests: []reconcile.Request{
 				{NamespacedName: types.NamespacedName{Name: nodeName}},
 				{NamespacedName: types.NamespacedName{Name: nodeName2}},
 			},
-			wantFailedNode: "",
+			wantFailedNodes: nil,
 			wantEvictedCond: &metav1.Condition{
 				Type:    kueue.WorkloadEvicted,
 				Status:  metav1.ConditionTrue,
 				Reason:  kueue.WorkloadEvictedDueToNodeFailures,
-				Message: fmt.Sprintf(nodeMultipleFailuresEvictionMessageFormat, nodeName, nodeName2),
+				Message: fmt.Sprintf(nodeMultipleFailuresEvictionMessageFormat, nodeName+", "+nodeName2),
 			},
 		},
 	}
 	for name, tc := range tests {
+		fakeClock.SetTime(testStartTime)
 		t.Run(name, func(t *testing.T) {
 			for _, fg := range tc.featureGates {
 				features.SetFeatureGateDuringTest(t, fg, true)
@@ -312,10 +310,11 @@ func TestNodeFailureReconciler(t *testing.T) {
 				t.Fatalf("Failed to get workload %q: %v", wlName, err)
 			}
 
-			gotFailedNode := wl.GetAnnotations()[kueuealpha.NodeToReplaceAnnotation]
-			expectedNode := tc.wantFailedNode
-			if diff := cmp.Diff(expectedNode, gotFailedNode); diff != "" {
-				t.Errorf("Unexpected FailedNodes in annotation (-want/+got):\n%s", diff)
+			gotNodesToReplace := wl.Status.NodesToReplace
+			if len(tc.wantFailedNodes) > 0 {
+				if diff := cmp.Diff(tc.wantFailedNodes, gotNodesToReplace, cmpopts.EquateEmpty()); diff != "" {
+					t.Errorf("Unexpected nodesToReplace in status (-want/+got):\n%s", diff)
+				}
 			}
 			if diff := cmp.Diff(tc.wantRequeue, result.RequeueAfter); diff != "" {
 				t.Errorf("Unexpected RequeueAfter (-want/+got):\n%s", diff)
diff --git a/pkg/features/kube_features_test.go b/pkg/features/kube_features_test.go
index 923186fc7..bae6be084 100644
--- a/pkg/features/kube_features_test.go
+++ b/pkg/features/kube_features_test.go
@@ -24,9 +24,9 @@ import (
 )
 
 func TestFeatureGate(t *testing.T) {
-	featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, QueueVisibility, true)
+	featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, PartialAdmission, false)
 
-	if !utilfeature.DefaultFeatureGate.Enabled(PartialAdmission) {
-		t.Error("feature gate should be enabled")
+	if utilfeature.DefaultFeatureGate.Enabled(PartialAdmission) {
+		t.Error("feature gate should be disabled")
 	}
 }
diff --git a/pkg/scheduler/scheduler_test.go b/pkg/scheduler/scheduler_test.go
index 0ff12c4c6..27a91ca75 100644
--- a/pkg/scheduler/scheduler_test.go
+++ b/pkg/scheduler/scheduler_test.go
@@ -3786,7 +3786,7 @@ func TestLastSchedulingContext(t *testing.T) {
 		cqs                            []kueue.ClusterQueue
 		admittedWorkloads              []kueue.Workload
 		workloads                      []kueue.Workload
-		deleteWorkloads                []kueue.Workload
+		deleteWorkloads                []client.ObjectKey
 		wantPreempted                  sets.Set[workload.Reference]
 		wantAdmissionsOnFirstSchedule  map[workload.Reference]kueue.Admission
 		wantAdmissionsOnSecondSchedule map[workload.Reference]kueue.Admission
@@ -3826,14 +3826,10 @@ func TestLastSchedulingContext(t *testing.T) {
 					Request(corev1.ResourceCPU, "20").
 					Obj(),
 			},
-			deleteWorkloads: []kueue.Workload{
-				*utiltesting.MakeWorkload("low-1", "default").
-					Queue("main").
-					Request(corev1.ResourceCPU, "50").
-					ReserveQuota(utiltesting.MakeAdmission("eng-alpha").Assignment(corev1.ResourceCPU, "on-demand", "50").Obj()).
-					Admitted(true).
-					Obj(),
-			},
+			deleteWorkloads: []client.ObjectKey{{
+				Namespace: metav1.NamespaceDefault,
+				Name:      "low-1",
+			}},
 			wantPreempted:                 sets.Set[workload.Reference]{},
 			wantAdmissionsOnFirstSchedule: map[workload.Reference]kueue.Admission{},
 			wantAdmissionsOnSecondSchedule: map[workload.Reference]kueue.Admission{
@@ -3860,8 +3856,7 @@ func TestLastSchedulingContext(t *testing.T) {
 					Request(corev1.ResourceCPU, "20").
 					Obj(),
 			},
-			deleteWorkloads: []kueue.Workload{},
-			wantPreempted:   sets.Set[workload.Reference]{},
+			wantPreempted: sets.Set[workload.Reference]{},
 			wantAdmissionsOnFirstSchedule: map[workload.Reference]kueue.Admission{
 				"default/workload1": *utiltesting.MakeAdmission("eng-cohort-beta").Assignment(corev1.ResourceCPU, "on-demand", "20").Obj(),
 				"default/borrower":  *utiltesting.MakeAdmission("eng-cohort-alpha").Assignment(corev1.ResourceCPU, "on-demand", "20").Obj(),
@@ -3893,8 +3888,7 @@ func TestLastSchedulingContext(t *testing.T) {
 					Request(corev1.ResourceCPU, "20").
 					Obj(),
 			},
-			deleteWorkloads: []kueue.Workload{},
-			wantPreempted:   sets.Set[workload.Reference]{},
+			wantPreempted: sets.Set[workload.Reference]{},
 			wantAdmissionsOnFirstSchedule: map[workload.Reference]kueue.Admission{
 				"default/workload": *utiltesting.MakeAdmission("eng-cohort-theta").Assignment(corev1.ResourceCPU, "spot", "20").Obj(),
 			},
@@ -3930,8 +3924,7 @@ func TestLastSchedulingContext(t *testing.T) {
 					Request(corev1.ResourceCPU, "20").
 					Obj(),
 			},
-			deleteWorkloads: []kueue.Workload{},
-			wantPreempted:   sets.Set[workload.Reference]{},
+			wantPreempted: sets.Set[workload.Reference]{},
 			wantAdmissionsOnFirstSchedule: map[workload.Reference]kueue.Admission{
 				"default/workload": *utiltesting.MakeAdmission("eng-cohort-theta").Assignment(corev1.ResourceCPU, "on-demand", "20").Obj(),
 			},
@@ -3964,7 +3957,10 @@ func TestLastSchedulingContext(t *testing.T) {
 					Request(corev1.ResourceCPU, "20").
 					Obj(),
 			},
-			deleteWorkloads:               []kueue.Workload{*utiltesting.MakeWorkload("placeholder-alpha", "default").Obj()},
+			deleteWorkloads: []client.ObjectKey{{
+				Namespace: metav1.NamespaceDefault,
+				Name:      "placeholder-alpha",
+			}},
 			wantPreempted:                 sets.New[workload.Reference]("default/placeholder-alpha"),
 			wantAdmissionsOnFirstSchedule: map[workload.Reference]kueue.Admission{},
 			wantAdmissionsOnSecondSchedule: map[workload.Reference]kueue.Admission{
@@ -4047,8 +4043,11 @@ func TestLastSchedulingContext(t *testing.T) {
 					Request(corev1.ResourceCPU, "22").
 					Obj(),
 			},
-			deleteWorkloads: []kueue.Workload{*utiltesting.MakeWorkload("alpha2", "default").Obj()},
-			wantPreempted:   sets.New[workload.Reference]("default/alpha2"),
+			deleteWorkloads: []client.ObjectKey{{
+				Namespace: metav1.NamespaceDefault,
+				Name:      "alpha2",
+			}},
+			wantPreempted: sets.New[workload.Reference]("default/alpha2"),
 			wantAdmissionsOnSecondSchedule: map[workload.Reference]kueue.Admission{
 				"default/alpha1": *utiltesting.MakeAdmission("eng-cohort-alpha").Assignment(corev1.ResourceCPU, "on-demand", "22").Obj(),
 				"default/alpha3": *utiltesting.MakeAdmission("eng-cohort-alpha").Assignment(corev1.ResourceCPU, "spot", "22").Obj(),
@@ -4130,16 +4129,21 @@ func TestLastSchedulingContext(t *testing.T) {
 				t.Errorf("Unexpected scheduled workloads (-want,+got):\n%s", diff)
 			}
 
-			for _, wl := range tc.deleteWorkloads {
-				err := cl.Delete(ctx, &wl)
+			for _, workloadReference := range tc.deleteWorkloads {
+				var workload kueue.Workload
+				err := cl.Get(ctx, workloadReference, &workload)
+				if err != nil {
+					t.Errorf("Unable to get workload: %v", err)
+				}
+				err = cl.Delete(ctx, &workload)
 				if err != nil {
 					t.Errorf("Delete workload failed: %v", err)
 				}
-				err = cqCache.DeleteWorkload(log, &wl)
+				err = cqCache.DeleteWorkload(log, &workload)
 				if err != nil {
 					t.Errorf("Delete workload failed: %v", err)
 				}
-				qManager.QueueAssociatedInadmissibleWorkloadsAfter(ctx, &wl, nil)
+				qManager.QueueAssociatedInadmissibleWorkloadsAfter(ctx, &workload, nil)
 			}
 
 			scheduler.schedule(ctx)
@@ -4848,7 +4852,7 @@ func TestScheduleForTAS(t *testing.T) {
 			clusterQueues:   []kueue.ClusterQueue{defaultClusterQueue},
 			workloads: []kueue.Workload{
 				*utiltesting.MakeWorkload("foo", "default").
-					Annotations(map[string]string{kueuealpha.NodeToReplaceAnnotation: "x0"}).
+					NodesToReplace("x0").
 					Queue("tas-main").
 					PodSets(*utiltesting.MakePodSet("one", 1).
 						PreferredTopologyRequest(corev1.LabelHostname).
@@ -4884,7 +4888,7 @@ func TestScheduleForTAS(t *testing.T) {
 			clusterQueues:   []kueue.ClusterQueue{defaultClusterQueue},
 			workloads: []kueue.Workload{
 				*utiltesting.MakeWorkload("foo", "default").
-					Annotations(map[string]string{kueuealpha.NodeToReplaceAnnotation: "x0"}).
+					NodesToReplace("x0").
 					Queue("tas-main").
 					PodSets(*utiltesting.MakePodSet("one", 2).
 						PreferredTopologyRequest(tasRackLabel).
@@ -4922,7 +4926,7 @@ func TestScheduleForTAS(t *testing.T) {
 			clusterQueues:   []kueue.ClusterQueue{defaultClusterQueue},
 			workloads: []kueue.Workload{
 				*utiltesting.MakeWorkload("foo", "default").
-					Annotations(map[string]string{kueuealpha.NodeToReplaceAnnotation: "x0"}).
+					NodesToReplace("x0").
 					Queue("tas-main").
 					PodSets(*utiltesting.MakePodSet("one", 1).
 						PreferredTopologyRequest(tasRackLabel).
@@ -4963,7 +4967,7 @@ func TestScheduleForTAS(t *testing.T) {
 			clusterQueues:   []kueue.ClusterQueue{defaultClusterQueue},
 			workloads: []kueue.Workload{
 				*utiltesting.MakeWorkload("foo", "default").
-					Annotations(map[string]string{kueuealpha.NodeToReplaceAnnotation: "x0"}).
+					NodesToReplace("x0").
 					Queue("tas-main").
 					PodSets(*utiltesting.MakePodSet("one", 1).
 						PreferredTopologyRequest(tasRackLabel).
@@ -5005,7 +5009,7 @@ func TestScheduleForTAS(t *testing.T) {
 			clusterQueues:   []kueue.ClusterQueue{defaultClusterQueue},
 			workloads: []kueue.Workload{
 				*utiltesting.MakeWorkload("foo", "default").
-					Annotations(map[string]string{kueuealpha.NodeToReplaceAnnotation: "x0"}).
+					NodesToReplace("x0").
 					Queue("tas-main").
 					PodSets(*utiltesting.MakePodSet("one", 2).
 						RequiredTopologyRequest(tasRackLabel).
@@ -5043,7 +5047,7 @@ func TestScheduleForTAS(t *testing.T) {
 			clusterQueues:   []kueue.ClusterQueue{defaultClusterQueue},
 			workloads: []kueue.Workload{
 				*utiltesting.MakeWorkload("foo", "default").
-					Annotations(map[string]string{kueuealpha.NodeToReplaceAnnotation: "x0"}).
+					NodesToReplace("x0").
 					Queue("tas-main").
 					PodSets(*utiltesting.MakePodSet("one", 1).
 						RequiredTopologyRequest(tasRackLabel).
@@ -5079,7 +5083,7 @@ func TestScheduleForTAS(t *testing.T) {
 			clusterQueues:   []kueue.ClusterQueue{defaultClusterQueue},
 			workloads: []kueue.Workload{
 				*utiltesting.MakeWorkload("foo", "default").
-					Annotations(map[string]string{kueuealpha.NodeToReplaceAnnotation: "x0"}).
+					NodesToReplace("x0").
 					Queue("tas-main").
 					PodSets(*utiltesting.MakePodSet("one", 2).
 						RequiredTopologyRequest(tasRackLabel).
@@ -5122,7 +5126,7 @@ func TestScheduleForTAS(t *testing.T) {
 			clusterQueues:   []kueue.ClusterQueue{defaultClusterQueue},
 			workloads: []kueue.Workload{
 				*utiltesting.MakeWorkload("foo", "default").
-					Annotations(map[string]string{kueuealpha.NodeToReplaceAnnotation: "x0"}).
+					NodesToReplace("x0").
 					Queue("tas-main").
 					PodSets(
 						*utiltesting.MakePodSet("one", 1).
diff --git a/pkg/util/testing/wrappers.go b/pkg/util/testing/wrappers.go
index 3272119e4..3e52eaf78 100644
--- a/pkg/util/testing/wrappers.go
+++ b/pkg/util/testing/wrappers.go
@@ -348,6 +348,11 @@ func (w *WorkloadWrapper) Annotations(annotations map[string]string) *WorkloadWr
 	return w
 }
 
+func (w *WorkloadWrapper) NodesToReplace(nodesToReplace ...string) *WorkloadWrapper {
+	w.Status.NodesToReplace = nodesToReplace
+	return w
+}
+
 // DeletionTimestamp sets a deletion timestamp for the workload.
 func (w *WorkloadWrapper) DeletionTimestamp(t time.Time) *WorkloadWrapper {
 	w.Workload.DeletionTimestamp = ptr.To(metav1.NewTime(t).Rfc3339Copy())
diff --git a/pkg/util/testingjobs/raycluster/wrappers.go b/pkg/util/testingjobs/raycluster/wrappers.go
index 2edc0b679..5f576c2a6 100644
--- a/pkg/util/testingjobs/raycluster/wrappers.go
+++ b/pkg/util/testingjobs/raycluster/wrappers.go
@@ -133,6 +133,11 @@ func (j *ClusterWrapper) Queue(queue string) *ClusterWrapper {
 	return j
 }
 
+func (j *ClusterWrapper) SetAnnotation(key, content string) *ClusterWrapper {
+	j.Annotations[key] = content
+	return j
+}
+
 // Clone returns deep copy of the Job.
 func (j *ClusterWrapper) Clone() *ClusterWrapper {
 	return &ClusterWrapper{RayCluster: *j.DeepCopy()}
@@ -143,6 +148,11 @@ func (j *ClusterWrapper) WithEnableAutoscaling(value *bool) *ClusterWrapper {
 	return j
 }
 
+func (j *ClusterWrapper) ScaleFirstWorkerGroup(replicas int32) *ClusterWrapper {
+	j.Spec.WorkerGroupSpecs[0].Replicas = &replicas
+	return j
+}
+
 func (j *ClusterWrapper) WithWorkerGroups(workers ...rayv1.WorkerGroupSpec) *ClusterWrapper {
 	j.Spec.WorkerGroupSpecs = workers
 	return j
diff --git a/pkg/webhooks/workload_webhook_test.go b/pkg/webhooks/workload_webhook_test.go
index 27a795ce9..b9cbf45ac 100644
--- a/pkg/webhooks/workload_webhook_test.go
+++ b/pkg/webhooks/workload_webhook_test.go
@@ -376,7 +376,7 @@ func TestValidateWorkloadUpdate(t *testing.T) {
 				State:              kueue.CheckStateReady,
 			}).Obj(),
 		},
-		"TopologyAssignment cannot be mutated": {
+		"TopologyAssignment can be mutated": {
 			enableTopologyAwareScheduling: true,
 			before: testingutil.MakeWorkload(testWorkloadName, testWorkloadNamespace).
 				PodSets(
@@ -420,60 +420,22 @@ func TestValidateWorkloadUpdate(t *testing.T) {
 						Obj(),
 				).
 				Obj(),
-			wantErr: field.ErrorList{
-				field.Invalid(field.NewPath("status", "admission"), nil, ""),
-			},
+			wantErr: nil,
 		},
-		"TopologyAssignment cannot be set without delayedTopologyRequest": {
+		"PodSets cannot be removed from admission": {
 			enableTopologyAwareScheduling: true,
 			before: testingutil.MakeWorkload(testWorkloadName, testWorkloadNamespace).
 				PodSets(
 					*testingutil.MakePodSet("ps1", 3).Obj(),
+					*testingutil.MakePodSet("ps2", 3).Obj(),
 				).
 				ReserveQuota(
 					testingutil.MakeAdmission("cluster-queue").
 						PodSets(kueue.PodSetAssignment{
 							Name: "ps1",
 						}).
-						Obj(),
-				).
-				Obj(),
-			after: testingutil.MakeWorkload(testWorkloadName, testWorkloadNamespace).
-				PodSets(
-					*testingutil.MakePodSet("ps1", 3).Obj(),
-				).
-				ReserveQuota(
-					testingutil.MakeAdmission("cluster-queue").
 						PodSets(kueue.PodSetAssignment{
-							Name: "ps1",
-							TopologyAssignment: &kueue.TopologyAssignment{
-								Levels: []string{"level"},
-								Domains: []kueue.TopologyDomainAssignment{
-									{
-										Values: []string{"abc"},
-										Count:  3,
-									},
-								},
-							},
-						}).
-						Obj(),
-				).
-				Obj(),
-			wantErr: field.ErrorList{
-				field.Invalid(field.NewPath("status", "admission"), nil, ""),
-			},
-		},
-		"TopologyAssignment can be set if delayedTopologyRequest is Pending": {
-			enableTopologyAwareScheduling: true,
-			before: testingutil.MakeWorkload(testWorkloadName, testWorkloadNamespace).
-				PodSets(
-					*testingutil.MakePodSet("ps1", 3).Obj(),
-				).
-				ReserveQuota(
-					testingutil.MakeAdmission("cluster-queue").
-						PodSets(kueue.PodSetAssignment{
-							Name:                   "ps1",
-							DelayedTopologyRequest: ptr.To(kueue.DelayedTopologyRequestStatePending),
+							Name: "ps2",
 						}).
 						Obj(),
 				).
@@ -481,20 +443,12 @@ func TestValidateWorkloadUpdate(t *testing.T) {
 			after: testingutil.MakeWorkload(testWorkloadName, testWorkloadNamespace).
 				PodSets(
 					*testingutil.MakePodSet("ps1", 3).Obj(),
+					*testingutil.MakePodSet("ps2", 3).Obj(),
 				).
 				ReserveQuota(
 					testingutil.MakeAdmission("cluster-queue").
 						PodSets(kueue.PodSetAssignment{
 							Name: "ps1",
-							TopologyAssignment: &kueue.TopologyAssignment{
-								Levels: []string{"level"},
-								Domains: []kueue.TopologyDomainAssignment{
-									{
-										Values: []string{"abc"},
-										Count:  3,
-									},
-								},
-							},
 						}).
 						Obj(),
 				).
@@ -503,49 +457,22 @@ func TestValidateWorkloadUpdate(t *testing.T) {
 				field.Invalid(field.NewPath("status", "admission"), nil, ""),
 			},
 		},
-		"TopologyAssignment cannot be set if delayedTopologyRequest is Ready": {
+		"PodSets cannot be added to admission": {
 			enableTopologyAwareScheduling: true,
 			before: testingutil.MakeWorkload(testWorkloadName, testWorkloadNamespace).
 				PodSets(
 					*testingutil.MakePodSet("ps1", 3).Obj(),
-				).
-				ReserveQuota(
-					testingutil.MakeAdmission("cluster-queue").
-						PodSets(kueue.PodSetAssignment{
-							Name:                   "ps1",
-							DelayedTopologyRequest: ptr.To(kueue.DelayedTopologyRequestStateReady),
-						}).
-						Obj(),
-				).
-				Obj(),
-			after: testingutil.MakeWorkload(testWorkloadName, testWorkloadNamespace).
-				PodSets(
-					*testingutil.MakePodSet("ps1", 3).Obj(),
+					*testingutil.MakePodSet("ps2", 3).Obj(),
 				).
 				ReserveQuota(
 					testingutil.MakeAdmission("cluster-queue").
 						PodSets(kueue.PodSetAssignment{
 							Name: "ps1",
-							TopologyAssignment: &kueue.TopologyAssignment{
-								Levels: []string{"level"},
-								Domains: []kueue.TopologyDomainAssignment{
-									{
-										Values: []string{"abc"},
-										Count:  3,
-									},
-								},
-							},
 						}).
 						Obj(),
 				).
 				Obj(),
-			wantErr: field.ErrorList{
-				field.Invalid(field.NewPath("status", "admission"), nil, ""),
-			},
-		},
-		"PodSets cannot be removed from admission": {
-			enableTopologyAwareScheduling: true,
-			before: testingutil.MakeWorkload(testWorkloadName, testWorkloadNamespace).
+			after: testingutil.MakeWorkload(testWorkloadName, testWorkloadNamespace).
 				PodSets(
 					*testingutil.MakePodSet("ps1", 3).Obj(),
 					*testingutil.MakePodSet("ps2", 3).Obj(),
@@ -561,19 +488,6 @@ func TestValidateWorkloadUpdate(t *testing.T) {
 						Obj(),
 				).
 				Obj(),
-			after: testingutil.MakeWorkload(testWorkloadName, testWorkloadNamespace).
-				PodSets(
-					*testingutil.MakePodSet("ps1", 3).Obj(),
-					*testingutil.MakePodSet("ps2", 3).Obj(),
-				).
-				ReserveQuota(
-					testingutil.MakeAdmission("cluster-queue").
-						PodSets(kueue.PodSetAssignment{
-							Name: "ps1",
-						}).
-						Obj(),
-				).
-				Obj(),
 			wantErr: field.ErrorList{
 				field.Invalid(field.NewPath("status", "admission"), nil, ""),
 			},
@@ -619,6 +533,7 @@ func TestValidateWorkloadUpdate(t *testing.T) {
 	for name, tc := range testCases {
 		t.Run(name, func(t *testing.T) {
 			features.SetFeatureGateDuringTest(t, features.ElasticJobsViaWorkloadSlices, tc.enableElasticJobsFeature)
+			features.SetFeatureGateDuringTest(t, features.TopologyAwareScheduling, tc.enableTopologyAwareScheduling)
 			errList := ValidateWorkloadUpdate(tc.after, tc.before, configapi.MultiKueueDispatcherModeAllAtOnce)
 			if diff := cmp.Diff(tc.wantErr, errList, cmpopts.IgnoreFields(field.Error{}, "Detail", "BadValue")); diff != "" {
 				t.Errorf("ValidateWorkloadUpdate() mismatch (-want +got):\n%s", diff)
diff --git a/pkg/workload/admissionchecks_test.go b/pkg/workload/admissionchecks_test.go
index 8e137b078..7a0699a26 100644
--- a/pkg/workload/admissionchecks_test.go
+++ b/pkg/workload/admissionchecks_test.go
@@ -29,6 +29,7 @@ import (
 
 	kueue "sigs.k8s.io/kueue/apis/kueue/v1beta1"
 	"sigs.k8s.io/kueue/pkg/features"
+	"sigs.k8s.io/kueue/pkg/util/admissioncheck"
 	utiltesting "sigs.k8s.io/kueue/pkg/util/testing"
 )
 
@@ -536,7 +537,7 @@ func TestSetCheckState(t *testing.T) {
 			if tc.state.LastTransitionTime.IsZero() {
 				opts = append(opts, cmpopts.IgnoreFields(kueue.AdmissionCheckState{}, "LastTransitionTime"), cmpopts.EquateApproxTime(time.Second))
 
-				if updatedCheck := FindAdmissionCheck(gotStates, tc.state.Name); updatedCheck == nil {
+				if updatedCheck := admissioncheck.FindAdmissionCheck(gotStates, tc.state.Name); updatedCheck == nil {
 					t.Error("Cannot find the updated check state")
 				} else {
 					if diff := cmp.Diff(metav1.NewTime(now), updatedCheck.LastTransitionTime, opts...); diff != "" {
diff --git a/pkg/workload/workload_test.go b/pkg/workload/workload_test.go
index 2a870c743..80a8e49e7 100644
--- a/pkg/workload/workload_test.go
+++ b/pkg/workload/workload_test.go
@@ -31,7 +31,6 @@ import (
 	"sigs.k8s.io/controller-runtime/pkg/client"
 
 	config "sigs.k8s.io/kueue/apis/config/v1beta1"
-	kueuealpha "sigs.k8s.io/kueue/apis/kueue/v1alpha1"
 	kueue "sigs.k8s.io/kueue/apis/kueue/v1beta1"
 	"sigs.k8s.io/kueue/pkg/features"
 	"sigs.k8s.io/kueue/pkg/resources"
@@ -1096,7 +1095,7 @@ func TestNeedsSecondPass(t *testing.T) {
 	}{
 		"admitted workload with NodeToReplace": {
 			wl: utiltesting.MakeWorkload("foo", "default").
-				Annotations(map[string]string{kueuealpha.NodeToReplaceAnnotation: "x0"}).
+				NodesToReplace("x0").
 				Queue("tas-main").
 				PodSets(*utiltesting.MakePodSet("one", 1).
 					PreferredTopologyRequest(corev1.LabelHostname).
@@ -1153,7 +1152,7 @@ func TestNeedsSecondPass(t *testing.T) {
 		},
 		"admitted workload with NodeToReplace, but no node in the assignment": {
 			wl: utiltesting.MakeWorkload("foo", "default").
-				Annotations(map[string]string{kueuealpha.NodeToReplaceAnnotation: "x0"}).
+				NodesToReplace("x0").
 				Queue("tas-main").
 				PodSets(*utiltesting.MakePodSet("one", 1).
 					PreferredTopologyRequest(corev1.LabelHostname).
@@ -1182,7 +1181,7 @@ func TestNeedsSecondPass(t *testing.T) {
 		},
 		"finished workload with NodeToReplace": {
 			wl: utiltesting.MakeWorkload("foo", "default").
-				Annotations(map[string]string{kueuealpha.NodeToReplaceAnnotation: "x0"}).
+				NodesToReplace("x0").
 				Queue("tas-main").
 				PodSets(*utiltesting.MakePodSet("one", 1).
 					PreferredTopologyRequest(corev1.LabelHostname).
@@ -1212,7 +1211,7 @@ func TestNeedsSecondPass(t *testing.T) {
 		},
 		"evicted workload with NodeToReplace": {
 			wl: utiltesting.MakeWorkload("foo", "default").
-				Annotations(map[string]string{kueuealpha.NodeToReplaceAnnotation: "x0"}).
+				NodesToReplace("x0").
 				Queue("tas-main").
 				PodSets(*utiltesting.MakePodSet("one", 1).
 					PreferredTopologyRequest(corev1.LabelHostname).
diff --git a/test/e2e/multikueue/e2e_test.go b/test/e2e/multikueue/e2e_test.go
index 27ab2121a..b3e3f771a 100644
--- a/test/e2e/multikueue/e2e_test.go
+++ b/test/e2e/multikueue/e2e_test.go
@@ -50,6 +50,7 @@ import (
 	podconstants "sigs.k8s.io/kueue/pkg/controller/jobs/pod/constants"
 	workloadraycluster "sigs.k8s.io/kueue/pkg/controller/jobs/raycluster"
 	workloadrayjob "sigs.k8s.io/kueue/pkg/controller/jobs/rayjob"
+	"sigs.k8s.io/kueue/pkg/util/admissioncheck"
 	utilpod "sigs.k8s.io/kueue/pkg/util/pod"
 	utiltesting "sigs.k8s.io/kueue/pkg/util/testing"
 	testingaw "sigs.k8s.io/kueue/pkg/util/testingjobs/appwrapper"
@@ -61,7 +62,6 @@ import (
 	testingpytorchjob "sigs.k8s.io/kueue/pkg/util/testingjobs/pytorchjob"
 	testingraycluster "sigs.k8s.io/kueue/pkg/util/testingjobs/raycluster"
 	testingrayjob "sigs.k8s.io/kueue/pkg/util/testingjobs/rayjob"
-	"sigs.k8s.io/kueue/pkg/workload"
 	"sigs.k8s.io/kueue/test/util"
 )
 
@@ -214,7 +214,7 @@ var _ = ginkgo.Describe("MultiKueue", func() {
 			ginkgo.By("Waiting to be admitted in worker2", 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{
+					g.Expect(admissioncheck.FindAdmissionCheck(createdLeaderWorkload.Status.AdmissionChecks, kueue.AdmissionCheckReference(multiKueueAc.Name))).To(gomega.BeComparableTo(&kueue.AdmissionCheckState{
 						Name:    kueue.AdmissionCheckReference(multiKueueAc.Name),
 						State:   kueue.CheckStatePending,
 						Message: `The workload got reservation on "worker2"`,
@@ -410,7 +410,7 @@ var _ = ginkgo.Describe("MultiKueue", func() {
 			ginkgo.By("Waiting to be admitted in worker2", 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{
+					g.Expect(admissioncheck.FindAdmissionCheck(createdLeaderWorkload.Status.AdmissionChecks, kueue.AdmissionCheckReference(multiKueueAc.Name))).To(gomega.BeComparableTo(&kueue.AdmissionCheckState{
 						Name:    kueue.AdmissionCheckReference(multiKueueAc.Name),
 						State:   kueue.CheckStatePending,
 						Message: `The workload got reservation on "worker2"`,
@@ -463,7 +463,7 @@ var _ = ginkgo.Describe("MultiKueue", func() {
 			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{
+					g.Expect(admissioncheck.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"`,
@@ -1028,7 +1028,7 @@ func waitForJobAdmitted(wlLookupKey types.NamespacedName, acName, workerName str
 			Reason:  "Admitted",
 			Message: "The workload is admitted",
 		}, util.IgnoreConditionTimestampsAndObservedGeneration))
-		g.Expect(workload.FindAdmissionCheck(createdWorkload.Status.AdmissionChecks, kueue.AdmissionCheckReference(acName))).To(gomega.BeComparableTo(&kueue.AdmissionCheckState{
+		g.Expect(admissioncheck.FindAdmissionCheck(createdWorkload.Status.AdmissionChecks, kueue.AdmissionCheckReference(acName))).To(gomega.BeComparableTo(&kueue.AdmissionCheckState{
 			Name:    kueue.AdmissionCheckReference(acName),
 			State:   kueue.CheckStateReady,
 			Message: fmt.Sprintf(`The workload got reservation on "%s"`, workerName),
@@ -1060,7 +1060,7 @@ func ensurePodWorkloadsRunning(deployment *appsv1.Deployment, managerNs corev1.N
 		gomega.Expect(k8sManagerClient.Get(ctx, wlLookupKey, createdLeaderWorkload)).To(gomega.Succeed())
 
 		// By checking the assigned cluster we can discern which client to use
-		admissionCheckMessage := workload.FindAdmissionCheck(createdLeaderWorkload.Status.AdmissionChecks, kueue.AdmissionCheckReference(multiKueueAc.Name)).Message
+		admissionCheckMessage := admissioncheck.FindAdmissionCheck(createdLeaderWorkload.Status.AdmissionChecks, kueue.AdmissionCheckReference(multiKueueAc.Name)).Message
 		workerCluster := kubernetesClients[GetMultiKueueClusterNameFromAdmissionCheckMessage(admissionCheckMessage)]
 
 		// Worker pods should be in "Running" phase
diff --git a/test/integration/multikueue/dispatcher_test.go b/test/integration/multikueue/dispatcher_test.go
index 97ca671ef..acc0b6f5d 100644
--- a/test/integration/multikueue/dispatcher_test.go
+++ b/test/integration/multikueue/dispatcher_test.go
@@ -35,6 +35,7 @@ import (
 	"sigs.k8s.io/kueue/pkg/constants"
 	workloadjob "sigs.k8s.io/kueue/pkg/controller/jobs/job"
 	"sigs.k8s.io/kueue/pkg/features"
+	"sigs.k8s.io/kueue/pkg/util/admissioncheck"
 	utiltesting "sigs.k8s.io/kueue/pkg/util/testing"
 	testingjob "sigs.k8s.io/kueue/pkg/util/testingjobs/job"
 	"sigs.k8s.io/kueue/pkg/workload"
@@ -679,7 +680,7 @@ var _ = ginkgo.Describe("MultiKueueDispatcherAllAtOnce", ginkgo.Ordered, ginkgo.
 						Message: "The workload is admitted",
 					}, util.IgnoreConditionTimestampsAndObservedGeneration),
 				))
-				state := workload.FindAdmissionCheck(createdWorkload.Status.AdmissionChecks, kueue.AdmissionCheckReference(multiKueueAC.Name))
+				state := admissioncheck.FindAdmissionCheck(createdWorkload.Status.AdmissionChecks, kueue.AdmissionCheckReference(multiKueueAC.Name))
 				g.Expect(state).NotTo(gomega.BeNil())
 				g.Expect(state.State).To(gomega.Equal(kueue.CheckStateReady))
 			}, util.Timeout, util.Interval).Should(gomega.Succeed())
@@ -727,7 +728,7 @@ var _ = ginkgo.Describe("MultiKueueDispatcherAllAtOnce", ginkgo.Ordered, ginkgo.
 						Message: "The workload is admitted",
 					}, util.IgnoreConditionTimestampsAndObservedGeneration),
 				))
-				state := workload.FindAdmissionCheck(createdWorkload.Status.AdmissionChecks, kueue.AdmissionCheckReference(multiKueueAC.Name))
+				state := admissioncheck.FindAdmissionCheck(createdWorkload.Status.AdmissionChecks, kueue.AdmissionCheckReference(multiKueueAC.Name))
 				g.Expect(state).NotTo(gomega.BeNil())
 				g.Expect(state.State).To(gomega.Equal(kueue.CheckStateReady))
 			}, util.Timeout, util.Interval).Should(gomega.Succeed())
diff --git a/test/integration/multikueue/enabled_integration_test.go b/test/integration/multikueue/enabled_integration_test.go
index 369490ed5..ddc148716 100644
--- a/test/integration/multikueue/enabled_integration_test.go
+++ b/test/integration/multikueue/enabled_integration_test.go
@@ -39,10 +39,10 @@ import (
 	kueue "sigs.k8s.io/kueue/apis/kueue/v1beta1"
 	workloadjob "sigs.k8s.io/kueue/pkg/controller/jobs/job"
 	workloadmpijob "sigs.k8s.io/kueue/pkg/controller/jobs/mpijob"
+	"sigs.k8s.io/kueue/pkg/util/admissioncheck"
 	utiltesting "sigs.k8s.io/kueue/pkg/util/testing"
 	testingjob "sigs.k8s.io/kueue/pkg/util/testingjobs/job"
 	testingmpijob "sigs.k8s.io/kueue/pkg/util/testingjobs/mpijob"
-	"sigs.k8s.io/kueue/pkg/workload"
 	"sigs.k8s.io/kueue/test/util"
 )
 
@@ -172,7 +172,7 @@ var _ = ginkgo.Describe("MultiKueue when not all integrations are enabled", gink
 
 			gomega.Eventually(func(g gomega.Gomega) {
 				g.Expect(managerTestCluster.client.Get(managerTestCluster.ctx, wlLookupKey, createdWorkload)).To(gomega.Succeed())
-				acs := workload.FindAdmissionCheck(createdWorkload.Status.AdmissionChecks, kueue.AdmissionCheckReference(multiKueueAC.Name))
+				acs := admissioncheck.FindAdmissionCheck(createdWorkload.Status.AdmissionChecks, kueue.AdmissionCheckReference(multiKueueAC.Name))
 				g.Expect(acs).NotTo(gomega.BeNil())
 				g.Expect(acs.State).To(gomega.Equal(kueue.CheckStatePending))
 				g.Expect(acs.Message).To(gomega.Equal(`The workload got reservation on "worker1"`))
@@ -271,7 +271,7 @@ var _ = ginkgo.Describe("MultiKueue when not all integrations are enabled", gink
 		ginkgo.By("checking the workload creation was rejected in the management cluster", func() {
 			managerWl := &kueue.Workload{}
 			gomega.Expect(managerTestCluster.client.Get(managerTestCluster.ctx, wlLookupKey, managerWl)).To(gomega.Succeed())
-			acs := workload.FindAdmissionCheck(managerWl.Status.AdmissionChecks, kueue.AdmissionCheckReference(multiKueueAC.Name))
+			acs := admissioncheck.FindAdmissionCheck(managerWl.Status.AdmissionChecks, kueue.AdmissionCheckReference(multiKueueAC.Name))
 			gomega.Expect(acs).To(gomega.BeComparableTo(&kueue.AdmissionCheckState{
 				Name:    kueue.AdmissionCheckReference(multiKueueAC.Name),
 				State:   kueue.CheckStateRejected,
diff --git a/test/integration/multikueue/jobs_test.go b/test/integration/multikueue/jobs_test.go
index 0a7a26520..e34a111dd 100644
--- a/test/integration/multikueue/jobs_test.go
+++ b/test/integration/multikueue/jobs_test.go
@@ -53,6 +53,7 @@ import (
 	workloadraycluster "sigs.k8s.io/kueue/pkg/controller/jobs/raycluster"
 	workloadrayjob "sigs.k8s.io/kueue/pkg/controller/jobs/rayjob"
 	"sigs.k8s.io/kueue/pkg/features"
+	"sigs.k8s.io/kueue/pkg/util/admissioncheck"
 	utiltesting "sigs.k8s.io/kueue/pkg/util/testing"
 	testingaw "sigs.k8s.io/kueue/pkg/util/testingjobs/appwrapper"
 	testingjob "sigs.k8s.io/kueue/pkg/util/testingjobs/job"
@@ -65,7 +66,6 @@ import (
 	testingrayjob "sigs.k8s.io/kueue/pkg/util/testingjobs/rayjob"
 	testingtfjob "sigs.k8s.io/kueue/pkg/util/testingjobs/tfjob"
 	testingxgboostjob "sigs.k8s.io/kueue/pkg/util/testingjobs/xgboostjob"
-	"sigs.k8s.io/kueue/pkg/workload"
 	"sigs.k8s.io/kueue/test/integration/framework"
 	"sigs.k8s.io/kueue/test/util"
 )
@@ -243,7 +243,7 @@ var _ = ginkgo.Describe("MultiKueue", ginkgo.Ordered, ginkgo.ContinueOnFailure,
 
 			gomega.Eventually(func(g gomega.Gomega) {
 				g.Expect(managerTestCluster.client.Get(managerTestCluster.ctx, wlLookupKey, createdWorkload)).To(gomega.Succeed())
-				acs := workload.FindAdmissionCheck(createdWorkload.Status.AdmissionChecks, kueue.AdmissionCheckReference(multiKueueAC.Name))
+				acs := admissioncheck.FindAdmissionCheck(createdWorkload.Status.AdmissionChecks, kueue.AdmissionCheckReference(multiKueueAC.Name))
 				g.Expect(acs).NotTo(gomega.BeNil())
 				g.Expect(acs.State).To(gomega.Equal(kueue.CheckStatePending))
 				g.Expect(acs.Message).To(gomega.Equal(`The workload got reservation on "worker1"`))
@@ -347,7 +347,7 @@ var _ = ginkgo.Describe("MultiKueue", ginkgo.Ordered, ginkgo.ContinueOnFailure,
 
 			gomega.Eventually(func(g gomega.Gomega) {
 				g.Expect(managerTestCluster.client.Get(managerTestCluster.ctx, wlLookupKey, createdWorkload)).To(gomega.Succeed())
-				acs := workload.FindAdmissionCheck(createdWorkload.Status.AdmissionChecks, kueue.AdmissionCheckReference(multiKueueAC.Name))
+				acs := admissioncheck.FindAdmissionCheck(createdWorkload.Status.AdmissionChecks, kueue.AdmissionCheckReference(multiKueueAC.Name))
 				g.Expect(acs).NotTo(gomega.BeNil())
 				g.Expect(acs.State).To(gomega.Equal(kueue.CheckStateReady))
 				g.Expect(acs.Message).To(gomega.Equal(`The workload got reservation on "worker1"`))
@@ -1062,7 +1062,7 @@ var _ = ginkgo.Describe("MultiKueue", ginkgo.Ordered, ginkgo.ContinueOnFailure,
 
 			gomega.Eventually(func(g gomega.Gomega) {
 				g.Expect(managerTestCluster.client.Get(managerTestCluster.ctx, wlLookupKey, createdWorkload)).To(gomega.Succeed())
-				acs := workload.FindAdmissionCheck(createdWorkload.Status.AdmissionChecks, kueue.AdmissionCheckReference(multiKueueAC.Name))
+				acs := admissioncheck.FindAdmissionCheck(createdWorkload.Status.AdmissionChecks, kueue.AdmissionCheckReference(multiKueueAC.Name))
 				g.Expect(acs).NotTo(gomega.BeNil())
 				g.Expect(acs.State).To(gomega.Equal(kueue.CheckStatePending))
 				g.Expect(acs.Message).To(gomega.Equal(`The workload got reservation on "worker1"`))
@@ -1179,7 +1179,7 @@ var _ = ginkgo.Describe("MultiKueue", ginkgo.Ordered, ginkgo.ContinueOnFailure,
 
 			gomega.Eventually(func(g gomega.Gomega) {
 				g.Expect(managerTestCluster.client.Get(managerTestCluster.ctx, wlLookupKey, createdWorkload)).To(gomega.Succeed())
-				acs := workload.FindAdmissionCheck(createdWorkload.Status.AdmissionChecks, kueue.AdmissionCheckReference(multiKueueAC.Name))
+				acs := admissioncheck.FindAdmissionCheck(createdWorkload.Status.AdmissionChecks, kueue.AdmissionCheckReference(multiKueueAC.Name))
 				g.Expect(acs).NotTo(gomega.BeNil())
 				g.Expect(acs.State).To(gomega.Equal(kueue.CheckStatePending))
 				g.Expect(acs.Message).To(gomega.Equal(`The workload got reservation on "worker1"`))
@@ -1463,7 +1463,7 @@ var _ = ginkgo.Describe("MultiKueue", ginkgo.Ordered, ginkgo.ContinueOnFailure,
 			gomega.Eventually(func(g gomega.Gomega) {
 				createdWorkload := &kueue.Workload{}
 				g.Expect(managerTestCluster.client.Get(managerTestCluster.ctx, wlLookupKey, createdWorkload)).To(gomega.Succeed())
-				acs := workload.FindAdmissionCheck(createdWorkload.Status.AdmissionChecks, kueue.AdmissionCheckReference(multiKueueAC.Name))
+				acs := admissioncheck.FindAdmissionCheck(createdWorkload.Status.AdmissionChecks, kueue.AdmissionCheckReference(multiKueueAC.Name))
 				g.Expect(acs).To(gomega.BeComparableTo(&kueue.AdmissionCheckState{
 					Name:  kueue.AdmissionCheckReference(multiKueueAC.Name),
 					State: kueue.CheckStatePending,
@@ -1625,7 +1625,7 @@ func admitWorkloadAndCheckWorkerCopies(acName string, wlLookupKey types.Namespac
 
 		gomega.Eventually(func(g gomega.Gomega) {
 			g.Expect(managerTestCluster.client.Get(managerTestCluster.ctx, wlLookupKey, createdWorkload)).To(gomega.Succeed())
-			acs := workload.FindAdmissionCheck(createdWorkload.Status.AdmissionChecks, kueue.AdmissionCheckReference(acName))
+			acs := admissioncheck.FindAdmissionCheck(createdWorkload.Status.AdmissionChecks, kueue.AdmissionCheckReference(acName))
 			g.Expect(acs).NotTo(gomega.BeNil())
 			g.Expect(acs.State).To(gomega.Equal(kueue.CheckStateReady))
 			g.Expect(acs.Message).To(gomega.Equal(`The workload got reservation on "worker2"`))
diff --git a/test/integration/multikueue/no_gc_test.go b/test/integration/multikueue/no_gc_test.go
index 1df02ffe5..08695ab50 100644
--- a/test/integration/multikueue/no_gc_test.go
+++ b/test/integration/multikueue/no_gc_test.go
@@ -33,6 +33,7 @@ import (
 	kueue "sigs.k8s.io/kueue/apis/kueue/v1beta1"
 	workloadjob "sigs.k8s.io/kueue/pkg/controller/jobs/job"
 	"sigs.k8s.io/kueue/pkg/features"
+	"sigs.k8s.io/kueue/pkg/util/admissioncheck"
 	utiltesting "sigs.k8s.io/kueue/pkg/util/testing"
 	testingjob "sigs.k8s.io/kueue/pkg/util/testingjobs/job"
 	"sigs.k8s.io/kueue/pkg/workload"
@@ -254,7 +255,7 @@ var _ = ginkgo.Describe("MultiKueue no GC", ginkgo.Ordered, ginkgo.ContinueOnFai
 		ginkgo.By("setting workload reservation in worker1, AC state is updated in manager and worker2 wl is removed", func() {
 			gomega.Eventually(func(g gomega.Gomega) {
 				g.Expect(managerTestCluster.client.Get(managerTestCluster.ctx, wlLookupKey, createdWorkload)).To(gomega.Succeed())
-				acs := workload.FindAdmissionCheck(createdWorkload.Status.AdmissionChecks, kueue.AdmissionCheckReference(multiKueueAC.Name))
+				acs := admissioncheck.FindAdmissionCheck(createdWorkload.Status.AdmissionChecks, kueue.AdmissionCheckReference(multiKueueAC.Name))
 				g.Expect(acs).NotTo(gomega.BeNil())
 				g.Expect(acs.State).To(gomega.Equal(kueue.CheckStatePending))
 			}, util.Timeout, util.Interval).Should(gomega.Succeed())
diff --git a/test/integration/singlecluster/controller/admissionchecks/provisioning/provisioning_test.go b/test/integration/singlecluster/controller/admissionchecks/provisioning/provisioning_test.go
index ee9b3aa73..c4a33a490 100644
--- a/test/integration/singlecluster/controller/admissionchecks/provisioning/provisioning_test.go
+++ b/test/integration/singlecluster/controller/admissionchecks/provisioning/provisioning_test.go
@@ -33,6 +33,7 @@ import (
 	kueue "sigs.k8s.io/kueue/apis/kueue/v1beta1"
 	"sigs.k8s.io/kueue/pkg/constants"
 	"sigs.k8s.io/kueue/pkg/controller/admissionchecks/provisioning"
+	"sigs.k8s.io/kueue/pkg/util/admissioncheck"
 	"sigs.k8s.io/kueue/pkg/util/testing"
 	"sigs.k8s.io/kueue/pkg/workload"
 	"sigs.k8s.io/kueue/test/integration/framework"
@@ -270,7 +271,7 @@ var _ = ginkgo.Describe("Provisioning", ginkgo.Ordered, ginkgo.ContinueOnFailure
 			ginkgo.By("Checking that the ETA is propagated to workload", func() {
 				gomega.Eventually(func(g gomega.Gomega) {
 					g.Expect(k8sClient.Get(ctx, wlKey, &updatedWl)).To(gomega.Succeed())
-					state := workload.FindAdmissionCheck(updatedWl.Status.AdmissionChecks, kueue.AdmissionCheckReference(ac.Name))
+					state := admissioncheck.FindAdmissionCheck(updatedWl.Status.AdmissionChecks, kueue.AdmissionCheckReference(ac.Name))
 					g.Expect(state).NotTo(gomega.BeNil())
 					g.Expect(state.State).To(gomega.Equal(kueue.CheckStatePending))
 					g.Expect(state.Message).To(gomega.Equal("Not provisioned, ETA: 2024-02-22T10:36:40Z."))
@@ -292,7 +293,7 @@ var _ = ginkgo.Describe("Provisioning", ginkgo.Ordered, ginkgo.ContinueOnFailure
 			ginkgo.By("Checking the admission check", func() {
 				gomega.Eventually(func(g gomega.Gomega) {
 					g.Expect(k8sClient.Get(ctx, wlKey, &updatedWl)).To(gomega.Succeed())
-					state := workload.FindAdmissionCheck(updatedWl.Status.AdmissionChecks, kueue.AdmissionCheckReference(ac.Name))
+					state := admissioncheck.FindAdmissionCheck(updatedWl.Status.AdmissionChecks, kueue.AdmissionCheckReference(ac.Name))
 					g.Expect(state).NotTo(gomega.BeNil())
 					g.Expect(state.State).To(gomega.Equal(kueue.CheckStateReady))
 					g.Expect(state.PodSetUpdates).To(gomega.BeComparableTo([]kueue.PodSetUpdate{
@@ -697,7 +698,7 @@ var _ = ginkgo.Describe("Provisioning", ginkgo.Ordered, ginkgo.ContinueOnFailure
 			ginkgo.By("Checking the admission check state indicates an inactive check", func() {
 				gomega.Eventually(func(g gomega.Gomega) {
 					g.Expect(k8sClient.Get(ctx, wlKey, &updatedWl)).To(gomega.Succeed())
-					state := workload.FindAdmissionCheck(updatedWl.Status.AdmissionChecks, kueue.AdmissionCheckReference(ac.Name))
+					state := admissioncheck.FindAdmissionCheck(updatedWl.Status.AdmissionChecks, kueue.AdmissionCheckReference(ac.Name))
 					g.Expect(state).NotTo(gomega.BeNil())
 					g.Expect(state.Message).To(gomega.Equal(provisioning.CheckInactiveMessage))
 				}, util.Timeout, util.Interval).Should(gomega.Succeed())
@@ -733,7 +734,7 @@ var _ = ginkgo.Describe("Provisioning", ginkgo.Ordered, ginkgo.ContinueOnFailure
 			ginkgo.By("Checking the admission check is ready", func() {
 				gomega.Eventually(func(g gomega.Gomega) {
 					g.Expect(k8sClient.Get(ctx, wlKey, &updatedWl)).To(gomega.Succeed())
-					state := workload.FindAdmissionCheck(updatedWl.Status.AdmissionChecks, kueue.AdmissionCheckReference(ac.Name))
+					state := admissioncheck.FindAdmissionCheck(updatedWl.Status.AdmissionChecks, kueue.AdmissionCheckReference(ac.Name))
 					g.Expect(state).NotTo(gomega.BeNil())
 					g.Expect(state.State).To(gomega.Equal(kueue.CheckStateReady))
 					g.Expect(state.PodSetUpdates).To(gomega.BeComparableTo([]kueue.PodSetUpdate{
@@ -777,7 +778,7 @@ var _ = ginkgo.Describe("Provisioning", ginkgo.Ordered, ginkgo.ContinueOnFailure
 			ginkgo.By("Checking the admission check remains ready", func() {
 				gomega.Eventually(func(g gomega.Gomega) {
 					g.Expect(k8sClient.Get(ctx, wlKey, &updatedWl)).To(gomega.Succeed())
-					state := workload.FindAdmissionCheck(updatedWl.Status.AdmissionChecks, kueue.AdmissionCheckReference(ac.Name))
+					state := admissioncheck.FindAdmissionCheck(updatedWl.Status.AdmissionChecks, kueue.AdmissionCheckReference(ac.Name))
 					g.Expect(state).NotTo(gomega.BeNil())
 					g.Expect(state.State).To(gomega.Equal(kueue.CheckStateReady))
 				}, util.Timeout, util.Interval).Should(gomega.Succeed())
@@ -901,7 +902,7 @@ var _ = ginkgo.Describe("Provisioning", ginkgo.Ordered, ginkgo.ContinueOnFailure
 			ginkgo.By("Checking the AdmissionChecks are reset to Pending and remain this way", func() {
 				gomega.Consistently(func(g gomega.Gomega) {
 					g.Expect(k8sClient.Get(ctx, wlKey, &updatedWl)).To(gomega.Succeed())
-					check := workload.FindAdmissionCheck(updatedWl.Status.AdmissionChecks, kueue.AdmissionCheckReference(ac.Name))
+					check := admissioncheck.FindAdmissionCheck(updatedWl.Status.AdmissionChecks, kueue.AdmissionCheckReference(ac.Name))
 					g.Expect(check).NotTo(gomega.BeNil())
 					g.Expect(check.State).To(gomega.Equal(kueue.CheckStatePending), fmt.Sprintf("status: %v", updatedWl.Status))
 				}, util.ConsistentDuration, util.ShortInterval).Should(gomega.Succeed())
@@ -945,7 +946,7 @@ var _ = ginkgo.Describe("Provisioning", ginkgo.Ordered, ginkgo.ContinueOnFailure
 					g.Expect(k8sClient.Get(ctx, wlKey, &updatedWl)).To(gomega.Succeed())
 					_, evicted := workload.IsEvictedByAdmissionCheck(&updatedWl)
 					g.Expect(evicted).To(gomega.BeTrue())
-					check := workload.FindAdmissionCheck(updatedWl.Status.AdmissionChecks, kueue.AdmissionCheckReference(ac.Name))
+					check := admissioncheck.FindAdmissionCheck(updatedWl.Status.AdmissionChecks, kueue.AdmissionCheckReference(ac.Name))
 					g.Expect(check).NotTo(gomega.BeNil())
 					g.Expect(check.State).To(gomega.Equal(kueue.CheckStatePending))
 				}, util.Timeout, util.Interval).Should(gomega.Succeed())
@@ -1004,7 +1005,7 @@ var _ = ginkgo.Describe("Provisioning", ginkgo.Ordered, ginkgo.ContinueOnFailure
 			ginkgo.By("Checking the admission check is ready", func() {
 				gomega.Eventually(func(g gomega.Gomega) {
 					g.Expect(k8sClient.Get(ctx, wlKey, &updatedWl)).To(gomega.Succeed())
-					state := workload.FindAdmissionCheck(updatedWl.Status.AdmissionChecks, kueue.AdmissionCheckReference(ac.Name))
+					state := admissioncheck.FindAdmissionCheck(updatedWl.Status.AdmissionChecks, kueue.AdmissionCheckReference(ac.Name))
 					g.Expect(state).NotTo(gomega.BeNil())
 					g.Expect(state.State).To(gomega.Equal(kueue.CheckStateReady))
 				}, util.Timeout, util.Interval).Should(gomega.Succeed())
@@ -1048,7 +1049,7 @@ var _ = ginkgo.Describe("Provisioning", ginkgo.Ordered, ginkgo.ContinueOnFailure
 					g.Expect(k8sClient.Get(ctx, wlKey, &updatedWl)).To(gomega.Succeed())
 					_, evicted := workload.IsEvictedByAdmissionCheck(&updatedWl)
 					g.Expect(evicted).To(gomega.BeTrue())
-					check := workload.FindAdmissionCheck(updatedWl.Status.AdmissionChecks, kueue.AdmissionCheckReference(ac.Name))
+					check := admissioncheck.FindAdmissionCheck(updatedWl.Status.AdmissionChecks, kueue.AdmissionCheckReference(ac.Name))
 					g.Expect(check).NotTo(gomega.BeNil())
 					g.Expect(check.State).To(gomega.Equal(kueue.CheckStatePending))
 				}, util.Timeout, util.Interval).Should(gomega.Succeed())
@@ -1172,7 +1173,7 @@ var _ = ginkgo.Describe("Provisioning", ginkgo.Ordered, ginkgo.ContinueOnFailure
 					g.Expect(k8sClient.Get(ctx, wlKey, &updatedWl)).To(gomega.Succeed())
 					_, evicted := workload.IsEvictedByAdmissionCheck(&updatedWl)
 					g.Expect(evicted).To(gomega.BeTrue())
-					check := workload.FindAdmissionCheck(updatedWl.Status.AdmissionChecks, kueue.AdmissionCheckReference(ac.Name))
+					check := admissioncheck.FindAdmissionCheck(updatedWl.Status.AdmissionChecks, kueue.AdmissionCheckReference(ac.Name))
 					g.Expect(check).NotTo(gomega.BeNil())
 					g.Expect(check.State).To(gomega.Equal(kueue.CheckStatePending))
 				}, util.Timeout, util.Interval).Should(gomega.Succeed())
@@ -1231,7 +1232,7 @@ var _ = ginkgo.Describe("Provisioning", ginkgo.Ordered, ginkgo.ContinueOnFailure
 			ginkgo.By("Checking the admission check is ready", func() {
 				gomega.Eventually(func(g gomega.Gomega) {
 					g.Expect(k8sClient.Get(ctx, wlKey, &updatedWl)).To(gomega.Succeed())
-					state := workload.FindAdmissionCheck(updatedWl.Status.AdmissionChecks, kueue.AdmissionCheckReference(ac.Name))
+					state := admissioncheck.FindAdmissionCheck(updatedWl.Status.AdmissionChecks, kueue.AdmissionCheckReference(ac.Name))
 					g.Expect(state).NotTo(gomega.BeNil())
 					g.Expect(state.State).To(gomega.Equal(kueue.CheckStateReady))
 				}, util.Timeout, util.Interval).Should(gomega.Succeed())
@@ -1342,7 +1343,7 @@ var _ = ginkgo.Describe("Provisioning", ginkgo.Ordered, ginkgo.ContinueOnFailure
 					g.Expect(k8sClient.Get(ctx, wlKey, &updatedWl)).To(gomega.Succeed())
 					_, evicted := workload.IsEvictedByAdmissionCheck(&updatedWl)
 					g.Expect(evicted).To(gomega.BeTrue())
-					check := workload.FindAdmissionCheck(updatedWl.Status.AdmissionChecks, kueue.AdmissionCheckReference(ac.Name))
+					check := admissioncheck.FindAdmissionCheck(updatedWl.Status.AdmissionChecks, kueue.AdmissionCheckReference(ac.Name))
 					g.Expect(check).NotTo(gomega.BeNil())
 					g.Expect(check.State).To(gomega.Equal(kueue.CheckStatePending))
 				}, util.Timeout, util.Interval).Should(gomega.Succeed())
@@ -1391,7 +1392,7 @@ var _ = ginkgo.Describe("Provisioning", ginkgo.Ordered, ginkgo.ContinueOnFailure
 					g.Expect(k8sClient.Get(ctx, wlKey, &updatedWl)).To(gomega.Succeed())
 					_, evicted := workload.IsEvictedByAdmissionCheck(&updatedWl)
 					g.Expect(evicted).To(gomega.BeTrue())
-					check := workload.FindAdmissionCheck(updatedWl.Status.AdmissionChecks, kueue.AdmissionCheckReference(ac.Name))
+					check := admissioncheck.FindAdmissionCheck(updatedWl.Status.AdmissionChecks, kueue.AdmissionCheckReference(ac.Name))
 					g.Expect(check).NotTo(gomega.BeNil())
 					g.Expect(check.State).To(gomega.Equal(kueue.CheckStatePending))
 				}, util.Timeout, util.Interval).Should(gomega.Succeed())
diff --git a/test/integration/singlecluster/controller/core/clusterqueue_controller_test.go b/test/integration/singlecluster/controller/core/clusterqueue_controller_test.go
index 8556a3156..06bcce326 100644
--- a/test/integration/singlecluster/controller/core/clusterqueue_controller_test.go
+++ b/test/integration/singlecluster/controller/core/clusterqueue_controller_test.go
@@ -26,7 +26,6 @@ import (
 	"k8s.io/utils/ptr"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 
-	config "sigs.k8s.io/kueue/apis/config/v1beta1"
 	kueue "sigs.k8s.io/kueue/apis/kueue/v1beta1"
 	"sigs.k8s.io/kueue/pkg/features"
 	"sigs.k8s.io/kueue/pkg/metrics"
@@ -47,7 +46,6 @@ const (
 	flavorCPUArchB = "arch-b"
 )
 
-var ignoreLastChangeTime = cmpopts.IgnoreFields(kueue.ClusterQueuePendingWorkloadsStatus{}, "LastChangeTime")
 var ignorePendingWorkloadsStatus = cmpopts.IgnoreFields(kueue.ClusterQueueStatus{}, "PendingWorkloadsStatus")
 
 var _ = ginkgo.Describe("ClusterQueue controller", ginkgo.Ordered, ginkgo.ContinueOnFailure, func() {
@@ -934,180 +932,3 @@ var _ = ginkgo.Describe("ClusterQueue controller", ginkgo.Ordered, ginkgo.Contin
 		})
 	})
 })
-
-var _ = ginkgo.Describe("ClusterQueue controller with queue visibility is enabled", ginkgo.Ordered, ginkgo.ContinueOnFailure, func() {
-	var ns *corev1.Namespace
-
-	ginkgo.BeforeAll(func() {
-		ginkgo.By("Enabling queue visibility feature", func() {
-			gomega.Expect(features.SetEnable(features.QueueVisibility, true)).To(gomega.Succeed())
-		})
-		fwk.StartManager(
-			ctx, cfg,
-			managerAndControllerSetup(
-				&config.Configuration{
-					QueueVisibility: &config.QueueVisibility{
-						UpdateIntervalSeconds: 2,
-						ClusterQueues: &config.ClusterQueueVisibility{
-							MaxCount: 3,
-						},
-					},
-				},
-			),
-		)
-	})
-
-	ginkgo.AfterAll(func() {
-		fwk.StopManager(ctx)
-	})
-
-	ginkgo.BeforeEach(func() {
-		ns = util.CreateNamespaceFromPrefixWithLog(ctx, k8sClient, "core-clusterqueue-")
-	})
-
-	ginkgo.AfterEach(func() {
-		gomega.Expect(util.DeleteNamespace(ctx, k8sClient, ns)).To(gomega.Succeed())
-	})
-
-	ginkgo.When("Reconciling clusterQueue pending workload status", func() {
-		var (
-			clusterQueue   *kueue.ClusterQueue
-			localQueue     *kueue.LocalQueue
-			onDemandFlavor *kueue.ResourceFlavor
-		)
-
-		ginkgo.BeforeEach(func() {
-			onDemandFlavor = testing.MakeResourceFlavor(flavorOnDemand).Obj()
-			util.MustCreate(ctx, k8sClient, onDemandFlavor)
-			clusterQueue = testing.MakeClusterQueue("cluster-queue").
-				ResourceGroup(
-					*testing.MakeFlavorQuotas(flavorOnDemand).
-						Resource(corev1.ResourceCPU, "5", "5").Obj(),
-				).
-				Cohort("cohort").
-				Obj()
-			util.MustCreate(ctx, k8sClient, clusterQueue)
-			localQueue = testing.MakeLocalQueue("queue", ns.Name).ClusterQueue(clusterQueue.Name).Obj()
-			util.MustCreate(ctx, k8sClient, localQueue)
-		})
-
-		ginkgo.AfterEach(func() {
-			util.ExpectObjectToBeDeleted(ctx, k8sClient, clusterQueue, true)
-			util.ExpectObjectToBeDeleted(ctx, k8sClient, onDemandFlavor, true)
-		})
-
-		ginkgo.It("Should update of the pending workloads when a new workload is scheduled", framework.SlowSpec, func() {
-			const lowPrio, midLowerPrio, midHigherPrio, highPrio = 0, 10, 20, 100
-			workloadsFirstBatch := []*kueue.Workload{
-				testing.MakeWorkload("one", ns.Name).Queue(kueue.LocalQueueName(localQueue.Name)).Priority(highPrio).
-					Request(corev1.ResourceCPU, "2").Request(resourceGPU, "2").Obj(),
-				testing.MakeWorkload("two", ns.Name).Queue(kueue.LocalQueueName(localQueue.Name)).Priority(midHigherPrio).
-					Request(corev1.ResourceCPU, "3").Request(resourceGPU, "3").Obj(),
-			}
-
-			ginkgo.By("Verify pending workload status before adding workloads")
-			gomega.Eventually(func(g gomega.Gomega) {
-				var updatedCq kueue.ClusterQueue
-				g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(clusterQueue), &updatedCq)).To(gomega.Succeed())
-				g.Expect(updatedCq.Status.PendingWorkloadsStatus).Should(gomega.BeComparableTo(&kueue.ClusterQueuePendingWorkloadsStatus{}, ignoreLastChangeTime))
-			}, util.Timeout, util.Interval).Should(gomega.Succeed())
-
-			ginkgo.By("Creating workloads")
-			for _, w := range workloadsFirstBatch {
-				util.MustCreate(ctx, k8sClient, w)
-			}
-
-			ginkgo.By("Awaiting for the pending workloads to be updated")
-			gomega.Eventually(func(g gomega.Gomega) {
-				var updatedCq kueue.ClusterQueue
-				g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(clusterQueue), &updatedCq)).To(gomega.Succeed())
-				g.Expect(updatedCq.Status.PendingWorkloadsStatus).Should(gomega.BeComparableTo(&kueue.ClusterQueuePendingWorkloadsStatus{
-					Head: []kueue.ClusterQueuePendingWorkload{
-						{
-							Name:      "one",
-							Namespace: ns.Name,
-						},
-						{
-							Name:      "two",
-							Namespace: ns.Name,
-						},
-					},
-				}, ignoreLastChangeTime))
-			}, util.Timeout, util.Interval).Should(gomega.Succeed())
-
-			ginkgo.By("Creating new workloads to so that the number of workloads exceeds the MaxCount")
-			workloadsSecondBatch := []*kueue.Workload{
-				testing.MakeWorkload("three", ns.Name).Queue(kueue.LocalQueueName(localQueue.Name)).Priority(midLowerPrio).
-					Request(corev1.ResourceCPU, "2").Request(resourceGPU, "2").Obj(),
-				testing.MakeWorkload("four", ns.Name).Queue(kueue.LocalQueueName(localQueue.Name)).Priority(lowPrio).
-					Request(corev1.ResourceCPU, "3").Request(resourceGPU, "3").Obj(),
-			}
-			for _, w := range workloadsSecondBatch {
-				util.MustCreate(ctx, k8sClient, w)
-			}
-
-			ginkgo.By("Verify the head of pending workloads when the number of pending workloads exceeds MaxCount")
-			gomega.Eventually(func(g gomega.Gomega) {
-				var updatedCq kueue.ClusterQueue
-				g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(clusterQueue), &updatedCq)).To(gomega.Succeed())
-				g.Expect(updatedCq.Status.PendingWorkloadsStatus).Should(gomega.BeComparableTo(&kueue.ClusterQueuePendingWorkloadsStatus{
-					Head: []kueue.ClusterQueuePendingWorkload{
-						{
-							Name:      "one",
-							Namespace: ns.Name,
-						},
-						{
-							Name:      "two",
-							Namespace: ns.Name,
-						},
-						{
-							Name:      "three",
-							Namespace: ns.Name,
-						},
-					},
-				}, ignoreLastChangeTime))
-			}, util.Timeout, util.Interval).Should(gomega.Succeed())
-
-			ginkgo.By("Admitting workloads")
-			for _, w := range workloadsFirstBatch {
-				gomega.Eventually(func(g gomega.Gomega) {
-					var newWL kueue.Workload
-					g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(w), &newWL)).To(gomega.Succeed())
-					g.Expect(util.SetQuotaReservation(ctx, k8sClient, &newWL, testing.MakeAdmission(clusterQueue.Name).Obj())).Should(gomega.Succeed())
-				}, util.Timeout, util.Interval).Should(gomega.Succeed())
-			}
-
-			ginkgo.By("Awaiting for the pending workloads status to be updated after the workloads are admitted")
-			gomega.Eventually(func(g gomega.Gomega) {
-				var updatedCQ kueue.ClusterQueue
-				g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(clusterQueue), &updatedCQ)).To(gomega.Succeed())
-				g.Expect(updatedCQ.Status.PendingWorkloadsStatus).Should(gomega.BeComparableTo(&kueue.ClusterQueuePendingWorkloadsStatus{
-					Head: []kueue.ClusterQueuePendingWorkload{
-						{
-							Name:      "three",
-							Namespace: ns.Name,
-						},
-						{
-							Name:      "four",
-							Namespace: ns.Name,
-						},
-					},
-				}, ignoreLastChangeTime))
-			}, util.Timeout, util.Interval).Should(gomega.Succeed())
-
-			ginkgo.By("Finishing workload", func() {
-				util.FinishWorkloads(ctx, k8sClient, workloadsFirstBatch...)
-				util.FinishWorkloads(ctx, k8sClient, workloadsSecondBatch...)
-			})
-
-			ginkgo.By("Awaiting for the pending workloads status to be updated after the workloads are finished")
-			gomega.Eventually(func(g gomega.Gomega) {
-				var updatedCq kueue.ClusterQueue
-				g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(clusterQueue), &updatedCq)).To(gomega.Succeed())
-				g.Expect(updatedCq.Status.PendingWorkloadsStatus).Should(gomega.BeComparableTo(&kueue.ClusterQueuePendingWorkloadsStatus{
-					Head: []kueue.ClusterQueuePendingWorkload{},
-				}, ignoreLastChangeTime))
-			}, util.Timeout, util.Interval).Should(gomega.Succeed())
-		})
-	})
-})
diff --git a/test/integration/singlecluster/controller/core/workload_controller_test.go b/test/integration/singlecluster/controller/core/workload_controller_test.go
index ee1a9ddce..4ebbc9140 100644
--- a/test/integration/singlecluster/controller/core/workload_controller_test.go
+++ b/test/integration/singlecluster/controller/core/workload_controller_test.go
@@ -33,6 +33,7 @@ import (
 	kueue "sigs.k8s.io/kueue/apis/kueue/v1beta1"
 	"sigs.k8s.io/kueue/pkg/constants"
 	"sigs.k8s.io/kueue/pkg/features"
+	"sigs.k8s.io/kueue/pkg/util/admissioncheck"
 	"sigs.k8s.io/kueue/pkg/util/slices"
 	"sigs.k8s.io/kueue/pkg/util/testing"
 	"sigs.k8s.io/kueue/pkg/workload"
@@ -236,7 +237,7 @@ var _ = ginkgo.Describe("Workload controller", ginkgo.Ordered, ginkgo.ContinueOn
 			})
 
 			// save check2 condition
-			oldCheck2Cond := workload.FindAdmissionCheck(createdWl.Status.AdmissionChecks, "check2")
+			oldCheck2Cond := admissioncheck.FindAdmissionCheck(createdWl.Status.AdmissionChecks, "check2")
 			gomega.Expect(oldCheck2Cond).NotTo(gomega.BeNil())
 
 			ginkgo.By("updating the queue checks, the changes should propagate to the workload", func() {
@@ -256,7 +257,7 @@ var _ = ginkgo.Describe("Workload controller", ginkgo.Ordered, ginkgo.ContinueOn
 					})).Should(gomega.ConsistOf("check2", "check3"))
 				}, util.Timeout, util.Interval).Should(gomega.Succeed())
 
-				check2Cond := workload.FindAdmissionCheck(createdWl.Status.AdmissionChecks, "check2")
+				check2Cond := admissioncheck.FindAdmissionCheck(createdWl.Status.AdmissionChecks, "check2")
 				gomega.Expect(check2Cond).To(gomega.Equal(oldCheck2Cond))
 			})
 		})
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 bcf154db5..653e32e3f 100644
--- a/test/integration/singlecluster/controller/jobs/job/job_controller_test.go
+++ b/test/integration/singlecluster/controller/jobs/job/job_controller_test.go
@@ -3220,7 +3220,6 @@ var _ = ginkgo.Describe("Job with elastic jobs via workload-slices support", gin
 					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())
diff --git a/test/integration/singlecluster/controller/jobs/raycluster/raycluster_controller_test.go b/test/integration/singlecluster/controller/jobs/raycluster/raycluster_controller_test.go
index 9dfc7544f..ec72973f6 100644
--- a/test/integration/singlecluster/controller/jobs/raycluster/raycluster_controller_test.go
+++ b/test/integration/singlecluster/controller/jobs/raycluster/raycluster_controller_test.go
@@ -18,6 +18,7 @@ package raycluster
 
 import (
 	"fmt"
+	"strconv"
 
 	"github.com/onsi/ginkgo/v2"
 	"github.com/onsi/gomega"
@@ -25,8 +26,10 @@ import (
 	corev1 "k8s.io/api/core/v1"
 	schedulingv1 "k8s.io/api/scheduling/v1"
 	apimeta "k8s.io/apimachinery/pkg/api/meta"
+	"k8s.io/apimachinery/pkg/api/resource"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/types"
+	utilfeature "k8s.io/apiserver/pkg/util/feature"
 	"k8s.io/utils/ptr"
 	ctrl "sigs.k8s.io/controller-runtime"
 	"sigs.k8s.io/controller-runtime/pkg/client"
@@ -36,9 +39,12 @@ import (
 	"sigs.k8s.io/kueue/pkg/controller/constants"
 	"sigs.k8s.io/kueue/pkg/controller/jobframework"
 	workloadraycluster "sigs.k8s.io/kueue/pkg/controller/jobs/raycluster"
+	"sigs.k8s.io/kueue/pkg/features"
 	"sigs.k8s.io/kueue/pkg/util/testing"
 	testingraycluster "sigs.k8s.io/kueue/pkg/util/testingjobs/raycluster"
 	testingrayjob "sigs.k8s.io/kueue/pkg/util/testingjobs/rayjob"
+	"sigs.k8s.io/kueue/pkg/workload"
+	"sigs.k8s.io/kueue/pkg/workloadslicing"
 	"sigs.k8s.io/kueue/test/util"
 
 	_ "sigs.k8s.io/kueue/pkg/controller/jobs/rayjob" // to enable the framework
@@ -690,3 +696,254 @@ var _ = ginkgo.Describe("Job controller with preemption enabled", ginkgo.Ordered
 		}, util.Timeout, util.Interval).Should(gomega.Succeed())
 	})
 })
+
+var _ = ginkgo.Describe("RayCluster with elastic jobs via workload-slices support", ginkgo.Ordered, ginkgo.ContinueOnFailure, func() {
+	var (
+		ns             *corev1.Namespace
+		resourceFlavor *kueue.ResourceFlavor
+		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())
+		fwk.StartManager(ctx, cfg, managerAndSchedulerSetup())
+	})
+	ginkgo.AfterAll(func() {
+		fwk.StopManager(ctx)
+	})
+
+	ginkgo.BeforeEach(func() {
+		ns = util.CreateNamespaceFromPrefixWithLog(ctx, k8sClient, "core-")
+
+		resourceFlavor = testing.MakeResourceFlavor("default").Obj()
+		util.MustCreate(ctx, k8sClient, resourceFlavor)
+
+		clusterQueue = testing.MakeClusterQueue("default").
+			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)
+		util.ExpectObjectToBeDeleted(ctx, k8sClient, localQueue, true)
+		util.ExpectObjectToBeDeleted(ctx, k8sClient, resourceFlavor, true)
+	})
+
+	ginkgo.It("Should support raycluster scale-down and scale-up", func() {
+		testRayCluster := testingraycluster.MakeCluster("foo", ns.Name).
+			SetAnnotation(workloadslicing.EnabledAnnotationKey, workloadslicing.EnabledAnnotationValue).
+			Queue(string(kueue.LocalQueueName(localQueue.Name))).
+			Request(rayv1.HeadNode, corev1.ResourceCPU, "1").
+			RequestWorkerGroup(corev1.ResourceCPU, "1").
+			WithEnableAutoscaling(ptr.To(true)).
+			ScaleFirstWorkerGroup(2).
+			Obj()
+
+		var testRayClusterWorkload *kueue.Workload
+
+		ginkgo.By("creating a raycluster")
+		util.MustCreate(ctx, k8sClient, testRayCluster)
+
+		ginkgo.By("admitting the raycluster's workload")
+		gomega.Eventually(func(g gomega.Gomega) {
+			workloads := &kueue.WorkloadList{}
+			g.Expect(k8sClient.List(ctx, workloads, client.InNamespace(testRayCluster.Namespace))).Should(gomega.Succeed())
+			g.Expect(workloads.Items).Should(gomega.HaveLen(1))
+			testRayClusterWorkload = &workloads.Items[0]
+			g.Expect(testRayClusterWorkload.Spec.PodSets).Should(gomega.HaveLen(2))
+
+			g.Expect(testRayClusterWorkload.Spec.PodSets[0].Count).Should(gomega.BeEquivalentTo(int32(1)))
+			g.Expect(testRayClusterWorkload.Spec.PodSets[1].Count).Should(gomega.BeEquivalentTo(int32(2)))
+
+			util.ExpectWorkloadsToBeAdmitted(ctx, k8sClient, testRayClusterWorkload)
+		}, util.Timeout, util.Interval).Should(gomega.Succeed())
+
+		ginkgo.By("the raycluster is unsuspended")
+		gomega.Eventually(func(g gomega.Gomega) {
+			g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(testRayCluster), testRayCluster)).Should(gomega.Succeed())
+			g.Expect(ptr.Deref(testRayCluster.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("3")))
+		}, util.Timeout, util.Interval).Should(gomega.Succeed())
+
+		ginkgo.By("reducing the worker replicas to 1 to emulate scale-down operation")
+		gomega.Eventually(func(g gomega.Gomega) {
+			g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(testRayCluster), testRayCluster)).Should(gomega.Succeed())
+			testRayCluster.Spec.WorkerGroupSpecs[0].Replicas = ptr.To(int32(1))
+			g.Expect(k8sClient.Update(ctx, testRayCluster)).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("2")))
+		}, util.Timeout, util.Interval).Should(gomega.Succeed())
+
+		ginkgo.By("assert the raycluster's workload is updated and still admitted")
+		gomega.Eventually(func(g gomega.Gomega) {
+			workloads := &kueue.WorkloadList{}
+			g.Expect(k8sClient.List(ctx, workloads, client.InNamespace(testRayCluster.Namespace))).Should(gomega.Succeed())
+			g.Expect(workloads.Items).Should(gomega.HaveLen(1))
+			util.ExpectWorkloadsToBeAdmitted(ctx, k8sClient, testRayClusterWorkload)
+
+			g.Expect(workloads.Items[0].Spec.PodSets).Should(gomega.HaveLen(2))
+			g.Expect(workloads.Items[0].Spec.PodSets[0].Count).Should(gomega.Equal(int32(1)))
+			g.Expect(workloads.Items[0].Spec.PodSets[1].Count).Should(gomega.Equal(int32(1)))
+
+			g.Expect(workloads.Items[0].UID).Should(gomega.BeEquivalentTo(testRayClusterWorkload.UID))
+			testRayClusterWorkload = &workloads.Items[0]
+		}, util.Timeout, util.Interval).Should(gomega.Succeed())
+
+		ginkgo.By("increasing the RayCluster's worker replicas to 2 to emulate scale-up operation")
+		gomega.Eventually(func(g gomega.Gomega) {
+			g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(testRayCluster), testRayCluster)).Should(gomega.Succeed())
+			testRayCluster.Spec.WorkerGroupSpecs[0].Replicas = ptr.To(int32(2))
+			g.Expect(k8sClient.Update(ctx, testRayCluster)).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))
+			// 1 core for the head node, and 1 for each of the 2 workers
+			g.Expect(cq.Status.FlavorsUsage[0].Resources[0].Total).Should(gomega.BeEquivalentTo(resource.MustParse("3")))
+		}, 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(testRayCluster.Namespace))).Should(gomega.Succeed())
+			g.Expect(workloads.Items).Should(gomega.HaveLen(2))
+
+			nameBeforeScaleUp := testRayClusterWorkload.Name
+
+			for i := range workloads.Items {
+				if workload.IsFinished(&workloads.Items[i]) {
+					g.Expect(workloads.Items[i].Name).Should(gomega.Equal(nameBeforeScaleUp))
+
+					// The original workload had 1 head node, and a single worker group with a single worker
+					g.Expect(workloads.Items[i].Spec.PodSets).Should(gomega.HaveLen(2))
+					g.Expect(workloads.Items[i].Spec.PodSets[0].Count).Should(gomega.Equal(int32(1)))
+					g.Expect(workloads.Items[i].Spec.PodSets[1].Count).Should(gomega.Equal(int32(1)))
+				} else {
+					g.Expect(workloads.Items[i].Name).ShouldNot(gomega.Equal(testRayClusterWorkload.Name))
+					util.ExpectWorkloadsToBeAdmitted(ctx, k8sClient, testRayClusterWorkload)
+					testRayClusterWorkload = &workloads.Items[i]
+				}
+			}
+
+			// We should have both the finished and the non-finished but admitted workload
+			g.Expect(testRayClusterWorkload.Name).ShouldNot(gomega.Equal(nameBeforeScaleUp))
+		}, util.Timeout, util.Interval).Should(gomega.Succeed())
+
+		ginkgo.By("the new workload has the correct podSets count")
+		gomega.Eventually(func(g gomega.Gomega) {
+			g.Expect(workload.IsAdmitted(testRayClusterWorkload)).Should(gomega.BeTrue())
+			g.Expect(workload.IsFinished(testRayClusterWorkload)).Should(gomega.BeFalse())
+
+			g.Expect(testRayClusterWorkload.Spec.PodSets).Should(gomega.HaveLen(2))
+			g.Expect(testRayClusterWorkload.Spec.PodSets[0].Count).Should(gomega.Equal(int32(1)))
+			g.Expect(testRayClusterWorkload.Spec.PodSets[1].Count).Should(gomega.Equal(int32(2)))
+		}, util.Timeout, util.Interval).Should(gomega.Succeed())
+	})
+
+	ginkgo.It("Should support scheduling pending workload after freeing capacity on scale-down", func() {
+		var (
+			testRayClusterAWorkload *kueue.Workload
+			testRayClusterBWorkload *kueue.Workload
+		)
+
+		testRayClusterA := testingraycluster.MakeCluster("raycluster-a", ns.Name).
+			SetAnnotation(workloadslicing.EnabledAnnotationKey, workloadslicing.EnabledAnnotationValue).
+			Queue(string(kueue.LocalQueueName(localQueue.Name))).
+			Request(rayv1.HeadNode, corev1.ResourceCPU, "1").
+			RequestWorkerGroup(corev1.ResourceCPU, "1").
+			WithEnableAutoscaling(ptr.To(true)).
+			ScaleFirstWorkerGroup(2).
+			Obj()
+
+		ginkgo.By("creating a raycluster-a")
+		util.MustCreate(ctx, k8sClient, testRayClusterA)
+
+		ginkgo.By("admitting the raycluster-a's workload")
+		gomega.Eventually(func(g gomega.Gomega) {
+			workloads := &kueue.WorkloadList{}
+			g.Expect(k8sClient.List(ctx, workloads, client.InNamespace(testRayClusterA.Namespace))).Should(gomega.Succeed())
+			g.Expect(workloads.Items).Should(gomega.HaveLen(1))
+			testRayClusterAWorkload = &workloads.Items[0]
+			util.ExpectWorkloadsToBeAdmitted(ctx, k8sClient, testRayClusterAWorkload)
+		}, util.Timeout, util.Interval).Should(gomega.Succeed())
+
+		ginkgo.By("the raycluster-a is unsuspended")
+		gomega.Eventually(func(g gomega.Gomega) {
+			g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(testRayClusterA), testRayClusterA)).Should(gomega.Succeed())
+			g.Expect(ptr.Deref(testRayClusterA.Spec.Suspend, false)).Should(gomega.BeFalse())
+		}, util.Timeout, util.Interval).Should(gomega.Succeed())
+
+		testRayClusterB := testingraycluster.MakeCluster("raycluster-b", ns.Name).
+			SetAnnotation(workloadslicing.EnabledAnnotationKey, workloadslicing.EnabledAnnotationValue).
+			Queue(string(kueue.LocalQueueName(localQueue.Name))).
+			Request(rayv1.HeadNode, corev1.ResourceCPU, "1").
+			RequestWorkerGroup(corev1.ResourceCPU, "1").
+			WithEnableAutoscaling(ptr.To(true)).
+			ScaleFirstWorkerGroup(2).
+			Obj()
+
+		ginkgo.By("creating a raycluster-b")
+		util.MustCreate(ctx, k8sClient, testRayClusterB)
+
+		ginkgo.By("the testRayClusterB remains suspended")
+		gomega.Eventually(func(g gomega.Gomega) {
+			g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(testRayClusterB), testRayClusterB)).Should(gomega.Succeed())
+			g.Expect(ptr.Deref(testRayClusterB.Spec.Suspend, false)).Should(gomega.BeTrue())
+		}, util.Timeout, util.Interval).Should(gomega.Succeed())
+
+		ginkgo.By("raycluster-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(testRayClusterA.Namespace), client.MatchingLabels{constants.JobUIDLabel: string(testRayClusterB.UID)})).Should(gomega.Succeed())
+			g.Expect(workloads.Items).Should(gomega.HaveLen(1))
+			testRayClusterBWorkload = &workloads.Items[0]
+			util.ExpectWorkloadsToBePending(ctx, k8sClient, testRayClusterBWorkload)
+		}, util.Timeout, util.Interval).Should(gomega.Succeed())
+
+		ginkgo.By("scale-down raycluster-a to make room for raycluster-b")
+		gomega.Eventually(func(g gomega.Gomega) {
+			testRayClusterA.Spec.WorkerGroupSpecs[0].Replicas = ptr.To(int32(1))
+			g.Expect(k8sClient.Update(ctx, testRayClusterA)).Should(gomega.Succeed())
+		}, util.Timeout, util.Interval).Should(gomega.Succeed())
+
+		ginkgo.By("admitting the raycluster-b workload")
+		gomega.Eventually(func(g gomega.Gomega) {
+			g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(testRayClusterBWorkload), testRayClusterBWorkload)).Should(gomega.Succeed())
+			util.ExpectWorkloadsToBeAdmitted(ctx, k8sClient, testRayClusterBWorkload)
+		}, util.Timeout, util.Interval).Should(gomega.Succeed())
+
+		ginkgo.By("the raycluster-b is unsuspended")
+		gomega.Eventually(func(g gomega.Gomega) {
+			g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(testRayClusterB), testRayClusterB)).Should(gomega.Succeed())
+			g.Expect(ptr.Deref(testRayClusterB.Spec.Suspend, false)).Should(gomega.BeFalse())
+		}, util.Timeout, util.Interval).Should(gomega.Succeed())
+	})
+})
diff --git a/test/integration/singlecluster/tas/tas_test.go b/test/integration/singlecluster/tas/tas_test.go
index e9e89708d..3940e2d8f 100644
--- a/test/integration/singlecluster/tas/tas_test.go
+++ b/test/integration/singlecluster/tas/tas_test.go
@@ -39,6 +39,7 @@ import (
 	"sigs.k8s.io/kueue/pkg/controller/admissionchecks/provisioning"
 	"sigs.k8s.io/kueue/pkg/controller/tas"
 	"sigs.k8s.io/kueue/pkg/features"
+	"sigs.k8s.io/kueue/pkg/util/admissioncheck"
 	utiltas "sigs.k8s.io/kueue/pkg/util/tas"
 	"sigs.k8s.io/kueue/pkg/util/testing"
 	testingnode "sigs.k8s.io/kueue/pkg/util/testingjobs/node"
@@ -956,7 +957,7 @@ var _ = ginkgo.Describe("Topology Aware Scheduling", ginkgo.Ordered, func() {
 					gomega.Expect(k8sClient.Delete(ctx, nodeToUpdate)).Should(gomega.Succeed())
 				})
 
-				ginkgo.By("verify the workload has corrected TopologyAssignment and no NodeToReplaceAnnotation", func() {
+				ginkgo.By("verify the workload has corrected TopologyAssignment and no NodeToReplace", func() {
 					gomega.Eventually(func(g gomega.Gomega) {
 						g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(wl1), wl1)).To(gomega.Succeed())
 						g.Expect(wl1.Status.Admission.PodSetAssignments[0].TopologyAssignment).Should(gomega.BeComparableTo(
@@ -968,7 +969,7 @@ var _ = ginkgo.Describe("Topology Aware Scheduling", ginkgo.Ordered, func() {
 								},
 							},
 						))
-						g.Expect(wl1.Annotations).NotTo(gomega.HaveKeyWithValue(kueuealpha.NodeToReplaceAnnotation, nodeName))
+						g.Expect(wl1.Status.NodesToReplace).NotTo(gomega.ContainElement(nodeName))
 					}, util.Timeout, util.Interval).Should(gomega.Succeed())
 				})
 			})
@@ -1010,7 +1011,7 @@ var _ = ginkgo.Describe("Topology Aware Scheduling", ginkgo.Ordered, func() {
 					})
 				})
 
-				ginkgo.By("verify the workload has corrected TopologyAssignment and no NodeToReplaceAnnotation", func() {
+				ginkgo.By("verify the workload has corrected TopologyAssignment", func() {
 					gomega.Eventually(func(g gomega.Gomega) {
 						g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(wl1), wl1)).To(gomega.Succeed())
 						g.Expect(wl1.Status.Admission.PodSetAssignments[0].TopologyAssignment).Should(gomega.BeComparableTo(
@@ -1022,11 +1023,11 @@ var _ = ginkgo.Describe("Topology Aware Scheduling", ginkgo.Ordered, func() {
 								},
 							},
 						))
-						g.Expect(wl1.Annotations).NotTo(gomega.HaveKeyWithValue(kueuealpha.NodeToReplaceAnnotation, nodeName))
+						gomega.Expect(wl1.Status.NodesToReplace).NotTo(gomega.ContainElement(nodeName))
 					}, util.Timeout, util.Interval).Should(gomega.Succeed())
 				})
 			})
-			ginkgo.It("should clear the annotation when node recovers", func() {
+			ginkgo.It("should remove node from nodesToReplace when the node recovers", func() {
 				var wl1 *kueue.Workload
 				nodeName := nodes[0].Name
 
@@ -1065,11 +1066,11 @@ var _ = ginkgo.Describe("Topology Aware Scheduling", ginkgo.Ordered, func() {
 					})
 				})
 
-				ginkgo.By("verify the workload eventually gets the NodeToReplaceAnnotation", func() {
-					gomega.Eventually(func(g gomega.Gomega) map[string]string {
+				ginkgo.By("verify the workload eventually gets an entry in nodesToReplace list", func() {
+					gomega.Eventually(func(g gomega.Gomega) []string {
 						g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(wl1), wl1)).To(gomega.Succeed())
-						return wl1.Annotations
-					}, util.Timeout, util.Interval).Should(gomega.HaveKeyWithValue(kueuealpha.NodeToReplaceAnnotation, nodeName))
+						return wl1.Status.NodesToReplace
+					}, util.Timeout, util.Interval).Should(gomega.ContainElement(nodeName))
 				})
 
 				ginkgo.By("node recovers", func() {
@@ -1083,15 +1084,15 @@ var _ = ginkgo.Describe("Topology Aware Scheduling", ginkgo.Ordered, func() {
 					})
 				})
 
-				ginkgo.By("verify the annotation is cleared", func() {
-					gomega.Eventually(func(g gomega.Gomega) map[string]string {
+				ginkgo.By("verify the node is removed from nodesToReplace", func() {
+					gomega.Eventually(func(g gomega.Gomega) []string {
 						g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(wl1), wl1)).To(gomega.Succeed())
-						return wl1.Annotations
-					}, util.Timeout, util.Interval).ShouldNot(gomega.HaveKeyWithValue(kueuealpha.NodeToReplaceAnnotation, nodeName))
+						return wl1.Status.NodesToReplace
+					}, util.Timeout, util.Interval).ShouldNot(gomega.ContainElement(nodeName))
 				})
 			})
 
-			ginkgo.It("should clear the annotation when node reappears", func() {
+			ginkgo.It("should remove the node from nodesToReplace when node reappears", func() {
 				var wl1 *kueue.Workload
 				nodeName := nodes[0].Name
 
@@ -1125,10 +1126,10 @@ var _ = ginkgo.Describe("Topology Aware Scheduling", ginkgo.Ordered, func() {
 				})
 
 				ginkgo.By("verify the workload eventually gets the NodeToReplaceAnnotation", func() {
-					gomega.Eventually(func(g gomega.Gomega) map[string]string {
+					gomega.Eventually(func(g gomega.Gomega) []string {
 						g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(wl1), wl1)).To(gomega.Succeed())
-						return wl1.Annotations
-					}, util.Timeout, util.Interval).Should(gomega.HaveKeyWithValue(kueuealpha.NodeToReplaceAnnotation, nodeName))
+						return wl1.Status.NodesToReplace
+					}, util.Timeout, util.Interval).Should(gomega.ContainElement(nodeName))
 				})
 
 				ginkgo.By("node reappears", func() {
@@ -1136,11 +1137,11 @@ var _ = ginkgo.Describe("Topology Aware Scheduling", ginkgo.Ordered, func() {
 					gomega.Expect(k8sClient.Create(ctx, nodeToDelete)).Should(gomega.Succeed())
 				})
 
-				ginkgo.By("verify the annotation is cleared", func() {
-					gomega.Eventually(func(g gomega.Gomega) map[string]string {
+				ginkgo.By("verify the NodesToReplace is cleared", func() {
+					gomega.Eventually(func(g gomega.Gomega) []string {
 						g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(wl1), wl1)).To(gomega.Succeed())
-						return wl1.Annotations
-					}, util.Timeout, util.Interval).ShouldNot(gomega.HaveKeyWithValue(kueuealpha.NodeToReplaceAnnotation, nodeName))
+						return wl1.Status.NodesToReplace
+					}, util.Timeout, util.Interval).ShouldNot(gomega.ContainElement(nodeName))
 				})
 			})
 
@@ -1223,7 +1224,7 @@ var _ = ginkgo.Describe("Topology Aware Scheduling", ginkgo.Ordered, func() {
 				ginkgo.By("Finishing second workload")
 				util.FinishWorkloads(ctx, k8sClient, wl2)
 
-				ginkgo.By("verify the workload has corrected TopologyAssignment and no NodeToReplaceAnnotation", func() {
+				ginkgo.By("verify the workload has corrected TopologyAssignment and no node in NodesToReplace", func() {
 					gomega.Eventually(func(g gomega.Gomega) {
 						g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(wl1), wl1)).To(gomega.Succeed())
 						g.Expect(wl1.Status.Admission.PodSetAssignments[0].TopologyAssignment).Should(gomega.BeComparableTo(
@@ -1235,7 +1236,7 @@ var _ = ginkgo.Describe("Topology Aware Scheduling", ginkgo.Ordered, func() {
 								},
 							},
 						))
-						g.Expect(wl1.Annotations).NotTo(gomega.HaveKeyWithValue(kueuealpha.NodeToReplaceAnnotation, nodeName))
+						g.Expect(wl1.Status.NodesToReplace).NotTo(gomega.ContainElement(nodeName))
 					}, util.Timeout, util.Interval).Should(gomega.Succeed())
 				})
 			})
@@ -1286,9 +1287,7 @@ var _ = ginkgo.Describe("Topology Aware Scheduling", ginkgo.Ordered, func() {
 					gomega.Eventually(func(g gomega.Gomega) {
 						updatedWl := &kueue.Workload{}
 						g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(wl1), updatedWl)).To(gomega.Succeed())
-						annotations := updatedWl.GetAnnotations()
-						_, found := annotations[kueuealpha.NodeToReplaceAnnotation]
-						g.Expect(found).To(gomega.BeFalse(), "NodeToReplaceAnnotation should be cleared after eviction due to multiple node failures")
+						g.Expect(updatedWl.Status.NodesToReplace).To(gomega.BeEmpty(), "NodesToReplace should be cleared after eviction due to multiple node failures")
 					}, util.Timeout, util.Interval).Should(gomega.Succeed())
 				})
 			})
@@ -1330,7 +1329,6 @@ var _ = ginkgo.Describe("Topology Aware Scheduling", ginkgo.Ordered, func() {
 						LastTransitionTime: metav1.NewTime(time.Now().Add(-tas.NodeFailureDelay)),
 					})
 				})
-
 				ginkgo.By("updating nodeReady condition of the second node", func() {
 					nodeToUpdate := &corev1.Node{}
 					gomega.Expect(k8sClient.Get(ctx, apitypes.NamespacedName{Name: node2Name}, nodeToUpdate)).Should(gomega.Succeed())
@@ -1346,9 +1344,7 @@ var _ = ginkgo.Describe("Topology Aware Scheduling", ginkgo.Ordered, func() {
 					gomega.Eventually(func(g gomega.Gomega) {
 						updatedWl := &kueue.Workload{}
 						g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(wl1), updatedWl)).To(gomega.Succeed())
-						annotations := updatedWl.GetAnnotations()
-						_, found := annotations[kueuealpha.NodeToReplaceAnnotation]
-						g.Expect(found).To(gomega.BeFalse(), "NodeToReplaceAnnotation should be cleared after eviction due to multiple node failures")
+						g.Expect(updatedWl.Status.NodesToReplace).To(gomega.BeEmpty(), "NodesToReplace should be cleared after eviction due to multiple node failures")
 					}, util.Timeout, util.Interval).Should(gomega.Succeed())
 				})
 			})
@@ -1489,9 +1485,7 @@ var _ = ginkgo.Describe("Topology Aware Scheduling", ginkgo.Ordered, func() {
 					gomega.Eventually(func(g gomega.Gomega) {
 						updatedWl := &kueue.Workload{}
 						g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(wl1), updatedWl)).To(gomega.Succeed())
-						annotations := updatedWl.GetAnnotations()
-						_, found := annotations[kueuealpha.NodeToReplaceAnnotation]
-						g.Expect(found).To(gomega.BeFalse())
+						g.Expect(wl1.Status.NodesToReplace).To(gomega.BeEmpty())
 					}, util.Timeout, util.Interval).Should(gomega.Succeed())
 				})
 
@@ -2528,7 +2522,7 @@ var _ = ginkgo.Describe("Topology Aware Scheduling", ginkgo.Ordered, func() {
 				ginkgo.By("await for the check to be ready", func() {
 					gomega.Eventually(func(g gomega.Gomega) {
 						g.Expect(k8sClient.Get(ctx, wlKey, wl1)).To(gomega.Succeed())
-						state := workload.FindAdmissionCheck(wl1.Status.AdmissionChecks, kueue.AdmissionCheckReference(ac.Name))
+						state := admissioncheck.FindAdmissionCheck(wl1.Status.AdmissionChecks, kueue.AdmissionCheckReference(ac.Name))
 						g.Expect(state).NotTo(gomega.BeNil())
 						g.Expect(state.State).To(gomega.Equal(kueue.CheckStateReady))
 					}, util.Timeout, time.Millisecond).Should(gomega.Succeed())
diff --git a/test/util/util.go b/test/util/util.go
index 70c922479..d3eec9060 100644
--- a/test/util/util.go
+++ b/test/util/util.go
@@ -68,6 +68,7 @@ import (
 	podconstants "sigs.k8s.io/kueue/pkg/controller/jobs/pod/constants"
 	"sigs.k8s.io/kueue/pkg/metrics"
 	"sigs.k8s.io/kueue/pkg/scheduler/preemption"
+	"sigs.k8s.io/kueue/pkg/util/admissioncheck"
 	utiltas "sigs.k8s.io/kueue/pkg/util/tas"
 	"sigs.k8s.io/kueue/pkg/util/testing"
 	"sigs.k8s.io/kueue/pkg/workload"
@@ -747,7 +748,7 @@ func SetWorkloadsAdmissionCheck(ctx context.Context, k8sClient client.Client, wl
 	gomega.EventuallyWithOffset(1, func(g gomega.Gomega) {
 		g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(wl), &updatedWorkload)).To(gomega.Succeed())
 		if expectExisting {
-			currentCheck := workload.FindAdmissionCheck(updatedWorkload.Status.AdmissionChecks, check)
+			currentCheck := admissioncheck.FindAdmissionCheck(updatedWorkload.Status.AdmissionChecks, check)
 			g.Expect(currentCheck).NotTo(gomega.BeNil(), "the check %s was not found in %s", check, workload.Key(wl))
 			currentCheck.State = state
 		} else {
@@ -936,6 +937,14 @@ func ExpectJobUnsuspendedWithNodeSelectors(ctx context.Context, c client.Client,
 	}, Timeout, Interval).Should(gomega.Succeed())
 }
 
+func ExpectRayClusterUnsuspended(ctx context.Context, c client.Client, key types.NamespacedName) {
+	rayCluster := &rayv1.RayCluster{}
+	gomega.EventuallyWithOffset(1, func(g gomega.Gomega) {
+		g.Expect(c.Get(ctx, key, rayCluster)).To(gomega.Succeed())
+		g.Expect(rayCluster.Spec.Suspend).Should(gomega.Equal(ptr.To(false)))
+	}, Timeout, Interval).Should(gomega.Succeed())
+}
+
 func CreateNodesWithStatus(ctx context.Context, c client.Client, nodes []corev1.Node) {
 	for _, node := range nodes {
 		// 1. Create a node