Repository: kubernetes-sigs/kueue
Pull request #4567: TAS: Add the `kueue.x-k8s.io/podset-unconstrained-topology` annotation
Author: login: PBundyra
Labels: name: kind/feature
description: Categorizes issue or PR as related to a new feature.
name: release-note
description: Denotes a PR that will be considered when it comes time to generate release notes.
name: lgtm
description: "Looks good to me", indicates that a PR is ready to be merged.
name: size/XL
description: Denotes a PR that changes 500-999 lines, ignoring generated files.
name: approved
description: Indicates a PR has been approved by an approver from all required OWNERS files.
name: cncf-cla: yes
description: Indicates the PR's author has signed the CNCF CLA.
Created: 2025-03-12T12:47:26Z | Merged: 2025-03-13T12:25:47Z

<!--  Thanks for sending a pull request!  Here are some tips for you:

1. If this is your first time, please read our contributor guidelines: https://git.k8s.io/community/contributors/guide/first-contribution.md#your-first-contribution and developer guide https://git.k8s.io/community/contributors/devel/development.md#development-guide
2. Please label this pull request according to what type of issue you are addressing, especially if this is a release targeted pull request. For reference on required PR/issue labels, read here:
https://git.k8s.io/community/contributors/devel/sig-release/release.md#issuepr-kind-label
3. Ensure you have added or ran the appropriate tests for your PR: https://git.k8s.io/community/contributors/devel/sig-testing/testing.md
4. If you want *faster* PR reviews, read how: https://git.k8s.io/community/contributors/guide/pull-requests.md#best-practices-for-faster-reviews
5. If the PR is unfinished, see how to mark it: https://git.k8s.io/community/contributors/guide/pull-requests.md#marking-unfinished-pull-requests
-->

#### What type of PR is this?
/kind feature

<!--
Add one of the following kinds:
/kind bug
/kind cleanup
/kind documentation
/kind feature

Optionally add one or more of the following kinds if applicable:
/kind api-change
/kind deprecation
/kind failing-test
/kind flake
/kind regression
-->

#### What this PR does / why we need it:
This PR introduces changes described in this KEP #4542 :
- Adds a new annotation
- Extends PodSetTopologyRequest API with .unconstrained field

#### Which issue(s) this PR fixes:
<!--
*Automatically closes linked issue when PR is merged.
Usage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`.
_If PR is about `failing-tests or flakes`, please post the related issues/tests in a comment and do not use `Fixes`_*
-->
Part of #4474 

#### Special notes for your reviewer:

#### Does this PR introduce a user-facing change?
<!--
If no, just write "NONE" in the release-note block below.
If yes, a release note is required:
Enter your extended release note in the block below. If the PR requires additional action from users switching to the new release, include the string "action required".
-->
```release-note
TopologyAwareScheduling can now be used with `kueue.x-k8s.io/podset-unconstrained-topology` annotation
```


Diff:
diff --git a/apis/kueue/v1alpha1/tas_types.go b/apis/kueue/v1alpha1/tas_types.go
index 5538b2d61a9..84ba98f03a5 100644
--- a/apis/kueue/v1alpha1/tas_types.go
+++ b/apis/kueue/v1alpha1/tas_types.go
@@ -38,6 +38,14 @@ const (
 	// among multiple topology domains.
 	PodSetPreferredTopologyAnnotation = "kueue.x-k8s.io/podset-preferred-topology"
 
+	// PodSetUnconstrainedTopologyAnnotation indicates that a PodSet does not have any topology requirements.
+	// Kueue admits the PodSet if there's enough free capacity available.
+	// Recommended for PodSets that don't need low-latency or high-throughput pod-to-pod communication,
+	// but want to leverage TAS capabilities improve accuracy of admitting jobs
+	//
+	// +kubebuilder:validation:Type=boolean
+	PodSetUnconstrainedTopologyAnnotation = "kueue.x-k8s.io/podset-unconstrained-topology"
+
 	// TopologySchedulingGate is used to delay scheduling of a Pod until the
 	// nodeSelectors corresponding to the assigned topology domain are injected
 	// into the Pod. For the Pod-based integrations the gate is added in webhook
diff --git a/apis/kueue/v1beta1/workload_types.go b/apis/kueue/v1beta1/workload_types.go
index be31e10ce36..db8a7c2b18c 100644
--- a/apis/kueue/v1beta1/workload_types.go
+++ b/apis/kueue/v1beta1/workload_types.go
@@ -104,6 +104,14 @@ type PodSetTopologyRequest struct {
 	// +optional
 	Preferred *string `json:"preferred,omitempty"`
 
+	// unconstrained indicates that Kueue has the freedom to schedule the PodSet within
+	// the entire available capacity, without constraints on the compactness of the placement.
+	// This is indicated by the `kueue.x-k8s.io/podset-unconstrained-topology` PodSet annotation.
+	//
+	// +optional
+	// +kubebuilder:validation:Type=boolean
+	Unconstrained *bool `json:"unconstrained,omitempty"`
+
 	// PodIndexLabel indicates the name of the label indexing the pods.
 	// For example, in the context of
 	// - kubernetes job this is: kubernetes.io/job-completion-index
diff --git a/apis/kueue/v1beta1/zz_generated.deepcopy.go b/apis/kueue/v1beta1/zz_generated.deepcopy.go
index 19af8c5e5b6..b6ab50c9fea 100644
--- a/apis/kueue/v1beta1/zz_generated.deepcopy.go
+++ b/apis/kueue/v1beta1/zz_generated.deepcopy.go
@@ -1055,6 +1055,11 @@ func (in *PodSetTopologyRequest) DeepCopyInto(out *PodSetTopologyRequest) {
 		*out = new(string)
 		**out = **in
 	}
+	if in.Unconstrained != nil {
+		in, out := &in.Unconstrained, &out.Unconstrained
+		*out = new(bool)
+		**out = **in
+	}
 	if in.PodIndexLabel != nil {
 		in, out := &in.PodIndexLabel, &out.PodIndexLabel
 		*out = new(string)
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 03a39b556dd..5767c72f340 100644
--- a/charts/kueue/templates/crd/kueue.x-k8s.io_workloads.yaml
+++ b/charts/kueue/templates/crd/kueue.x-k8s.io_workloads.yaml
@@ -8329,6 +8329,12 @@ spec:
                             SubGroupIndexLabel indicates the name of the label indexing the instances of replicated Jobs (groups)
                             within a PodSet. For example, in the context of JobSet this is jobset.sigs.k8s.io/job-index.
                           type: string
+                        unconstrained:
+                          description: |-
+                            unconstrained indicates that Kueue has the freedom to schedule the PodSet within
+                            the entire available capacity, without constraints on the compactness of the placement.
+                            This is indicated by the `kueue.x-k8s.io/podset-unconstrained-topology` PodSet annotation.
+                          type: boolean
                       type: object
                   required:
                   - count
diff --git a/client-go/applyconfiguration/kueue/v1beta1/podsettopologyrequest.go b/client-go/applyconfiguration/kueue/v1beta1/podsettopologyrequest.go
index 906eef5ad8e..3756f718109 100644
--- a/client-go/applyconfiguration/kueue/v1beta1/podsettopologyrequest.go
+++ b/client-go/applyconfiguration/kueue/v1beta1/podsettopologyrequest.go
@@ -22,6 +22,7 @@ package v1beta1
 type PodSetTopologyRequestApplyConfiguration struct {
 	Required           *string `json:"required,omitempty"`
 	Preferred          *string `json:"preferred,omitempty"`
+	Unconstrained      *bool   `json:"unconstrained,omitempty"`
 	PodIndexLabel      *string `json:"podIndexLabel,omitempty"`
 	SubGroupIndexLabel *string `json:"subGroupIndexLabel,omitempty"`
 	SubGroupCount      *int32  `json:"subGroupCount,omitempty"`
@@ -49,6 +50,14 @@ func (b *PodSetTopologyRequestApplyConfiguration) WithPreferred(value string) *P
 	return b
 }
 
+// WithUnconstrained sets the Unconstrained field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the Unconstrained field is set to the value of the last call.
+func (b *PodSetTopologyRequestApplyConfiguration) WithUnconstrained(value bool) *PodSetTopologyRequestApplyConfiguration {
+	b.Unconstrained = &value
+	return b
+}
+
 // WithPodIndexLabel sets the PodIndexLabel field in the declarative configuration to the given value
 // and returns the receiver, so that objects can be built by chaining "With" function invocations.
 // If called multiple times, the PodIndexLabel field is set to the value of the last call.
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 2f79cafed78..c879bd3105d 100644
--- a/config/components/crd/bases/kueue.x-k8s.io_workloads.yaml
+++ b/config/components/crd/bases/kueue.x-k8s.io_workloads.yaml
@@ -8314,6 +8314,12 @@ spec:
                             SubGroupIndexLabel indicates the name of the label indexing the instances of replicated Jobs (groups)
                             within a PodSet. For example, in the context of JobSet this is jobset.sigs.k8s.io/job-index.
                           type: string
+                        unconstrained:
+                          description: |-
+                            unconstrained indicates that Kueue has the freedom to schedule the PodSet within
+                            the entire available capacity, without constraints on the compactness of the placement.
+                            This is indicated by the `kueue.x-k8s.io/podset-unconstrained-topology` PodSet annotation.
+                          type: boolean
                       type: object
                   required:
                   - count
diff --git a/pkg/cache/tas_cache_test.go b/pkg/cache/tas_cache_test.go
index 3918717e665..b1da55b12b8 100644
--- a/pkg/cache/tas_cache_test.go
+++ b/pkg/cache/tas_cache_test.go
@@ -23,6 +23,7 @@ import (
 	"github.com/google/go-cmp/cmp"
 	corev1 "k8s.io/api/core/v1"
 	"k8s.io/apimachinery/pkg/api/resource"
+	"k8s.io/component-base/featuregate"
 	"k8s.io/utils/ptr"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 
@@ -115,6 +116,69 @@ func TestFindTopologyAssignment(t *testing.T) {
 			Ready().
 			Obj(),
 	}
+	//nolint:dupword // suppress duplicate r1 word
+	//       b1           b2
+	//       |             |
+	//       r1           r1
+	//     /  |  \       /  \
+	//   x1  x2  x3     x4  x5
+	scatteredNodes := []corev1.Node{
+		*testingnode.MakeNode("b1-r1-x1").
+			Label(tasBlockLabel, "b1").
+			Label(tasRackLabel, "r1").
+			Label(corev1.LabelHostname, "x1").
+			StatusAllocatable(corev1.ResourceList{
+				corev1.ResourceCPU:    resource.MustParse("4"),
+				corev1.ResourceMemory: resource.MustParse("1Gi"),
+				corev1.ResourcePods:   resource.MustParse("10"),
+			}).
+			Ready().
+			Obj(),
+		*testingnode.MakeNode("b1-r1-x2").
+			Label(tasBlockLabel, "b1").
+			Label(tasRackLabel, "r1").
+			Label(corev1.LabelHostname, "x2").
+			StatusAllocatable(corev1.ResourceList{
+				corev1.ResourceCPU:    resource.MustParse("1"),
+				corev1.ResourceMemory: resource.MustParse("1Gi"),
+				corev1.ResourcePods:   resource.MustParse("10"),
+			}).
+			Ready().
+			Obj(),
+		*testingnode.MakeNode("b1-r1-x3").
+			Label(tasBlockLabel, "b1").
+			Label(tasRackLabel, "r1").
+			Label(corev1.LabelHostname, "x3").
+			StatusAllocatable(corev1.ResourceList{
+				corev1.ResourceCPU:    resource.MustParse("1"),
+				corev1.ResourceMemory: resource.MustParse("1Gi"),
+				corev1.ResourcePods:   resource.MustParse("10"),
+			}).
+			Ready().
+			Obj(),
+		*testingnode.MakeNode("b2-r1-x4").
+			Label(tasBlockLabel, "b2").
+			Label(tasRackLabel, "r1").
+			Label(corev1.LabelHostname, "x4").
+			StatusAllocatable(corev1.ResourceList{
+				corev1.ResourceCPU:    resource.MustParse("2"),
+				corev1.ResourceMemory: resource.MustParse("1Gi"),
+				corev1.ResourcePods:   resource.MustParse("10"),
+			}).
+			Ready().
+			Obj(),
+		*testingnode.MakeNode("b2-r1-x5").
+			Label(tasBlockLabel, "b2").
+			Label(tasRackLabel, "r1").
+			Label(corev1.LabelHostname, "x5").
+			StatusAllocatable(corev1.ResourceList{
+				corev1.ResourceCPU:    resource.MustParse("1"),
+				corev1.ResourceMemory: resource.MustParse("1Gi"),
+				corev1.ResourcePods:   resource.MustParse("10"),
+			}).
+			Ready().
+			Obj(),
+	}
 	defaultOneLevel := []string{
 		corev1.LabelHostname,
 	}
@@ -226,17 +290,17 @@ func TestFindTopologyAssignment(t *testing.T) {
 
 	cases := map[string]struct {
 		// TODO: remove after dropping the TASMostFreeCapacity feature gate
-		enableTASMostFreeCapacity bool
-		wantReason                string
-		topologyRequest           kueue.PodSetTopologyRequest
-		levels                    []string
-		nodeLabels                map[string]string
-		nodes                     []corev1.Node
-		pods                      []corev1.Pod
-		requests                  resources.Requests
-		count                     int32
-		tolerations               []corev1.Toleration
-		wantAssignment            *kueue.TopologyAssignment
+		enableFeatureGates []featuregate.Feature
+		wantReason         string
+		topologyRequest    kueue.PodSetTopologyRequest
+		levels             []string
+		nodeLabels         map[string]string
+		nodes              []corev1.Node
+		pods               []corev1.Pod
+		requests           resources.Requests
+		count              int32
+		tolerations        []corev1.Toleration
+		wantAssignment     *kueue.TopologyAssignment
 	}{
 		// TODO: remove suffixes MostFreeCapacity/BestFit after dropping the TASMostFreeCapacity feature gate
 		"minimize the number of used racks before optimizing the number of nodes; MostFreeCapacity": {
@@ -348,7 +412,64 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: true,
+			enableFeatureGates: []featuregate.Feature{features.TASMostFreeCapacity},
+		},
+		"unconstrained; 6 pods fit into hosts scattered across the whole datacenter even they could fit into single rack; BestFit": {
+			nodes: scatteredNodes,
+			topologyRequest: kueue.PodSetTopologyRequest{
+				Unconstrained: ptr.To(true),
+			},
+			levels: defaultThreeLevels,
+			requests: resources.Requests{
+				corev1.ResourceCPU: 1000,
+			},
+			count: 6,
+			wantAssignment: &kueue.TopologyAssignment{
+				Levels: defaultOneLevel,
+				Domains: []kueue.TopologyDomainAssignment{
+					{
+						Count: 4,
+						Values: []string{
+							"x1",
+						},
+					},
+					{
+						Count: 2,
+						Values: []string{
+							"x4",
+						},
+					},
+				},
+			},
+		},
+		"unconstrained; 6 pods fit into hosts scattered across the whole datacenter even they could fit into single rack; MostFreeCapacityFit": {
+			nodes: scatteredNodes,
+			topologyRequest: kueue.PodSetTopologyRequest{
+				Unconstrained: ptr.To(true),
+			},
+			levels: defaultThreeLevels,
+			requests: resources.Requests{
+				corev1.ResourceCPU: 1000,
+			},
+			count: 6,
+			wantAssignment: &kueue.TopologyAssignment{
+				Levels: defaultOneLevel,
+				Domains: []kueue.TopologyDomainAssignment{
+					{
+						Count: 4,
+						Values: []string{
+							"x1",
+						},
+					},
+					{
+						Count: 2,
+						Values: []string{
+							"x4",
+						},
+					},
+				},
+			},
+			enableFeatureGates: []featuregate.Feature{features.TASMostFreeCapacity},
 		},
 		"block required; 4 pods fit into one host each; MostFreeCapacity": {
 			nodes: binaryTreesNodes,
@@ -389,7 +510,7 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: true,
+			enableFeatureGates: []featuregate.Feature{features.TASMostFreeCapacity},
 		},
 		"block required; 4 pods fit into one host each; BestFit": {
 			nodes: binaryTreesNodes,
@@ -430,7 +551,6 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: false,
 		},
 		"host required; single Pod fits in the host; MostFreeCapacity": {
 			// TODO: remove after dropping the TASMostFreeCapacity feature gate
@@ -454,7 +574,7 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: true,
+			enableFeatureGates: []featuregate.Feature{features.TASMostFreeCapacity},
 		},
 		"host required; single Pod fits in the host; BestFit": {
 			nodes: defaultNodes,
@@ -477,7 +597,6 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: false,
 		},
 		"rack required; single Pod fits in a rack; MostFreeCapacity": {
 			// TODO: remove after dropping the TASMostFreeCapacity feature gate
@@ -502,7 +621,7 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: true,
+			enableFeatureGates: []featuregate.Feature{features.TASMostFreeCapacity},
 		},
 		"rack required; multiple Pods fits in a rack; MostFreeCapacity": {
 			nodes: defaultNodes,
@@ -526,7 +645,7 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: true,
+			enableFeatureGates: []featuregate.Feature{features.TASMostFreeCapacity},
 		},
 		"rack required; multiple Pods fit in a rack; BestFit": {
 			nodes: defaultNodes,
@@ -550,7 +669,6 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: false,
 		},
 		"block preferred; Pods fit in 2 blocks; BestFit": {
 			nodes: []corev1.Node{
@@ -604,7 +722,6 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: false,
 		},
 		"rack required; multiple Pods fit in some racks; BestFit": {
 			nodes: defaultNodes,
@@ -628,7 +745,6 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: false,
 		},
 		"rack required; too many pods to fit in any rack; MostFreeCapacity": {
 			nodes: defaultNodes,
@@ -639,9 +755,10 @@ func TestFindTopologyAssignment(t *testing.T) {
 			requests: resources.Requests{
 				corev1.ResourceCPU: 1000,
 			},
-			count:                     4,
-			wantReason:                `topology "default" allows to fit only 3 out of 4 pod(s)`,
-			enableTASMostFreeCapacity: true,
+			count:      4,
+			wantReason: `topology "default" allows to fit only 3 out of 4 pod(s)`,
+
+			enableFeatureGates: []featuregate.Feature{features.TASMostFreeCapacity},
 		},
 		"block required; single Pod fits in a block; MostFreeCapacity": {
 			// TODO: remove after dropping the TASMostFreeCapacity feature gate
@@ -669,7 +786,7 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: true,
+			enableFeatureGates: []featuregate.Feature{features.TASMostFreeCapacity},
 		},
 		"block required; single Pod fits in a block and a single rack; BestFit": {
 			nodes: defaultNodes,
@@ -696,7 +813,6 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: false,
 		},
 		"block required; single Pod fits in a block spread across two racks; BestFit": {
 			nodes: defaultNodes,
@@ -730,7 +846,6 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: false,
 		},
 		"block required; Pods fit in a block spread across two racks; MostFreeCapacity": {
 			nodes: defaultNodes,
@@ -761,7 +876,7 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: true,
+			enableFeatureGates: []featuregate.Feature{features.TASMostFreeCapacity},
 		},
 		"block required; single Pod which cannot be split; MostFreeCapacity": {
 			nodes: defaultNodes,
@@ -772,9 +887,9 @@ func TestFindTopologyAssignment(t *testing.T) {
 			requests: resources.Requests{
 				corev1.ResourceCPU: 4000,
 			},
-			count:                     1,
-			wantReason:                `topology "default" doesn't allow to fit any of 1 pod(s)`,
-			enableTASMostFreeCapacity: true,
+			count:              1,
+			wantReason:         `topology "default" doesn't allow to fit any of 1 pod(s)`,
+			enableFeatureGates: []featuregate.Feature{features.TASMostFreeCapacity},
 		},
 		"block required; too many Pods to fit requested; MostFreeCapacity": {
 			nodes: defaultNodes,
@@ -785,9 +900,9 @@ func TestFindTopologyAssignment(t *testing.T) {
 			requests: resources.Requests{
 				corev1.ResourceCPU: 1000,
 			},
-			count:                     5,
-			wantReason:                `topology "default" allows to fit only 4 out of 5 pod(s)`,
-			enableTASMostFreeCapacity: true,
+			count:              5,
+			wantReason:         `topology "default" allows to fit only 4 out of 5 pod(s)`,
+			enableFeatureGates: []featuregate.Feature{features.TASMostFreeCapacity},
 		},
 		"rack required; single Pod requiring memory; MostFreeCapacity": {
 			// TODO: remove after dropping the TASMostFreeCapacity feature gate
@@ -812,7 +927,7 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: true,
+			enableFeatureGates: []featuregate.Feature{features.TASMostFreeCapacity},
 		},
 		"rack preferred; but only block can accommodate the workload; MostFreeCapacity": {
 			nodes: defaultNodes,
@@ -843,7 +958,7 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: true,
+			enableFeatureGates: []featuregate.Feature{features.TASMostFreeCapacity},
 		},
 		"rack preferred; but only multiple blocks can accommodate the workload; MostFreeCapacity": {
 			nodes: defaultNodes,
@@ -881,7 +996,7 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: true,
+			enableFeatureGates: []featuregate.Feature{features.TASMostFreeCapacity},
 		},
 		"block preferred; but only multiple blocks can accommodate the workload; MostFreeCapacity": {
 			nodes: defaultNodes,
@@ -919,7 +1034,7 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: true,
+			enableFeatureGates: []featuregate.Feature{features.TASMostFreeCapacity},
 		},
 		"block preferred; but the workload cannot be accommodate in entire topology; MostFreeCapacity": {
 			nodes: defaultNodes,
@@ -930,9 +1045,9 @@ func TestFindTopologyAssignment(t *testing.T) {
 			requests: resources.Requests{
 				corev1.ResourceCPU: 1000,
 			},
-			count:                     10,
-			wantReason:                `topology "default" allows to fit only 7 out of 10 pod(s)`,
-			enableTASMostFreeCapacity: true,
+			count:              10,
+			wantReason:         `topology "default" allows to fit only 7 out of 10 pod(s)`,
+			enableFeatureGates: []featuregate.Feature{features.TASMostFreeCapacity},
 		},
 		"only nodes with matching labels are considered; no matching node; MostFreeCapacity": {
 			nodes: []corev1.Node{
@@ -956,9 +1071,9 @@ func TestFindTopologyAssignment(t *testing.T) {
 			requests: resources.Requests{
 				corev1.ResourceCPU: 1000,
 			},
-			count:                     1,
-			wantReason:                "no topology domains at level: kubernetes.io/hostname",
-			enableTASMostFreeCapacity: true,
+			count:              1,
+			wantReason:         "no topology domains at level: kubernetes.io/hostname",
+			enableFeatureGates: []featuregate.Feature{features.TASMostFreeCapacity},
 		},
 		"only nodes with matching labels are considered; matching node is found; MostFreeCapacity": {
 			nodes: []corev1.Node{
@@ -995,7 +1110,7 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: true,
+			enableFeatureGates: []featuregate.Feature{features.TASMostFreeCapacity},
 		},
 		"only nodes with matching levels are considered; no host label on node; MostFreeCapacity": {
 			nodes: []corev1.Node{
@@ -1018,9 +1133,9 @@ func TestFindTopologyAssignment(t *testing.T) {
 			requests: resources.Requests{
 				corev1.ResourceCPU: 1000,
 			},
-			count:                     1,
-			wantReason:                "no topology domains at level: cloud.com/topology-rack",
-			enableTASMostFreeCapacity: true,
+			count:              1,
+			wantReason:         "no topology domains at level: cloud.com/topology-rack",
+			enableFeatureGates: []featuregate.Feature{features.TASMostFreeCapacity},
 		},
 		"don't consider unscheduled Pods when computing capacity; MostFreeCapacity": {
 			// the Pod is not scheduled (no NodeName set, so is not blocking capacity)
@@ -1059,7 +1174,7 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: true,
+			enableFeatureGates: []featuregate.Feature{features.TASMostFreeCapacity},
 		},
 		"don't consider terminal pods when computing the capacity; MostFreeCapacity": {
 			nodes: []corev1.Node{
@@ -1102,7 +1217,7 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: true,
+			enableFeatureGates: []featuregate.Feature{features.TASMostFreeCapacity},
 		},
 		"include usage from pending scheduled non-TAS pods, blocked assignment; MostFreeCapacity": {
 			// there is not enough free capacity on the only node x1
@@ -1130,9 +1245,8 @@ func TestFindTopologyAssignment(t *testing.T) {
 			requests: resources.Requests{
 				corev1.ResourceCPU: 600,
 			},
-			count:                     1,
-			wantReason:                `topology "default" doesn't allow to fit any of 1 pod(s)`,
-			enableTASMostFreeCapacity: true,
+			count:      1,
+			wantReason: `topology "default" doesn't allow to fit any of 1 pod(s)`,
 		},
 		"include usage from running non-TAS pods, blocked assignment; MostFreeCapacity": {
 			// there is not enough free capacity on the only node x1
@@ -1160,9 +1274,9 @@ func TestFindTopologyAssignment(t *testing.T) {
 			requests: resources.Requests{
 				corev1.ResourceCPU: 600,
 			},
-			count:                     1,
-			wantReason:                `topology "default" doesn't allow to fit any of 1 pod(s)`,
-			enableTASMostFreeCapacity: true,
+			count:              1,
+			wantReason:         `topology "default" doesn't allow to fit any of 1 pod(s)`,
+			enableFeatureGates: []featuregate.Feature{features.TASMostFreeCapacity},
 		},
 		"include usage from running non-TAS pods, found free capacity on another node; MostFreeCapacity": {
 			// there is not enough free capacity on the node x1 as the
@@ -1211,7 +1325,7 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: true,
+			enableFeatureGates: []featuregate.Feature{features.TASMostFreeCapacity},
 		},
 		"no assignment as node is not ready; MostFreeCapacity": {
 			nodes: []corev1.Node{
@@ -1240,9 +1354,9 @@ func TestFindTopologyAssignment(t *testing.T) {
 			requests: resources.Requests{
 				corev1.ResourceCPU: 1000,
 			},
-			count:                     1,
-			wantReason:                "no topology domains at level: kubernetes.io/hostname",
-			enableTASMostFreeCapacity: true,
+			count:              1,
+			wantReason:         "no topology domains at level: kubernetes.io/hostname",
+			enableFeatureGates: []featuregate.Feature{features.TASMostFreeCapacity},
 		},
 		"no assignment as node is unschedulable; MostFreeCapacity": {
 			nodes: []corev1.Node{
@@ -1268,9 +1382,9 @@ func TestFindTopologyAssignment(t *testing.T) {
 			requests: resources.Requests{
 				corev1.ResourceCPU: 1000,
 			},
-			count:                     1,
-			wantReason:                "no topology domains at level: kubernetes.io/hostname",
-			enableTASMostFreeCapacity: true,
+			count:              1,
+			wantReason:         "no topology domains at level: kubernetes.io/hostname",
+			enableFeatureGates: []featuregate.Feature{features.TASMostFreeCapacity},
 		},
 		"skip node which has untolerated taint; MostFreeCapacity": {
 			nodes: []corev1.Node{
@@ -1300,9 +1414,9 @@ func TestFindTopologyAssignment(t *testing.T) {
 			requests: resources.Requests{
 				corev1.ResourceCPU: 1000,
 			},
-			count:                     1,
-			wantReason:                `topology "default" doesn't allow to fit any of 1 pod(s)`,
-			enableTASMostFreeCapacity: true,
+			count:              1,
+			wantReason:         `topology "default" doesn't allow to fit any of 1 pod(s)`,
+			enableFeatureGates: []featuregate.Feature{features.TASMostFreeCapacity},
 		},
 		"allow to schedule on node with tolerated taint; MostFreeCapacity": {
 			nodes: []corev1.Node{
@@ -1351,7 +1465,7 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: true,
+			enableFeatureGates: []featuregate.Feature{features.TASMostFreeCapacity},
 		},
 		"no assignment as node does not have enough allocatable pods (.status.allocatable['pods']); MostFreeCapacity": {
 			nodes: []corev1.Node{
@@ -1382,16 +1496,18 @@ func TestFindTopologyAssignment(t *testing.T) {
 			requests: resources.Requests{
 				corev1.ResourceCPU: 300,
 			},
-			count:                     1,
-			wantReason:                `topology "default" doesn't allow to fit any of 1 pod(s)`,
-			enableTASMostFreeCapacity: true,
+			count:              1,
+			wantReason:         `topology "default" doesn't allow to fit any of 1 pod(s)`,
+			enableFeatureGates: []featuregate.Feature{features.TASMostFreeCapacity},
 		},
 	}
 	for name, tc := range cases {
 		t.Run(name, func(t *testing.T) {
 			ctx, _ := utiltesting.ContextWithLog(t)
-			// TODO: remove after dropping the TASMostFreeCapacity feature gate
-			features.SetFeatureGateDuringTest(t, features.TASMostFreeCapacity, tc.enableTASMostFreeCapacity)
+			// TODO: remove after dropping the TAS profiles feature gates
+			for _, gate := range tc.enableFeatureGates {
+				features.SetFeatureGateDuringTest(t, gate, true)
+			}
 
 			initialObjects := make([]client.Object, 0)
 			for i := range tc.nodes {
diff --git a/pkg/cache/tas_flavor_snapshot.go b/pkg/cache/tas_flavor_snapshot.go
index 358d4ce91c7..2a56f7912d3 100644
--- a/pkg/cache/tas_flavor_snapshot.go
+++ b/pkg/cache/tas_flavor_snapshot.go
@@ -414,6 +414,7 @@ func (s *TASFlavorSnapshot) findTopologyAssignment(
 	count := tasPodSetRequests.Count
 	required := isRequired(tasPodSetRequests.PodSet.TopologyRequest)
 	key := s.levelKeyWithImpliedFallback(&tasPodSetRequests)
+	unconstrained := isUnconstrained(tasPodSetRequests.PodSet.TopologyRequest)
 	if key == nil {
 		return nil, "topology level not specified"
 	}
@@ -426,24 +427,25 @@ func (s *TASFlavorSnapshot) findTopologyAssignment(
 
 	// phase 2a: determine the level at which the assignment is done along with
 	// the domains which can accommodate all pods
-	fitLevelIdx, currFitDomain, reason := s.findLevelWithFitDomains(levelIdx, required, count)
+	fitLevelIdx, currFitDomain, reason := s.findLevelWithFitDomains(levelIdx, required, count, unconstrained)
 	if len(reason) > 0 {
 		return nil, reason
 	}
 
 	// phase 2b: traverse the tree down level-by-level optimizing the number of
 	// topology domains at each level
-	currFitDomain = s.updateCountsToMinimum(currFitDomain, count)
+	// if unconstrained is set, we'll only do it once
+	currFitDomain = s.updateCountsToMinimum(currFitDomain, count, unconstrained)
 	for levelIdx := fitLevelIdx; levelIdx+1 < len(s.domainsPerLevel); levelIdx++ {
 		lowerFitDomains := s.lowerLevelDomains(currFitDomain)
 		sortedLowerDomains := s.sortedDomains(lowerFitDomains)
-		currFitDomain = s.updateCountsToMinimum(sortedLowerDomains, count)
+		currFitDomain = s.updateCountsToMinimum(sortedLowerDomains, count, unconstrained)
 	}
 	return s.buildAssignment(currFitDomain), ""
 }
 
 func (s *TASFlavorSnapshot) HasLevel(r *kueue.PodSetTopologyRequest) bool {
-	key := levelKey(r)
+	key := s.levelKey(r)
 	if key == nil {
 		return false
 	}
@@ -464,7 +466,7 @@ func isRequired(tr *kueue.PodSetTopologyRequest) bool {
 }
 
 func (s *TASFlavorSnapshot) levelKeyWithImpliedFallback(tasRequests *TASPodSetRequests) *string {
-	if key := levelKey(tasRequests.PodSet.TopologyRequest); key != nil {
+	if key := s.levelKey(tasRequests.PodSet.TopologyRequest); key != nil {
 		return key
 	}
 	if tasRequests.Implied {
@@ -473,16 +475,24 @@ func (s *TASFlavorSnapshot) levelKeyWithImpliedFallback(tasRequests *TASPodSetRe
 	return nil
 }
 
-func levelKey(topologyRequest *kueue.PodSetTopologyRequest) *string {
+func (s *TASFlavorSnapshot) levelKey(topologyRequest *kueue.PodSetTopologyRequest) *string {
 	if topologyRequest == nil {
 		return nil
 	}
-	if topologyRequest.Required != nil {
+	switch {
+	case topologyRequest.Required != nil:
 		return topologyRequest.Required
-	} else if topologyRequest.Preferred != nil {
+	case topologyRequest.Preferred != nil:
 		return topologyRequest.Preferred
+	case isUnconstrained(topologyRequest):
+		return ptr.To(s.lowestLevel())
+	default:
+		return nil
 	}
-	return nil
+}
+
+func isUnconstrained(tr *kueue.PodSetTopologyRequest) bool {
+	return (tr != nil && tr.Unconstrained != nil && *tr.Unconstrained) || features.Enabled(features.TASImplicitDefaultUnconstrained)
 }
 
 // findBestFitDomainIdx finds an index of the first domain with the lowest
@@ -501,7 +511,7 @@ func findBestFitDomainIdx(domains []*domain, count int32) int {
 	return bestFitIdx
 }
 
-func (s *TASFlavorSnapshot) findLevelWithFitDomains(levelIdx int, required bool, count int32) (int, []*domain, string) {
+func (s *TASFlavorSnapshot) findLevelWithFitDomains(levelIdx int, required bool, count int32, unconstrained bool) (int, []*domain, string) {
 	domains := s.domainsPerLevel[levelIdx]
 	if len(domains) == 0 {
 		return 0, nil, fmt.Sprintf("no topology domains at level: %s", s.levelKeys[levelIdx])
@@ -510,20 +520,22 @@ func (s *TASFlavorSnapshot) findLevelWithFitDomains(levelIdx int, required bool,
 	sortedDomain := s.sortedDomains(levelDomains)
 	topDomain := sortedDomain[0]
 	if !features.Enabled(features.TASMostFreeCapacity) && topDomain.state >= count {
+		// optimize the potentially last domain
 		topDomain = sortedDomain[findBestFitDomainIdx(sortedDomain, count)]
 	}
 	if topDomain.state < count {
 		if required {
 			return 0, nil, s.notFitMessage(topDomain.state, count)
 		}
-		if levelIdx > 0 {
-			return s.findLevelWithFitDomains(levelIdx-1, required, count)
+		if levelIdx > 0 && !unconstrained {
+			return s.findLevelWithFitDomains(levelIdx-1, required, count, unconstrained)
 		}
 		results := []*domain{}
 		remainingCount := count
 		for idx := 0; remainingCount > 0 && idx < len(sortedDomain) && sortedDomain[idx].state > 0; idx++ {
 			offset := 0
 			if !features.Enabled(features.TASMostFreeCapacity) && sortedDomain[idx].state >= remainingCount {
+				// optimize the last domain
 				offset = findBestFitDomainIdx(sortedDomain[idx:], remainingCount)
 			}
 			results = append(results, sortedDomain[idx+offset])
@@ -532,18 +544,19 @@ func (s *TASFlavorSnapshot) findLevelWithFitDomains(levelIdx int, required bool,
 		if remainingCount > 0 {
 			return 0, nil, s.notFitMessage(count-remainingCount, count)
 		}
-		return 0, results, ""
+		return levelIdx, results, ""
 	}
 	return levelIdx, []*domain{topDomain}, ""
 }
 
-func (s *TASFlavorSnapshot) updateCountsToMinimum(domains []*domain, count int32) []*domain {
+func (s *TASFlavorSnapshot) updateCountsToMinimum(domains []*domain, count int32, unconstrained bool) []*domain {
 	result := make([]*domain, 0)
 	remainingCount := count
 	for i, domain := range domains {
 		if !features.Enabled(features.TASMostFreeCapacity) && domain.state >= remainingCount {
-			bestFitIdx := findBestFitDomainIdx(domains[i:], remainingCount)
-			domain = domains[i+bestFitIdx]
+			// optimize the last domain
+			mostAllocatedIdx := findBestFitDomainIdx(domains[i:], remainingCount)
+			domain = domains[i+mostAllocatedIdx]
 		}
 
 		if domain.state >= remainingCount {
diff --git a/pkg/controller/jobframework/tas.go b/pkg/controller/jobframework/tas.go
index 9cebfd4d40a..e08a0b9a2fa 100644
--- a/pkg/controller/jobframework/tas.go
+++ b/pkg/controller/jobframework/tas.go
@@ -17,6 +17,8 @@ limitations under the License.
 package jobframework
 
 import (
+	"strconv"
+
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 
 	kueuealpha "sigs.k8s.io/kueue/apis/kueue/v1alpha1"
@@ -26,17 +28,22 @@ import (
 func PodSetTopologyRequest(meta *metav1.ObjectMeta, podIndexLabel *string, subGroupIndexLabel *string, subGroupCount *int32) *kueue.PodSetTopologyRequest {
 	requiredValue, requiredFound := meta.Annotations[kueuealpha.PodSetRequiredTopologyAnnotation]
 	preferredValue, preferredFound := meta.Annotations[kueuealpha.PodSetPreferredTopologyAnnotation]
+	unconstrained, unconstrainedFound := meta.Annotations[kueuealpha.PodSetUnconstrainedTopologyAnnotation]
 
-	if requiredFound || preferredFound {
+	if requiredFound || preferredFound || unconstrainedFound {
 		psTopologyReq := &kueue.PodSetTopologyRequest{
 			PodIndexLabel:      podIndexLabel,
 			SubGroupIndexLabel: subGroupIndexLabel,
 			SubGroupCount:      subGroupCount,
 		}
-		if requiredFound {
+		switch {
+		case requiredFound:
 			psTopologyReq.Required = &requiredValue
-		} else {
+		case preferredFound:
 			psTopologyReq.Preferred = &preferredValue
+		case unconstrainedFound:
+			unconstrained, _ := strconv.ParseBool(unconstrained)
+			psTopologyReq.Unconstrained = &unconstrained
 		}
 		return psTopologyReq
 	}
diff --git a/pkg/controller/jobframework/tas_validation.go b/pkg/controller/jobframework/tas_validation.go
index 5a672381ec7..a94c11c5a20 100644
--- a/pkg/controller/jobframework/tas_validation.go
+++ b/pkg/controller/jobframework/tas_validation.go
@@ -30,12 +30,20 @@ func ValidateTASPodSetRequest(replicaPath *field.Path, replicaMetadata *metav1.O
 	var allErrs field.ErrorList
 	requiredValue, requiredFound := replicaMetadata.Annotations[kueuealpha.PodSetRequiredTopologyAnnotation]
 	preferredValue, preferredFound := replicaMetadata.Annotations[kueuealpha.PodSetPreferredTopologyAnnotation]
+	_, unconstrainedFound := replicaMetadata.Annotations[kueuealpha.PodSetUnconstrainedTopologyAnnotation]
+	annotationFoundCount := 0
+	for _, found := range []bool{requiredFound, preferredFound, unconstrainedFound} {
+		if found {
+			annotationFoundCount++
+		}
+	}
 	annotationsPath := replicaPath.Child("annotations")
-	if requiredFound && preferredFound {
+	if annotationFoundCount > 1 {
 		allErrs = append(allErrs, field.Invalid(annotationsPath, field.OmitValueType{},
-			fmt.Sprintf("must not contain both %q and %q",
+			fmt.Sprintf("must not contain more than one topology annotation: [%q, %q, %q]",
 				kueuealpha.PodSetRequiredTopologyAnnotation,
-				kueuealpha.PodSetPreferredTopologyAnnotation),
+				kueuealpha.PodSetPreferredTopologyAnnotation,
+				kueuealpha.PodSetUnconstrainedTopologyAnnotation),
 		))
 	}
 	if requiredFound {
diff --git a/pkg/controller/jobs/job/job_webhook_test.go b/pkg/controller/jobs/job/job_webhook_test.go
index d7c8f8cc8ee..f9fd1b802d5 100644
--- a/pkg/controller/jobs/job/job_webhook_test.go
+++ b/pkg/controller/jobs/job/job_webhook_test.go
@@ -252,7 +252,8 @@ func TestValidateCreate(t *testing.T) {
 				Obj(),
 			wantErr: field.ErrorList{
 				field.Invalid(replicaMetaPath.Child("annotations"), field.OmitValueType{},
-					`must not contain both "kueue.x-k8s.io/podset-required-topology" and "kueue.x-k8s.io/podset-preferred-topology"`),
+					`must not contain more than one topology annotation: ["kueue.x-k8s.io/podset-required-topology", `+
+						`"kueue.x-k8s.io/podset-preferred-topology", "kueue.x-k8s.io/podset-unconstrained-topology"]`),
 			},
 		},
 		{
@@ -531,8 +532,8 @@ func TestValidateUpdate(t *testing.T) {
 				Obj(),
 			wantErr: field.ErrorList{
 				field.Invalid(replicaMetaPath.Child("annotations"), field.OmitValueType{},
-					`must not contain both "kueue.x-k8s.io/podset-required-topology" and "kueue.x-k8s.io/podset-preferred-topology"`),
-			},
+					`must not contain more than one topology annotation: ["kueue.x-k8s.io/podset-required-topology", `+
+						`"kueue.x-k8s.io/podset-preferred-topology", "kueue.x-k8s.io/podset-unconstrained-topology"]`)},
 		},
 	}
 
diff --git a/pkg/controller/jobs/jobset/jobset_webhook_test.go b/pkg/controller/jobs/jobset/jobset_webhook_test.go
index 3f4df608005..91e3f15bb3b 100644
--- a/pkg/controller/jobs/jobset/jobset_webhook_test.go
+++ b/pkg/controller/jobs/jobset/jobset_webhook_test.go
@@ -98,7 +98,8 @@ func TestValidateCreate(t *testing.T) {
 				},
 			}).Obj(),
 			wantErr: field.ErrorList{field.Invalid(field.NewPath("spec.replicatedJobs[1].template.metadata.annotations"),
-				field.OmitValueType{}, `must not contain both "kueue.x-k8s.io/podset-required-topology" and "kueue.x-k8s.io/podset-preferred-topology"`)}.ToAggregate(),
+				field.OmitValueType{}, `must not contain more than one topology annotation: ["kueue.x-k8s.io/podset-required-topology", `+
+					`"kueue.x-k8s.io/podset-preferred-topology", "kueue.x-k8s.io/podset-unconstrained-topology"]`)}.ToAggregate(),
 		},
 	}
 
@@ -148,7 +149,8 @@ func TestValidateUpdate(t *testing.T) {
 				},
 			}).Obj(),
 			wantErr: field.ErrorList{field.Invalid(field.NewPath("spec.replicatedJobs[0].template.metadata.annotations"),
-				field.OmitValueType{}, `must not contain both "kueue.x-k8s.io/podset-required-topology" and "kueue.x-k8s.io/podset-preferred-topology"`)},
+				field.OmitValueType{}, `must not contain more than one topology annotation: ["kueue.x-k8s.io/podset-required-topology", `+
+					`"kueue.x-k8s.io/podset-preferred-topology", "kueue.x-k8s.io/podset-unconstrained-topology"]`)},
 		},
 	}
 
diff --git a/pkg/controller/jobs/kubeflow/jobs/paddlejob/paddlejob_controller_test.go b/pkg/controller/jobs/kubeflow/jobs/paddlejob/paddlejob_controller_test.go
index 86941e19910..8deb25c654f 100644
--- a/pkg/controller/jobs/kubeflow/jobs/paddlejob/paddlejob_controller_test.go
+++ b/pkg/controller/jobs/kubeflow/jobs/paddlejob/paddlejob_controller_test.go
@@ -365,15 +365,15 @@ func TestValidate(t *testing.T) {
 						Key("Master").
 						Child("template", "metadata", "annotations"),
 					field.OmitValueType{},
-					`must not contain both "kueue.x-k8s.io/podset-required-topology" and "kueue.x-k8s.io/podset-preferred-topology"`,
-				),
+					`must not contain more than one topology annotation: ["kueue.x-k8s.io/podset-required-topology", `+
+						`"kueue.x-k8s.io/podset-preferred-topology", "kueue.x-k8s.io/podset-unconstrained-topology"]`),
 				field.Invalid(
 					field.NewPath("spec", "paddleReplicaSpecs").
 						Key("Worker").
 						Child("template", "metadata", "annotations"),
 					field.OmitValueType{},
-					`must not contain both "kueue.x-k8s.io/podset-required-topology" and "kueue.x-k8s.io/podset-preferred-topology"`,
-				),
+					`must not contain more than one topology annotation: ["kueue.x-k8s.io/podset-required-topology", `+
+						`"kueue.x-k8s.io/podset-preferred-topology", "kueue.x-k8s.io/podset-unconstrained-topology"]`),
 			},
 		},
 	}
diff --git a/pkg/controller/jobs/kubeflow/jobs/pytorchjob/pytorchjob_controller_test.go b/pkg/controller/jobs/kubeflow/jobs/pytorchjob/pytorchjob_controller_test.go
index 2a43e579e05..6d5a661c8a9 100644
--- a/pkg/controller/jobs/kubeflow/jobs/pytorchjob/pytorchjob_controller_test.go
+++ b/pkg/controller/jobs/kubeflow/jobs/pytorchjob/pytorchjob_controller_test.go
@@ -368,15 +368,15 @@ func TestValidate(t *testing.T) {
 						Key("Master").
 						Child("template", "metadata", "annotations"),
 					field.OmitValueType{},
-					`must not contain both "kueue.x-k8s.io/podset-required-topology" and "kueue.x-k8s.io/podset-preferred-topology"`,
-				),
+					`must not contain more than one topology annotation: ["kueue.x-k8s.io/podset-required-topology", `+
+						`"kueue.x-k8s.io/podset-preferred-topology", "kueue.x-k8s.io/podset-unconstrained-topology"]`),
 				field.Invalid(
 					field.NewPath("spec", "pytorchReplicaSpecs").
 						Key("Worker").
 						Child("template", "metadata", "annotations"),
 					field.OmitValueType{},
-					`must not contain both "kueue.x-k8s.io/podset-required-topology" and "kueue.x-k8s.io/podset-preferred-topology"`,
-				),
+					`must not contain more than one topology annotation: ["kueue.x-k8s.io/podset-required-topology", `+
+						`"kueue.x-k8s.io/podset-preferred-topology", "kueue.x-k8s.io/podset-unconstrained-topology"]`),
 			},
 		},
 	}
diff --git a/pkg/controller/jobs/kubeflow/jobs/tfjob/tfjob_controller_test.go b/pkg/controller/jobs/kubeflow/jobs/tfjob/tfjob_controller_test.go
index c496ceb4ac1..dab1a8d3e53 100644
--- a/pkg/controller/jobs/kubeflow/jobs/tfjob/tfjob_controller_test.go
+++ b/pkg/controller/jobs/kubeflow/jobs/tfjob/tfjob_controller_test.go
@@ -385,15 +385,15 @@ func TestValidate(t *testing.T) {
 						Key("Chief").
 						Child("template", "metadata", "annotations"),
 					field.OmitValueType{},
-					`must not contain both "kueue.x-k8s.io/podset-required-topology" and "kueue.x-k8s.io/podset-preferred-topology"`,
-				),
+					`must not contain more than one topology annotation: ["kueue.x-k8s.io/podset-required-topology", `+
+						`"kueue.x-k8s.io/podset-preferred-topology", "kueue.x-k8s.io/podset-unconstrained-topology"]`),
 				field.Invalid(
 					field.NewPath("spec", "tfReplicaSpecs").
 						Key("PS").
 						Child("template", "metadata", "annotations"),
 					field.OmitValueType{},
-					`must not contain both "kueue.x-k8s.io/podset-required-topology" and "kueue.x-k8s.io/podset-preferred-topology"`,
-				),
+					`must not contain more than one topology annotation: ["kueue.x-k8s.io/podset-required-topology", `+
+						`"kueue.x-k8s.io/podset-preferred-topology", "kueue.x-k8s.io/podset-unconstrained-topology"]`),
 			},
 		},
 	}
diff --git a/pkg/controller/jobs/kubeflow/jobs/xgboostjob/xgboostjob_controller_test.go b/pkg/controller/jobs/kubeflow/jobs/xgboostjob/xgboostjob_controller_test.go
index a9c1307626c..e5b817afafb 100644
--- a/pkg/controller/jobs/kubeflow/jobs/xgboostjob/xgboostjob_controller_test.go
+++ b/pkg/controller/jobs/kubeflow/jobs/xgboostjob/xgboostjob_controller_test.go
@@ -374,15 +374,15 @@ func TestValidate(t *testing.T) {
 						Key("Master").
 						Child("template", "metadata", "annotations"),
 					field.OmitValueType{},
-					`must not contain both "kueue.x-k8s.io/podset-required-topology" and "kueue.x-k8s.io/podset-preferred-topology"`,
-				),
+					`must not contain more than one topology annotation: ["kueue.x-k8s.io/podset-required-topology", `+
+						`"kueue.x-k8s.io/podset-preferred-topology", "kueue.x-k8s.io/podset-unconstrained-topology"]`),
 				field.Invalid(
 					field.NewPath("spec", "xgbReplicaSpecs").
 						Key("Worker").
 						Child("template", "metadata", "annotations"),
 					field.OmitValueType{},
-					`must not contain both "kueue.x-k8s.io/podset-required-topology" and "kueue.x-k8s.io/podset-preferred-topology"`,
-				),
+					`must not contain more than one topology annotation: ["kueue.x-k8s.io/podset-required-topology", `+
+						`"kueue.x-k8s.io/podset-preferred-topology", "kueue.x-k8s.io/podset-unconstrained-topology"]`),
 			},
 		},
 	}
diff --git a/pkg/controller/jobs/mpijob/mpijob_webhook_test.go b/pkg/controller/jobs/mpijob/mpijob_webhook_test.go
index 61c0f8356a9..0e0fb062089 100644
--- a/pkg/controller/jobs/mpijob/mpijob_webhook_test.go
+++ b/pkg/controller/jobs/mpijob/mpijob_webhook_test.go
@@ -110,13 +110,13 @@ func TestValidateCreate(t *testing.T) {
 				field.Invalid(
 					field.NewPath("spec.mpiReplicaSpecs[Launcher].template.metadata.annotations"),
 					field.OmitValueType{},
-					`must not contain both "kueue.x-k8s.io/podset-required-topology" and "kueue.x-k8s.io/podset-preferred-topology"`,
-				),
+					`must not contain more than one topology annotation: ["kueue.x-k8s.io/podset-required-topology", `+
+						`"kueue.x-k8s.io/podset-preferred-topology", "kueue.x-k8s.io/podset-unconstrained-topology"]`),
 				field.Invalid(
 					field.NewPath("spec.mpiReplicaSpecs[Worker].template.metadata.annotations"),
 					field.OmitValueType{},
-					`must not contain both "kueue.x-k8s.io/podset-required-topology" and "kueue.x-k8s.io/podset-preferred-topology"`,
-				),
+					`must not contain more than one topology annotation: ["kueue.x-k8s.io/podset-required-topology", `+
+						`"kueue.x-k8s.io/podset-preferred-topology", "kueue.x-k8s.io/podset-unconstrained-topology"]`),
 			}.ToAggregate(),
 		},
 	}
diff --git a/pkg/controller/jobs/raycluster/raycluster_webhook_test.go b/pkg/controller/jobs/raycluster/raycluster_webhook_test.go
index 02884ab9f93..2c55411ef50 100644
--- a/pkg/controller/jobs/raycluster/raycluster_webhook_test.go
+++ b/pkg/controller/jobs/raycluster/raycluster_webhook_test.go
@@ -240,13 +240,13 @@ func TestValidateCreate(t *testing.T) {
 				field.Invalid(
 					field.NewPath("spec.headGroupSpec.template, metadata.annotations"),
 					field.OmitValueType{},
-					`must not contain both "kueue.x-k8s.io/podset-required-topology" and "kueue.x-k8s.io/podset-preferred-topology"`,
-				),
+					`must not contain more than one topology annotation: ["kueue.x-k8s.io/podset-required-topology", `+
+						`"kueue.x-k8s.io/podset-preferred-topology", "kueue.x-k8s.io/podset-unconstrained-topology"]`),
 				field.Invalid(
 					field.NewPath("spec.workerGroupSpecs[0].template.metadata.annotations"),
 					field.OmitValueType{},
-					`must not contain both "kueue.x-k8s.io/podset-required-topology" and "kueue.x-k8s.io/podset-preferred-topology"`,
-				),
+					`must not contain more than one topology annotation: ["kueue.x-k8s.io/podset-required-topology", `+
+						`"kueue.x-k8s.io/podset-preferred-topology", "kueue.x-k8s.io/podset-unconstrained-topology"]`),
 			}.ToAggregate(),
 		},
 	}
diff --git a/pkg/controller/jobs/rayjob/rayjob_webhook_test.go b/pkg/controller/jobs/rayjob/rayjob_webhook_test.go
index 92873ac90e6..e34c6ac55fd 100644
--- a/pkg/controller/jobs/rayjob/rayjob_webhook_test.go
+++ b/pkg/controller/jobs/rayjob/rayjob_webhook_test.go
@@ -267,13 +267,13 @@ func TestValidateCreate(t *testing.T) {
 				field.Invalid(
 					field.NewPath("spec.rayClusterSpec.headGroupSpec.template, metadata.annotations"),
 					field.OmitValueType{},
-					`must not contain both "kueue.x-k8s.io/podset-required-topology" and "kueue.x-k8s.io/podset-preferred-topology"`,
-				),
+					`must not contain more than one topology annotation: ["kueue.x-k8s.io/podset-required-topology", `+
+						`"kueue.x-k8s.io/podset-preferred-topology", "kueue.x-k8s.io/podset-unconstrained-topology"]`),
 				field.Invalid(
 					field.NewPath("spec.rayClusterSpec.workerGroupSpecs[0].template.metadata.annotations"),
 					field.OmitValueType{},
-					`must not contain both "kueue.x-k8s.io/podset-required-topology" and "kueue.x-k8s.io/podset-preferred-topology"`,
-				),
+					`must not contain more than one topology annotation: ["kueue.x-k8s.io/podset-required-topology", `+
+						`"kueue.x-k8s.io/podset-preferred-topology", "kueue.x-k8s.io/podset-unconstrained-topology"]`),
 			}.ToAggregate(),
 		},
 	}
diff --git a/pkg/features/kube_features.go b/pkg/features/kube_features.go
index 4227e94c242..133b34d43de 100644
--- a/pkg/features/kube_features.go
+++ b/pkg/features/kube_features.go
@@ -151,6 +151,12 @@ const (
 	//
 	// Enable to set use LeastAlloactedFit algorithm for TAS
 	TASMostFreeCapacity featuregate.Feature = "TASMostFreeCapacity"
+
+	// owner: @pbundyra
+	// kep: https://github.com/kubernetes-sigs/kueue/tree/main/keps/2724-topology-aware-scheduling
+	//
+	// Enable to set implicit PodSetTopologyRequeste default to `.unconstrained=&true`
+	TASImplicitDefaultUnconstrained featuregate.Feature = "TASImplicitDefaultUnconstrained"
 )
 
 func init() {
@@ -234,6 +240,9 @@ var defaultVersionedFeatureGates = map[featuregate.Feature]featuregate.Versioned
 	TASMostFreeCapacity: {
 		{Version: version.MustParse("0.11"), Default: false, PreRelease: featuregate.Deprecated},
 	},
+	TASImplicitDefaultUnconstrained: {
+		{Version: version.MustParse("0.11"), Default: false, PreRelease: featuregate.Alpha},
+	},
 }
 
 func SetFeatureGateDuringTest(tb testing.TB, f featuregate.Feature, value bool) {
diff --git a/site/content/en/docs/reference/kueue.v1beta1.md b/site/content/en/docs/reference/kueue.v1beta1.md
index b922e38762b..d9975242afd 100644
--- a/site/content/en/docs/reference/kueue.v1beta1.md
+++ b/site/content/en/docs/reference/kueue.v1beta1.md
@@ -1832,6 +1832,15 @@ indicated by the <code>kueue.x-k8s.io/podset-preferred-topology</code> PodSet
 annotation.</p>
 </td>
 </tr>
+<tr><td><code>unconstrained</code><br/>
+<code>bool</code>
+</td>
+<td>
+   <p>unconstrained indicates that Kueue has the freedom to schedule the PodSet within
+the entire available capacity, without constraints on the compactness of the placement.
+This is indicated by the <code>kueue.x-k8s.io/podset-unconstrained-topology</code> PodSet annotation.</p>
+</td>
+</tr>
 <tr><td><code>podIndexLabel</code> <B>[Required]</B><br/>
 <code>string</code>
 </td>
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 a21cdac267d..04489419835 100644
--- a/test/integration/singlecluster/controller/jobs/job/job_controller_test.go
+++ b/test/integration/singlecluster/controller/jobs/job/job_controller_test.go
@@ -2602,6 +2602,7 @@ var _ = ginkgo.Describe("Job controller when TopologyAwareScheduling enabled", g
 		util.ExpectObjectToBeDeleted(ctx, k8sClient, clusterQueue, true)
 		util.ExpectObjectToBeDeleted(ctx, k8sClient, tasFlavor, true)
 		util.ExpectObjectToBeDeleted(ctx, k8sClient, topology, true)
+		features.SetFeatureGateDuringTest(ginkgo.GinkgoTB(), features.TASImplicitDefaultUnconstrained, false)
 		for _, node := range nodes {
 			util.ExpectObjectToBeDeleted(ctx, k8sClient, &node, true)
 		}
@@ -2655,4 +2656,105 @@ var _ = ginkgo.Describe("Job controller when TopologyAwareScheduling enabled", g
 			}, util.Timeout, util.Interval).Should(gomega.Succeed())
 		})
 	})
+
+	ginkgo.It("should admit workload with topology unconstrained annotation which fits", func() {
+		job := testingjob.MakeJob("job", ns.Name).
+			Queue(localQueue.Name).
+			PodAnnotation(kueuealpha.PodSetUnconstrainedTopologyAnnotation, "true").
+			Request(corev1.ResourceCPU, "1").
+			Obj()
+		ginkgo.By("creating a job", func() {
+			gomega.Expect(k8sClient.Create(ctx, job)).Should(gomega.Succeed())
+		})
+
+		wl := &kueue.Workload{}
+		wlLookupKey := types.NamespacedName{Name: workloadjob.GetWorkloadNameForJob(job.Name, job.UID), Namespace: ns.Name}
+
+		ginkgo.By("verify the workload is created", func() {
+			gomega.Eventually(func(g gomega.Gomega) {
+				g.Expect(k8sClient.Get(ctx, wlLookupKey, wl)).Should(gomega.Succeed())
+				g.Expect(wl.Spec.PodSets).Should(gomega.BeComparableTo([]kueue.PodSet{{
+					Name:  kueue.DefaultPodSetName,
+					Count: 1,
+					TopologyRequest: &kueue.PodSetTopologyRequest{
+						Unconstrained: ptr.To(true),
+						PodIndexLabel: ptr.To(batchv1.JobCompletionIndexAnnotation),
+					},
+				}}, cmpopts.IgnoreFields(kueue.PodSet{}, "Template")))
+			}, util.Timeout, util.Interval).Should(gomega.Succeed())
+		})
+
+		ginkgo.By("verify the workload is admitted", func() {
+			gomega.Eventually(func(g gomega.Gomega) {
+				g.Expect(k8sClient.Get(ctx, wlLookupKey, wl)).Should(gomega.Succeed())
+			}, util.Timeout, util.Interval).Should(gomega.Succeed())
+
+			util.ExpectWorkloadsToBeAdmitted(ctx, k8sClient, wl)
+			util.ExpectReservingActiveWorkloadsMetric(clusterQueue, 1)
+		})
+
+		ginkgo.By("verify admission for the workload", func() {
+			wlLookupKey := types.NamespacedName{Name: workloadjob.GetWorkloadNameForJob(job.Name, job.UID), Namespace: ns.Name}
+			gomega.Eventually(func(g gomega.Gomega) {
+				g.Expect(k8sClient.Get(ctx, wlLookupKey, wl)).Should(gomega.Succeed())
+				g.Expect(wl.Status.Admission).ShouldNot(gomega.BeNil())
+				g.Expect(wl.Status.Admission.PodSetAssignments).Should(gomega.HaveLen(1))
+				g.Expect(wl.Status.Admission.PodSetAssignments[0].TopologyAssignment).Should(gomega.BeComparableTo(
+					&kueue.TopologyAssignment{
+						Levels:  []string{tasBlockLabel},
+						Domains: []kueue.TopologyDomainAssignment{{Count: 1, Values: []string{"b1"}}},
+					},
+				))
+			}, util.Timeout, util.Interval).Should(gomega.Succeed())
+		})
+	})
+
+	ginkgo.It("should implicitly default the .unconstrained field if the TASImplicitDefaultUnconstrained gate is set", func() {
+		features.SetFeatureGateDuringTest(ginkgo.GinkgoTB(), features.TASImplicitDefaultUnconstrained, true)
+
+		job := testingjob.MakeJob("job", ns.Name).
+			Queue(localQueue.Name).
+			Request(corev1.ResourceCPU, "1").
+			Obj()
+		ginkgo.By("creating a job", func() {
+			gomega.Expect(k8sClient.Create(ctx, job)).Should(gomega.Succeed())
+		})
+
+		wl := &kueue.Workload{}
+		wlLookupKey := types.NamespacedName{Name: workloadjob.GetWorkloadNameForJob(job.Name, job.UID), Namespace: ns.Name}
+
+		ginkgo.By("verify the workload is created without .unconstrained", func() {
+			gomega.Eventually(func(g gomega.Gomega) {
+				g.Expect(k8sClient.Get(ctx, wlLookupKey, wl)).Should(gomega.Succeed())
+				g.Expect(wl.Spec.PodSets).Should(gomega.BeComparableTo([]kueue.PodSet{{
+					Name:  kueue.DefaultPodSetName,
+					Count: 1,
+				}}, cmpopts.IgnoreFields(kueue.PodSet{}, "Template")))
+			}, util.Timeout, util.Interval).Should(gomega.Succeed())
+		})
+
+		ginkgo.By("verify the workload is admitted", func() {
+			gomega.Eventually(func(g gomega.Gomega) {
+				g.Expect(k8sClient.Get(ctx, wlLookupKey, wl)).Should(gomega.Succeed())
+			}, util.Timeout, util.Interval).Should(gomega.Succeed())
+
+			util.ExpectWorkloadsToBeAdmitted(ctx, k8sClient, wl)
+			util.ExpectReservingActiveWorkloadsMetric(clusterQueue, 1)
+		})
+
+		ginkgo.By("verify admission for the workload", func() {
+			wlLookupKey := types.NamespacedName{Name: workloadjob.GetWorkloadNameForJob(job.Name, job.UID), Namespace: ns.Name}
+			gomega.Eventually(func(g gomega.Gomega) {
+				g.Expect(k8sClient.Get(ctx, wlLookupKey, wl)).Should(gomega.Succeed())
+				g.Expect(wl.Status.Admission).ShouldNot(gomega.BeNil())
+				g.Expect(wl.Status.Admission.PodSetAssignments).Should(gomega.HaveLen(1))
+				g.Expect(wl.Status.Admission.PodSetAssignments[0].TopologyAssignment).Should(gomega.BeComparableTo(
+					&kueue.TopologyAssignment{
+						Levels:  []string{tasBlockLabel},
+						Domains: []kueue.TopologyDomainAssignment{{Count: 1, Values: []string{"b1"}}},
+					},
+				))
+			}, util.Timeout, util.Interval).Should(gomega.Succeed())
+		})
+	})
 })


Reviews:
user: login: mimowo
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T14:04:49Z
user: login: mimowo
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T14:05:51Z
user: login: PBundyra
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T14:14:09Z
user: login: PBundyra
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T14:14:14Z
user: login: mimowo
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T14:14:27Z
user: login: mimowo
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T14:26:38Z
user: login: mimowo
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T15:46:07Z
user: login: PBundyra
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T15:54:54Z
user: login: mwielgus
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T15:57:12Z
user: login: mwielgus
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T15:59:09Z
user: login: PBundyra
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T16:17:57Z
user: login: PBundyra
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T16:18:03Z
user: login: mimowo
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-13T08:13:22Z
user: login: mimowo
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-13T08:20:10Z
user: login: mimowo
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-13T08:22:21Z
user: login: mimowo
body: The implementation LGTM, but I would like to improve the testing:
1. adding integration tests for the feature gate seems too much, I would keep the "proper" pyramid and move as unit tests to "scheduler_test.go". Feel free to keep one integration test for the baseline scenario.
2. it is not clear to me if the asserts are functionalliy different than "preferred" would have returned. Adding unit tests which show the difference as discussed under the issue would be great, and add a comment why we observe the difference.
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-13T08:25:21Z
user: login: mimowo
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-13T09:38:10Z
user: login: PBundyra
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-13T10:18:05Z
user: login: PBundyra
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-13T10:19:00Z
user: login: PBundyra
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-13T10:20:19Z
user: login: PBundyra
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-13T10:24:35Z
user: login: mimowo
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-13T12:23:54Z
user: login: mimowo
body: /lgtm
/approve
Thanks!
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-13T12:24:06Z

Review comments:
diff_hunk: @@ -150,9 +150,7 @@ webhookService:
       protocol: TCP
       targetPort: 9443
   type: ClusterIP
-
path: charts/kueue/values.yaml
user: login: mimowo
body: nit, revert formatting changes of unrelated files
created_at: 2025-03-12T14:04:49Z
author_association: CONTRIBUTOR
diff_hunk: @@ -38,6 +38,16 @@ const (
 	// among multiple topology domains.
 	PodSetPreferredTopologyAnnotation = "kueue.x-k8s.io/podset-preferred-topology"
 
+	// PodSetUnconstrainedTopologyAnnotation indicates that a PodSet requires
+	// Topology Aware Scheduling, but it promotes filling up nodes in use over
+	// compact placement. The pods have lower chance of being scheduled on the same
+	// node, but it mitigates resource fragmentation, and can lead to better
+	// node utilization. Recommended for PodSets that don't require heave inter pod
path: apis/kueue/v1alpha1/tas_types.go
user: login: mimowo
body: This seems old, with typos like " require heave inter pod". Please align with KEP.
created_at: 2025-03-12T14:05:51Z
author_association: CONTRIBUTOR
diff_hunk: @@ -150,9 +150,7 @@ webhookService:
       protocol: TCP
       targetPort: 9443
   type: ClusterIP
-
path: charts/kueue/values.yaml
user: login: PBundyra
body: Done
created_at: 2025-03-12T14:14:09Z
author_association: CONTRIBUTOR
diff_hunk: @@ -38,6 +38,16 @@ const (
 	// among multiple topology domains.
 	PodSetPreferredTopologyAnnotation = "kueue.x-k8s.io/podset-preferred-topology"
 
+	// PodSetUnconstrainedTopologyAnnotation indicates that a PodSet requires
+	// Topology Aware Scheduling, but it promotes filling up nodes in use over
+	// compact placement. The pods have lower chance of being scheduled on the same
+	// node, but it mitigates resource fragmentation, and can lead to better
+	// node utilization. Recommended for PodSets that don't require heave inter pod
path: apis/kueue/v1alpha1/tas_types.go
user: login: PBundyra
body: Done
created_at: 2025-03-12T14:14:14Z
author_association: CONTRIBUTOR
diff_hunk: @@ -17,27 +17,38 @@ limitations under the License.
 package jobframework
 
 import (
+	"strconv"
+
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"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"
 )
 
 func PodSetTopologyRequest(meta *metav1.ObjectMeta, podIndexLabel *string, subGroupIndexLabel *string, subGroupCount *int32) *kueue.PodSetTopologyRequest {
 	requiredValue, requiredFound := meta.Annotations[kueuealpha.PodSetRequiredTopologyAnnotation]
 	preferredValue, preferredFound := meta.Annotations[kueuealpha.PodSetPreferredTopologyAnnotation]
+	unconstrained, unconstrainedFound := meta.Annotations[kueuealpha.PodSetUnconstrainedTopologyAnnotation]
 
-	if requiredFound || preferredFound {
+	if requiredFound || preferredFound || unconstrainedFound || features.Enabled(features.TASImplicitDefaultUnconstrained) {
 		psTopologyReq := &kueue.PodSetTopologyRequest{
 			PodIndexLabel:      podIndexLabel,
 			SubGroupIndexLabel: subGroupIndexLabel,
 			SubGroupCount:      subGroupCount,
 		}
 		if requiredFound {
 			psTopologyReq.Required = &requiredValue
-		} else {
+		} else if preferredFound {
 			psTopologyReq.Preferred = &preferredValue
 		}
+		if unconstrainedFound {
+			unconstrained, _ := strconv.ParseBool(unconstrained)
+			psTopologyReq.Unconstrained = &unconstrained
+		} else if features.Enabled(features.TASImplicitDefaultUnconstrained) {
+			psTopologyReq.Unconstrained = ptr.To(true)
path: pkg/controller/jobframework/tas.go
user: login: mimowo
body: Actually, this makes me wonder that https://github.com/kubernetes-sigs/kueue/pull/4556 has a bug, that the rank-based ordering would not work. 
created_at: 2025-03-12T14:14:27Z
author_association: CONTRIBUTOR
diff_hunk: @@ -17,27 +17,38 @@ limitations under the License.
 package jobframework
 
 import (
+	"strconv"
+
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"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"
 )
 
 func PodSetTopologyRequest(meta *metav1.ObjectMeta, podIndexLabel *string, subGroupIndexLabel *string, subGroupCount *int32) *kueue.PodSetTopologyRequest {
 	requiredValue, requiredFound := meta.Annotations[kueuealpha.PodSetRequiredTopologyAnnotation]
 	preferredValue, preferredFound := meta.Annotations[kueuealpha.PodSetPreferredTopologyAnnotation]
+	unconstrained, unconstrainedFound := meta.Annotations[kueuealpha.PodSetUnconstrainedTopologyAnnotation]
 
-	if requiredFound || preferredFound {
+	if requiredFound || preferredFound || unconstrainedFound || features.Enabled(features.TASImplicitDefaultUnconstrained) {
 		psTopologyReq := &kueue.PodSetTopologyRequest{
 			PodIndexLabel:      podIndexLabel,
 			SubGroupIndexLabel: subGroupIndexLabel,
 			SubGroupCount:      subGroupCount,
 		}
 		if requiredFound {
 			psTopologyReq.Required = &requiredValue
-		} else {
+		} else if preferredFound {
 			psTopologyReq.Preferred = &preferredValue
 		}
+		if unconstrainedFound {
+			unconstrained, _ := strconv.ParseBool(unconstrained)
+			psTopologyReq.Unconstrained = &unconstrained
+		} else if features.Enabled(features.TASImplicitDefaultUnconstrained) {
+			psTopologyReq.Unconstrained = ptr.To(true)
path: pkg/controller/jobframework/tas.go
user: login: mimowo
body: However, when the problem is fixed, I wouldn't default it here in a persistent fashion probably since the default is implicit.
created_at: 2025-03-12T14:26:38Z
author_association: CONTRIBUTOR
diff_hunk: @@ -17,27 +17,38 @@ limitations under the License.
 package jobframework
 
 import (
+	"strconv"
+
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"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"
 )
 
 func PodSetTopologyRequest(meta *metav1.ObjectMeta, podIndexLabel *string, subGroupIndexLabel *string, subGroupCount *int32) *kueue.PodSetTopologyRequest {
 	requiredValue, requiredFound := meta.Annotations[kueuealpha.PodSetRequiredTopologyAnnotation]
 	preferredValue, preferredFound := meta.Annotations[kueuealpha.PodSetPreferredTopologyAnnotation]
+	unconstrained, unconstrainedFound := meta.Annotations[kueuealpha.PodSetUnconstrainedTopologyAnnotation]
 
-	if requiredFound || preferredFound {
+	if requiredFound || preferredFound || unconstrainedFound || features.Enabled(features.TASImplicitDefaultUnconstrained) {
 		psTopologyReq := &kueue.PodSetTopologyRequest{
 			PodIndexLabel:      podIndexLabel,
 			SubGroupIndexLabel: subGroupIndexLabel,
 			SubGroupCount:      subGroupCount,
 		}
 		if requiredFound {
 			psTopologyReq.Required = &requiredValue
-		} else {
+		} else if preferredFound {
 			psTopologyReq.Preferred = &preferredValue
 		}
+		if unconstrainedFound {
+			unconstrained, _ := strconv.ParseBool(unconstrained)
+			psTopologyReq.Unconstrained = &unconstrained
+		} else if features.Enabled(features.TASImplicitDefaultUnconstrained) {
+			psTopologyReq.Unconstrained = ptr.To(true)
path: pkg/controller/jobframework/tas.go
user: login: mimowo
body: Ticketed: https://github.com/kubernetes-sigs/kueue/issues/4573

created_at: 2025-03-12T15:46:07Z
author_association: CONTRIBUTOR
diff_hunk: @@ -17,27 +17,38 @@ limitations under the License.
 package jobframework
 
 import (
+	"strconv"
+
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"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"
 )
 
 func PodSetTopologyRequest(meta *metav1.ObjectMeta, podIndexLabel *string, subGroupIndexLabel *string, subGroupCount *int32) *kueue.PodSetTopologyRequest {
 	requiredValue, requiredFound := meta.Annotations[kueuealpha.PodSetRequiredTopologyAnnotation]
 	preferredValue, preferredFound := meta.Annotations[kueuealpha.PodSetPreferredTopologyAnnotation]
+	unconstrained, unconstrainedFound := meta.Annotations[kueuealpha.PodSetUnconstrainedTopologyAnnotation]
 
-	if requiredFound || preferredFound {
+	if requiredFound || preferredFound || unconstrainedFound || features.Enabled(features.TASImplicitDefaultUnconstrained) {
 		psTopologyReq := &kueue.PodSetTopologyRequest{
 			PodIndexLabel:      podIndexLabel,
 			SubGroupIndexLabel: subGroupIndexLabel,
 			SubGroupCount:      subGroupCount,
 		}
 		if requiredFound {
 			psTopologyReq.Required = &requiredValue
-		} else {
+		} else if preferredFound {
 			psTopologyReq.Preferred = &preferredValue
 		}
+		if unconstrainedFound {
+			unconstrained, _ := strconv.ParseBool(unconstrained)
+			psTopologyReq.Unconstrained = &unconstrained
+		} else if features.Enabled(features.TASImplicitDefaultUnconstrained) {
+			psTopologyReq.Unconstrained = ptr.To(true)
path: pkg/controller/jobframework/tas.go
user: login: PBundyra
body: Made defaulting actually implict, done
created_at: 2025-03-12T15:54:54Z
author_association: CONTRIBUTOR
diff_hunk: @@ -38,6 +38,14 @@ const (
 	// among multiple topology domains.
 	PodSetPreferredTopologyAnnotation = "kueue.x-k8s.io/podset-preferred-topology"
 
+	// PodSetUnconstrainedTopologyAnnotation indicates that a PodSet does not have any topology requirements.
+	// Kueue admits the PodSet if there's enough free capacity available.
+	// Recommended for PodSets that don't require pod-to-pod communication, but want
path: apis/kueue/v1alpha1/tas_types.go
user: login: mwielgus
body: s/don't require/don't need low-latency or high-throughput/
created_at: 2025-03-12T15:57:12Z
author_association: CONTRIBUTOR
diff_hunk: @@ -104,6 +104,14 @@ type PodSetTopologyRequest struct {
 	// +optional
 	Preferred *string `json:"preferred,omitempty"`
 
+	// unconstrained indicates that Kueue has freedom to schedule the PodSet within
path: apis/kueue/v1beta1/workload_types.go
user: login: mwielgus
body: With preferred Kueue also has this freedom.  Pivot the description more toward lack of need or preference for any specific placement. 
created_at: 2025-03-12T15:59:09Z
author_association: CONTRIBUTOR
diff_hunk: @@ -38,6 +38,14 @@ const (
 	// among multiple topology domains.
 	PodSetPreferredTopologyAnnotation = "kueue.x-k8s.io/podset-preferred-topology"
 
+	// PodSetUnconstrainedTopologyAnnotation indicates that a PodSet does not have any topology requirements.
+	// Kueue admits the PodSet if there's enough free capacity available.
+	// Recommended for PodSets that don't require pod-to-pod communication, but want
path: apis/kueue/v1alpha1/tas_types.go
user: login: PBundyra
body: Done
created_at: 2025-03-12T16:17:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -104,6 +104,14 @@ type PodSetTopologyRequest struct {
 	// +optional
 	Preferred *string `json:"preferred,omitempty"`
 
+	// unconstrained indicates that Kueue has freedom to schedule the PodSet within
path: apis/kueue/v1beta1/workload_types.go
user: login: PBundyra
body: Done
created_at: 2025-03-12T16:18:02Z
author_association: CONTRIBUTOR
diff_hunk: @@ -2655,4 +2655,105 @@ var _ = ginkgo.Describe("Job controller when TopologyAwareScheduling enabled", g
 			}, util.Timeout, util.Interval).Should(gomega.Succeed())
 		})
 	})
+
+	ginkgo.It("should admit workload with topology unconstrained annotation which fits", func() {
+		job := testingjob.MakeJob("job", ns.Name).
+			Queue(localQueue.Name).
+			PodAnnotation(kueuealpha.PodSetUnconstrainedTopologyAnnotation, "true").
+			Request(corev1.ResourceCPU, "1").
+			Obj()
+		ginkgo.By("creating a job", func() {
+			gomega.Expect(k8sClient.Create(ctx, job)).Should(gomega.Succeed())
+		})
+
+		wl := &kueue.Workload{}
+		wlLookupKey := types.NamespacedName{Name: workloadjob.GetWorkloadNameForJob(job.Name, job.UID), Namespace: ns.Name}
+
+		ginkgo.By("verify the workload is created", func() {
+			gomega.Eventually(func(g gomega.Gomega) {
+				g.Expect(k8sClient.Get(ctx, wlLookupKey, wl)).Should(gomega.Succeed())
+				g.Expect(wl.Spec.PodSets).Should(gomega.BeComparableTo([]kueue.PodSet{{
+					Name:  kueue.DefaultPodSetName,
+					Count: 1,
+					TopologyRequest: &kueue.PodSetTopologyRequest{
+						Unconstrained: ptr.To(true),
+						PodIndexLabel: ptr.To(batchv1.JobCompletionIndexAnnotation),
+					},
+				}}, cmpopts.IgnoreFields(kueue.PodSet{}, "Template")))
+			}, util.Timeout, util.Interval).Should(gomega.Succeed())
+		})
+
+		ginkgo.By("verify the workload is admitted", func() {
+			gomega.Eventually(func(g gomega.Gomega) {
+				g.Expect(k8sClient.Get(ctx, wlLookupKey, wl)).Should(gomega.Succeed())
+			}, util.Timeout, util.Interval).Should(gomega.Succeed())
+
+			util.ExpectWorkloadsToBeAdmitted(ctx, k8sClient, wl)
+			util.ExpectReservingActiveWorkloadsMetric(clusterQueue, 1)
+		})
+
+		ginkgo.By("verify admission for the workload", func() {
+			wlLookupKey := types.NamespacedName{Name: workloadjob.GetWorkloadNameForJob(job.Name, job.UID), Namespace: ns.Name}
+			gomega.Eventually(func(g gomega.Gomega) {
+				g.Expect(k8sClient.Get(ctx, wlLookupKey, wl)).Should(gomega.Succeed())
+				g.Expect(wl.Status.Admission).ShouldNot(gomega.BeNil())
+				g.Expect(wl.Status.Admission.PodSetAssignments).Should(gomega.HaveLen(1))
+				g.Expect(wl.Status.Admission.PodSetAssignments[0].TopologyAssignment).Should(gomega.BeComparableTo(
+					&kueue.TopologyAssignment{
+						Levels:  []string{tasBlockLabel},
+						Domains: []kueue.TopologyDomainAssignment{{Count: 1, Values: []string{"b1"}}},
+					},
+				))
+			}, util.Timeout, util.Interval).Should(gomega.Succeed())
+		})
+	})
+
+	ginkgo.It("should implicitly default the .unconstrained field if the TASImplicitDefaultUnconstrained gate is set", func() {
+		features.SetFeatureGateDuringTest(ginkgo.GinkgoTB(), features.TASImplicitDefaultUnconstrained, true)
path: test/integration/singlecluster/controller/jobs/job/job_controller_test.go
user: login: mimowo
body: Make sure the feature gate is reverted to false, so that it does not affect other tests.
created_at: 2025-03-13T08:13:22Z
author_association: CONTRIBUTOR
diff_hunk: @@ -2655,4 +2655,105 @@ var _ = ginkgo.Describe("Job controller when TopologyAwareScheduling enabled", g
 			}, util.Timeout, util.Interval).Should(gomega.Succeed())
 		})
 	})
+
+	ginkgo.It("should admit workload with topology unconstrained annotation which fits", func() {
path: test/integration/singlecluster/controller/jobs/job/job_controller_test.go
user: login: mimowo
body: Actually, I would consider moving these tests as unite tests in scheduler_test.go, under `TestScheduleForTAS`. 
Mainly, because the unit tests are much faster. I would be ok to probably keep one of them as 
integration, but it would be healthier to have a proper "testing pyramide".

And I would suggest to add a unit test which shows the difference between "preferred" and "unconstrained", as discussed under the issue: https://github.com/kubernetes-sigs/kueue/issues/4474

created_at: 2025-03-13T08:20:10Z
author_association: CONTRIBUTOR
diff_hunk: @@ -2655,4 +2655,105 @@ var _ = ginkgo.Describe("Job controller when TopologyAwareScheduling enabled", g
 			}, util.Timeout, util.Interval).Should(gomega.Succeed())
 		})
 	})
+
+	ginkgo.It("should admit workload with topology unconstrained annotation which fits", func() {
+		job := testingjob.MakeJob("job", ns.Name).
+			Queue(localQueue.Name).
+			PodAnnotation(kueuealpha.PodSetUnconstrainedTopologyAnnotation, "true").
+			Request(corev1.ResourceCPU, "1").
+			Obj()
+		ginkgo.By("creating a job", func() {
+			gomega.Expect(k8sClient.Create(ctx, job)).Should(gomega.Succeed())
+		})
+
+		wl := &kueue.Workload{}
+		wlLookupKey := types.NamespacedName{Name: workloadjob.GetWorkloadNameForJob(job.Name, job.UID), Namespace: ns.Name}
+
+		ginkgo.By("verify the workload is created", func() {
+			gomega.Eventually(func(g gomega.Gomega) {
+				g.Expect(k8sClient.Get(ctx, wlLookupKey, wl)).Should(gomega.Succeed())
+				g.Expect(wl.Spec.PodSets).Should(gomega.BeComparableTo([]kueue.PodSet{{
+					Name:  kueue.DefaultPodSetName,
+					Count: 1,
+					TopologyRequest: &kueue.PodSetTopologyRequest{
+						Unconstrained: ptr.To(true),
+						PodIndexLabel: ptr.To(batchv1.JobCompletionIndexAnnotation),
+					},
+				}}, cmpopts.IgnoreFields(kueue.PodSet{}, "Template")))
+			}, util.Timeout, util.Interval).Should(gomega.Succeed())
+		})
+
+		ginkgo.By("verify the workload is admitted", func() {
+			gomega.Eventually(func(g gomega.Gomega) {
+				g.Expect(k8sClient.Get(ctx, wlLookupKey, wl)).Should(gomega.Succeed())
+			}, util.Timeout, util.Interval).Should(gomega.Succeed())
+
+			util.ExpectWorkloadsToBeAdmitted(ctx, k8sClient, wl)
+			util.ExpectReservingActiveWorkloadsMetric(clusterQueue, 1)
+		})
+
+		ginkgo.By("verify admission for the workload", func() {
+			wlLookupKey := types.NamespacedName{Name: workloadjob.GetWorkloadNameForJob(job.Name, job.UID), Namespace: ns.Name}
+			gomega.Eventually(func(g gomega.Gomega) {
+				g.Expect(k8sClient.Get(ctx, wlLookupKey, wl)).Should(gomega.Succeed())
+				g.Expect(wl.Status.Admission).ShouldNot(gomega.BeNil())
+				g.Expect(wl.Status.Admission.PodSetAssignments).Should(gomega.HaveLen(1))
+				g.Expect(wl.Status.Admission.PodSetAssignments[0].TopologyAssignment).Should(gomega.BeComparableTo(
+					&kueue.TopologyAssignment{
+						Levels:  []string{tasBlockLabel},
+						Domains: []kueue.TopologyDomainAssignment{{Count: 1, Values: []string{"b1"}}},
path: test/integration/singlecluster/controller/jobs/job/job_controller_test.go
user: login: mimowo
body: It is not clear to me if the assignment was different if "preferred" was used and why.
created_at: 2025-03-13T08:22:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -348,7 +412,64 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: true,
+			enableFeatureGates: []featuregate.Feature{features.TASMostFreeCapacity},
+		},
+		"unconstrained; 5 pods fit into hosts scattered across the whole datacenter even they could fit into single rack; BestFit": {
path: pkg/cache/tas_cache_test.go
user: login: mimowo
body: I don't understand the test intention and description: "unconstrained; 5 pods fit into hosts scattered across the whole datacenter even they could fit into single rack", since x1 and x2 belong to the same rack (b1-r1), or I'm missing something?
created_at: 2025-03-13T09:38:10Z
author_association: CONTRIBUTOR
diff_hunk: @@ -348,7 +412,64 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: true,
+			enableFeatureGates: []featuregate.Feature{features.TASMostFreeCapacity},
+		},
+		"unconstrained; 5 pods fit into hosts scattered across the whole datacenter even they could fit into single rack; BestFit": {
path: pkg/cache/tas_cache_test.go
user: login: PBundyra
body: Oh I see, indeed that doesn't show the intentions very well, fixed
created_at: 2025-03-13T10:18:05Z
author_association: CONTRIBUTOR
diff_hunk: @@ -2655,4 +2655,105 @@ var _ = ginkgo.Describe("Job controller when TopologyAwareScheduling enabled", g
 			}, util.Timeout, util.Interval).Should(gomega.Succeed())
 		})
 	})
+
+	ginkgo.It("should admit workload with topology unconstrained annotation which fits", func() {
path: test/integration/singlecluster/controller/jobs/job/job_controller_test.go
user: login: PBundyra
body: Done, discussed in a separate thread
created_at: 2025-03-13T10:19:00Z
author_association: CONTRIBUTOR
diff_hunk: @@ -2655,4 +2655,105 @@ var _ = ginkgo.Describe("Job controller when TopologyAwareScheduling enabled", g
 			}, util.Timeout, util.Interval).Should(gomega.Succeed())
 		})
 	})
+
+	ginkgo.It("should admit workload with topology unconstrained annotation which fits", func() {
+		job := testingjob.MakeJob("job", ns.Name).
+			Queue(localQueue.Name).
+			PodAnnotation(kueuealpha.PodSetUnconstrainedTopologyAnnotation, "true").
+			Request(corev1.ResourceCPU, "1").
+			Obj()
+		ginkgo.By("creating a job", func() {
+			gomega.Expect(k8sClient.Create(ctx, job)).Should(gomega.Succeed())
+		})
+
+		wl := &kueue.Workload{}
+		wlLookupKey := types.NamespacedName{Name: workloadjob.GetWorkloadNameForJob(job.Name, job.UID), Namespace: ns.Name}
+
+		ginkgo.By("verify the workload is created", func() {
+			gomega.Eventually(func(g gomega.Gomega) {
+				g.Expect(k8sClient.Get(ctx, wlLookupKey, wl)).Should(gomega.Succeed())
+				g.Expect(wl.Spec.PodSets).Should(gomega.BeComparableTo([]kueue.PodSet{{
+					Name:  kueue.DefaultPodSetName,
+					Count: 1,
+					TopologyRequest: &kueue.PodSetTopologyRequest{
+						Unconstrained: ptr.To(true),
+						PodIndexLabel: ptr.To(batchv1.JobCompletionIndexAnnotation),
+					},
+				}}, cmpopts.IgnoreFields(kueue.PodSet{}, "Template")))
+			}, util.Timeout, util.Interval).Should(gomega.Succeed())
+		})
+
+		ginkgo.By("verify the workload is admitted", func() {
+			gomega.Eventually(func(g gomega.Gomega) {
+				g.Expect(k8sClient.Get(ctx, wlLookupKey, wl)).Should(gomega.Succeed())
+			}, util.Timeout, util.Interval).Should(gomega.Succeed())
+
+			util.ExpectWorkloadsToBeAdmitted(ctx, k8sClient, wl)
+			util.ExpectReservingActiveWorkloadsMetric(clusterQueue, 1)
+		})
+
+		ginkgo.By("verify admission for the workload", func() {
+			wlLookupKey := types.NamespacedName{Name: workloadjob.GetWorkloadNameForJob(job.Name, job.UID), Namespace: ns.Name}
+			gomega.Eventually(func(g gomega.Gomega) {
+				g.Expect(k8sClient.Get(ctx, wlLookupKey, wl)).Should(gomega.Succeed())
+				g.Expect(wl.Status.Admission).ShouldNot(gomega.BeNil())
+				g.Expect(wl.Status.Admission.PodSetAssignments).Should(gomega.HaveLen(1))
+				g.Expect(wl.Status.Admission.PodSetAssignments[0].TopologyAssignment).Should(gomega.BeComparableTo(
+					&kueue.TopologyAssignment{
+						Levels:  []string{tasBlockLabel},
+						Domains: []kueue.TopologyDomainAssignment{{Count: 1, Values: []string{"b1"}}},
path: test/integration/singlecluster/controller/jobs/job/job_controller_test.go
user: login: PBundyra
body: My primary goal for this integration test wasn't to show the difference in assignment as I show it in unit tests. I just wanted to make sure workload is admitted to show the new annotation and implicit defaulting works as intended
created_at: 2025-03-13T10:20:19Z
author_association: CONTRIBUTOR
diff_hunk: @@ -2655,4 +2655,105 @@ var _ = ginkgo.Describe("Job controller when TopologyAwareScheduling enabled", g
 			}, util.Timeout, util.Interval).Should(gomega.Succeed())
 		})
 	})
+
+	ginkgo.It("should admit workload with topology unconstrained annotation which fits", func() {
+		job := testingjob.MakeJob("job", ns.Name).
+			Queue(localQueue.Name).
+			PodAnnotation(kueuealpha.PodSetUnconstrainedTopologyAnnotation, "true").
+			Request(corev1.ResourceCPU, "1").
+			Obj()
+		ginkgo.By("creating a job", func() {
+			gomega.Expect(k8sClient.Create(ctx, job)).Should(gomega.Succeed())
+		})
+
+		wl := &kueue.Workload{}
+		wlLookupKey := types.NamespacedName{Name: workloadjob.GetWorkloadNameForJob(job.Name, job.UID), Namespace: ns.Name}
+
+		ginkgo.By("verify the workload is created", func() {
+			gomega.Eventually(func(g gomega.Gomega) {
+				g.Expect(k8sClient.Get(ctx, wlLookupKey, wl)).Should(gomega.Succeed())
+				g.Expect(wl.Spec.PodSets).Should(gomega.BeComparableTo([]kueue.PodSet{{
+					Name:  kueue.DefaultPodSetName,
+					Count: 1,
+					TopologyRequest: &kueue.PodSetTopologyRequest{
+						Unconstrained: ptr.To(true),
+						PodIndexLabel: ptr.To(batchv1.JobCompletionIndexAnnotation),
+					},
+				}}, cmpopts.IgnoreFields(kueue.PodSet{}, "Template")))
+			}, util.Timeout, util.Interval).Should(gomega.Succeed())
+		})
+
+		ginkgo.By("verify the workload is admitted", func() {
+			gomega.Eventually(func(g gomega.Gomega) {
+				g.Expect(k8sClient.Get(ctx, wlLookupKey, wl)).Should(gomega.Succeed())
+			}, util.Timeout, util.Interval).Should(gomega.Succeed())
+
+			util.ExpectWorkloadsToBeAdmitted(ctx, k8sClient, wl)
+			util.ExpectReservingActiveWorkloadsMetric(clusterQueue, 1)
+		})
+
+		ginkgo.By("verify admission for the workload", func() {
+			wlLookupKey := types.NamespacedName{Name: workloadjob.GetWorkloadNameForJob(job.Name, job.UID), Namespace: ns.Name}
+			gomega.Eventually(func(g gomega.Gomega) {
+				g.Expect(k8sClient.Get(ctx, wlLookupKey, wl)).Should(gomega.Succeed())
+				g.Expect(wl.Status.Admission).ShouldNot(gomega.BeNil())
+				g.Expect(wl.Status.Admission.PodSetAssignments).Should(gomega.HaveLen(1))
+				g.Expect(wl.Status.Admission.PodSetAssignments[0].TopologyAssignment).Should(gomega.BeComparableTo(
+					&kueue.TopologyAssignment{
+						Levels:  []string{tasBlockLabel},
+						Domains: []kueue.TopologyDomainAssignment{{Count: 1, Values: []string{"b1"}}},
+					},
+				))
+			}, util.Timeout, util.Interval).Should(gomega.Succeed())
+		})
+	})
+
+	ginkgo.It("should implicitly default the .unconstrained field if the TASImplicitDefaultUnconstrained gate is set", func() {
+		features.SetFeatureGateDuringTest(ginkgo.GinkgoTB(), features.TASImplicitDefaultUnconstrained, true)
path: test/integration/singlecluster/controller/jobs/job/job_controller_test.go
user: login: PBundyra
body: Done
created_at: 2025-03-13T10:24:35Z
author_association: CONTRIBUTOR
diff_hunk: @@ -2655,4 +2655,105 @@ var _ = ginkgo.Describe("Job controller when TopologyAwareScheduling enabled", g
 			}, util.Timeout, util.Interval).Should(gomega.Succeed())
 		})
 	})
+
+	ginkgo.It("should admit workload with topology unconstrained annotation which fits", func() {
+		job := testingjob.MakeJob("job", ns.Name).
+			Queue(localQueue.Name).
+			PodAnnotation(kueuealpha.PodSetUnconstrainedTopologyAnnotation, "true").
+			Request(corev1.ResourceCPU, "1").
+			Obj()
+		ginkgo.By("creating a job", func() {
+			gomega.Expect(k8sClient.Create(ctx, job)).Should(gomega.Succeed())
+		})
+
+		wl := &kueue.Workload{}
+		wlLookupKey := types.NamespacedName{Name: workloadjob.GetWorkloadNameForJob(job.Name, job.UID), Namespace: ns.Name}
+
+		ginkgo.By("verify the workload is created", func() {
+			gomega.Eventually(func(g gomega.Gomega) {
+				g.Expect(k8sClient.Get(ctx, wlLookupKey, wl)).Should(gomega.Succeed())
+				g.Expect(wl.Spec.PodSets).Should(gomega.BeComparableTo([]kueue.PodSet{{
+					Name:  kueue.DefaultPodSetName,
+					Count: 1,
+					TopologyRequest: &kueue.PodSetTopologyRequest{
+						Unconstrained: ptr.To(true),
+						PodIndexLabel: ptr.To(batchv1.JobCompletionIndexAnnotation),
+					},
+				}}, cmpopts.IgnoreFields(kueue.PodSet{}, "Template")))
+			}, util.Timeout, util.Interval).Should(gomega.Succeed())
+		})
+
+		ginkgo.By("verify the workload is admitted", func() {
+			gomega.Eventually(func(g gomega.Gomega) {
+				g.Expect(k8sClient.Get(ctx, wlLookupKey, wl)).Should(gomega.Succeed())
+			}, util.Timeout, util.Interval).Should(gomega.Succeed())
+
+			util.ExpectWorkloadsToBeAdmitted(ctx, k8sClient, wl)
+			util.ExpectReservingActiveWorkloadsMetric(clusterQueue, 1)
+		})
+
+		ginkgo.By("verify admission for the workload", func() {
+			wlLookupKey := types.NamespacedName{Name: workloadjob.GetWorkloadNameForJob(job.Name, job.UID), Namespace: ns.Name}
+			gomega.Eventually(func(g gomega.Gomega) {
+				g.Expect(k8sClient.Get(ctx, wlLookupKey, wl)).Should(gomega.Succeed())
+				g.Expect(wl.Status.Admission).ShouldNot(gomega.BeNil())
+				g.Expect(wl.Status.Admission.PodSetAssignments).Should(gomega.HaveLen(1))
+				g.Expect(wl.Status.Admission.PodSetAssignments[0].TopologyAssignment).Should(gomega.BeComparableTo(
+					&kueue.TopologyAssignment{
+						Levels:  []string{tasBlockLabel},
+						Domains: []kueue.TopologyDomainAssignment{{Count: 1, Values: []string{"b1"}}},
path: test/integration/singlecluster/controller/jobs/job/job_controller_test.go
user: login: mimowo
body: sgtm
created_at: 2025-03-13T12:23:54Z
author_association: CONTRIBUTOR

PR comments:
user: login: netlify[bot]
created_at: 2025-03-12T12:47:44Z
body: ### <span aria-hidden="true">✅</span> Deploy Preview for *kubernetes-sigs-kueue* canceled.


|  Name | Link |
|:-:|------------------------|
|<span aria-hidden="true">🔨</span> Latest commit | eb33d6faebbc05c47868006d2e9e015a61647df7 |
|<span aria-hidden="true">🔍</span> Latest deploy log | https://app.netlify.com/sites/kubernetes-sigs-kueue/deploys/67d2b25ac906b100089192c3 |
author_association: NONE
user: login: PBundyra
created_at: 2025-03-12T12:50:09Z
body: /assign @mimowo 
author_association: CONTRIBUTOR
user: login: PBundyra
created_at: 2025-03-12T13:22:34Z
body: /retest
author_association: CONTRIBUTOR
user: login: PBundyra
created_at: 2025-03-13T09:17:39Z
body: > 2\. it is not clear to me if the asserts are functionalliy different than "preferred" would have returned. Adding unit tests which show the difference as discussed under the issue would be great, and add a comment why we observe the difference.

Do you mean other than those?
https://github.com/kubernetes-sigs/kueue/pull/4567/files#diff-85a93b2977c9efa55ca4846fdd219e22733e2b736c4fa3dba06f70739c1bbdfbR417-R470
In these pods are assigned on nodes scattered across the whole cluster, while with preferred they would fit into a single rack
author_association: CONTRIBUTOR
user: login: mimowo
created_at: 2025-03-13T09:38:57Z
body: > Do you mean other than those?

No, these tests is what I was looking for (I somehow missed them), just not sure about the semantics still, but asked dedicated question: https://github.com/kubernetes-sigs/kueue/pull/4567/files#r1993128268
author_association: CONTRIBUTOR
user: login: k8s-ci-robot
created_at: 2025-03-13T12:24:12Z
body: LGTM label has been added.  <details>Git tree hash: c329b55c9336c1415569166fd21b5cd8b206a88a</details>
author_association: CONTRIBUTOR
user: login: k8s-ci-robot
created_at: 2025-03-13T12:24:15Z
body: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/kubernetes-sigs/kueue/pull/4567#pullrequestreview-2681693172" title="Approved">mimowo</a>*, *<a href="https://github.com/kubernetes-sigs/kueue/pull/4567#" title="Author self-approved">PBundyra</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=kubernetes-sigs%2Fkueue).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/kubernetes-sigs/kueue/blob/main/OWNERS)~~ [mimowo]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->
author_association: CONTRIBUTOR
user: login: mimowo
created_at: 2025-03-13T12:25:08Z
body: cc @tenzen-y feel free to add some comments post-merge. 

I'm merging as we need to revisit the defaulting in the context of rank-based ordering anyway. 
author_association: CONTRIBUTOR