Repository: kubernetes-sigs/gateway-api-inference-extension

Issue:
Update the whole repo to use v1 `inference.networking.k8s.io`  InferencePool
<!-- Please only use this template for submitting enhancement requests -->

**What would you like to be added**:
Update the whole repo to use v1 `inference.networking.k8s.io`  InferencePool

**Why is this needed**:
As #1116 and #1118  got merged, we should update the whole repo to use v1 `inference.networking.k8s.io`  InferencePool


Discussion:
@capri-xiyue: /assign

Solution patch:
diff --git a/.github/ISSUE_TEMPLATE/new-release.md b/.github/ISSUE_TEMPLATE/new-release.md
index 16ff164..6717239 100644
--- a/.github/ISSUE_TEMPLATE/new-release.md
+++ b/.github/ISSUE_TEMPLATE/new-release.md
@@ -42,7 +42,7 @@ This document defines the process for releasing Gateway API Inference Extension.
    ```shell
    export VLLM_GPU=0.9.2
    export VLLM_CPU=0.9.3
-   export VLLM_SIM=0.1.2
+   export VLLM_SIM=0.3.0
    ```
 
 ## Release Process
diff --git a/Makefile b/Makefile
index 5c8faa6..406eb02 100644
--- a/Makefile
+++ b/Makefile
@@ -292,6 +292,14 @@ live-docs:
 	docker build -t gaie/mkdocs hack/mkdocs/image
 	docker run --rm -it -p 3000:3000 -v ${PWD}:/docs gaie/mkdocs
 
+.PHONY: apix-ref-docs
+apix-ref-docs:
+	crd-ref-docs \
+		--source-path=${PWD}/apix/v1alpha2 \
+		--config=crd-ref-docs.yaml \
+		--renderer=markdown \
+		--output-path=${PWD}/site-src/reference/x-spec.md
+
 .PHONY: api-ref-docs
 api-ref-docs:
 	crd-ref-docs \
diff --git a/README.md b/README.md
index 8aa8630..8212c73 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,7 @@
 [![Go Report Card](https://goreportcard.com/badge/sigs.k8s.io/gateway-api-inference-extension)](https://goreportcard.com/report/sigs.k8s.io/gateway-api-inference-extension)
 [![Go Reference](https://pkg.go.dev/badge/sigs.k8s.io/gateway-api-inference-extension.svg)](https://pkg.go.dev/sigs.k8s.io/gateway-api-inference-extension)
 [![License](https://img.shields.io/github/license/kubernetes-sigs/gateway-api-inference-extension)](/LICENSE)
+[![Join Slack](https://img.shields.io/badge/Join_Slack-blue?logo=slack)](https://kubernetes.slack.com/archives/C08E3RZMT2P)
 
 # Gateway API Inference Extension
 
diff --git a/cmd/bbr/health.go b/cmd/bbr/health.go
index f42ca2b..e1020b3 100644
--- a/cmd/bbr/health.go
+++ b/cmd/bbr/health.go
@@ -24,6 +24,7 @@ import (
 	"google.golang.org/grpc/codes"
 	healthPb "google.golang.org/grpc/health/grpc_health_v1"
 	"google.golang.org/grpc/status"
+
 	logutil "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/util/logging"
 )
 
diff --git a/cmd/epp/main.go b/cmd/epp/main.go
index b5e0617..bd15e87 100644
--- a/cmd/epp/main.go
+++ b/cmd/epp/main.go
@@ -25,8 +25,6 @@ import (
 )
 
 func main() {
-	// Register all known plugin factories
-	runner.RegisterAllPlugins()
 	// For adding out-of-tree plugins to the plugins registry, use the following:
 	// plugins.Register(my-out-of-tree-plugin-name, my-out-of-tree-plugin-factory-function)
 
diff --git a/cmd/epp/runner/health.go b/cmd/epp/runner/health.go
index 283541e..cc5da8d 100644
--- a/cmd/epp/runner/health.go
+++ b/cmd/epp/runner/health.go
@@ -24,6 +24,7 @@ import (
 	"google.golang.org/grpc/codes"
 	healthPb "google.golang.org/grpc/health/grpc_health_v1"
 	"google.golang.org/grpc/status"
+
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/datastore"
 	logutil "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/util/logging"
 )
diff --git a/cmd/epp/runner/register.go b/cmd/epp/runner/register.go
deleted file mode 100644
index 161a224..0000000
--- a/cmd/epp/runner/register.go
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
-Copyright 2025 The Kubernetes Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package runner
-
-import (
-	"context"
-
-	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/plugins"
-	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/scheduling/framework/plugins/filter"
-	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/scheduling/framework/plugins/multi/prefix"
-	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/scheduling/framework/plugins/picker"
-	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/scheduling/framework/plugins/profile"
-	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/scheduling/framework/plugins/scorer"
-	testfilter "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/scheduling/framework/plugins/test/filter"
-)
-
-// RegisterAllPlugins registers the factory functions of all known plugins
-func RegisterAllPlugins() {
-	plugins.Register(filter.DecisionTreeFilterType, filter.DecisionTreeFilterFactory)
-	plugins.Register(filter.LeastKVCacheFilterType, filter.LeastKVCacheFilterFactory)
-	plugins.Register(filter.LeastQueueFilterType, filter.LeastQueueFilterFactory)
-	plugins.Register(filter.LoraAffinityFilterType, filter.LoraAffinityFilterFactory)
-	plugins.Register(filter.LowQueueFilterType, filter.LowQueueFilterFactory)
-	plugins.Register(prefix.PrefixCachePluginType, prefix.PrefixCachePluginFactory)
-	plugins.Register(picker.MaxScorePickerType, picker.MaxScorePickerFactory)
-	plugins.Register(picker.RandomPickerType, picker.RandomPickerFactory)
-	plugins.Register(profile.SingleProfileHandlerType, profile.SingleProfileHandlerFactory)
-	plugins.Register(scorer.KvCacheScorerType, scorer.KvCacheScorerFactory)
-	plugins.Register(scorer.QueueScorerType, scorer.QueueScorerFactory)
-	// register filter for test purpose only (used in conformance tests)
-	plugins.Register(testfilter.HeaderBasedTestingFilterType, testfilter.HeaderBasedTestingFilterFactory)
-}
-
-// eppHandle is an implementation of the interface plugins.Handle
-type eppHandle struct {
-	ctx context.Context
-	plugins.HandlePlugins
-}
-
-// Context returns a context the plugins can use, if they need one
-func (h *eppHandle) Context() context.Context {
-	return h.ctx
-}
-
-// eppHandlePlugins implements the set of APIs to work with instantiated plugins
-type eppHandlePlugins struct {
-	plugins map[string]plugins.Plugin
-}
-
-// Plugin returns the named plugin instance
-func (h *eppHandlePlugins) Plugin(name string) plugins.Plugin {
-	return h.plugins[name]
-}
-
-// AddPlugin adds a plugin to the set of known plugin instances
-func (h *eppHandlePlugins) AddPlugin(name string, plugin plugins.Plugin) {
-	h.plugins[name] = plugin
-}
-
-// GetAllPlugins returns all of the known plugins
-func (h *eppHandlePlugins) GetAllPlugins() []plugins.Plugin {
-	result := make([]plugins.Plugin, 0)
-	for _, plugin := range h.plugins {
-		result = append(result, plugin)
-	}
-	return result
-}
-
-// GetAllPluginsWithNames returns al of the known plugins with their names
-func (h *eppHandlePlugins) GetAllPluginsWithNames() map[string]plugins.Plugin {
-	return h.plugins
-}
-
-func newEppHandle(ctx context.Context) *eppHandle {
-	return &eppHandle{
-		ctx: ctx,
-		HandlePlugins: &eppHandlePlugins{
-			plugins: map[string]plugins.Plugin{},
-		},
-	}
-}
diff --git a/cmd/epp/runner/runner.go b/cmd/epp/runner/runner.go
index 1c45ce6..53c2466 100644
--- a/cmd/epp/runner/runner.go
+++ b/cmd/epp/runner/runner.go
@@ -18,9 +18,11 @@ package runner
 
 import (
 	"context"
+	"crypto/tls"
 	"errors"
 	"flag"
 	"fmt"
+	"net/http"
 	"net/http/pprof"
 	"os"
 
@@ -44,9 +46,16 @@ import (
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/datastore"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/metrics"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/metrics/collectors"
+	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/plugins"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/requestcontrol"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/saturationdetector"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/scheduling"
+	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/scheduling/framework/plugins/filter"
+	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/scheduling/framework/plugins/multi/prefix"
+	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/scheduling/framework/plugins/picker"
+	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/scheduling/framework/plugins/profile"
+	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/scheduling/framework/plugins/scorer"
+	testfilter "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/scheduling/framework/plugins/test/filter"
 	runserver "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/server"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/util/logging"
 	"sigs.k8s.io/gateway-api-inference-extension/version"
@@ -138,7 +147,9 @@ var (
 
 	modelServerMetricsPort = flag.Int("model-server-metrics-port", 0, "Port to scrape metrics from pods. "+
 		"Default value will be set to InferencePool.Spec.TargetPortNumber if not set.")
-	modelServerMetricsPath = flag.String("model-server-metrics-path", "/metrics", "Path to scrape metrics from pods")
+	modelServerMetricsPath                    = flag.String("model-server-metrics-path", "/metrics", "Path to scrape metrics from pods")
+	modelServerMetricsScheme                  = flag.String("model-server-metrics-scheme", "http", "Scheme to scrape metrics from pods")
+	modelServerMetricsHttpsInsecureSkipVerify = flag.Bool("model-server-metrics-https-insecure-skip-verify", true, "When using 'https' scheme for 'model-server-metrics-scheme', configure 'InsecureSkipVerify' (default to true)")
 
 	setupLog = ctrl.Log.WithName("setup")
 )
@@ -169,13 +180,15 @@ func (r *Runner) WithSchedulerConfig(schedulerConfig *scheduling.SchedulerConfig
 func bindEnvToFlags() {
 	// map[ENV_VAR]flagName   – add more as needed
 	for env, flg := range map[string]string{
-		"GRPC_PORT":                     "grpc-port",
-		"GRPC_HEALTH_PORT":              "grpc-health-port",
-		"MODEL_SERVER_METRICS_PORT":     "model-server-metrics-port",
-		"MODEL_SERVER_METRICS_PATH":     "model-server-metrics-path",
-		"DESTINATION_ENDPOINT_HINT_KEY": "destination-endpoint-hint-key",
-		"POOL_NAME":                     "pool-name",
-		"POOL_NAMESPACE":                "pool-namespace",
+		"GRPC_PORT":                                       "grpc-port",
+		"GRPC_HEALTH_PORT":                                "grpc-health-port",
+		"MODEL_SERVER_METRICS_PORT":                       "model-server-metrics-port",
+		"MODEL_SERVER_METRICS_PATH":                       "model-server-metrics-path",
+		"MODEL_SERVER_METRICS_SCHEME":                     "model-server-metrics-scheme",
+		"MODEL_SERVER_METRICS_HTTPS_INSECURE_SKIP_VERIFY": "model-server-metrics-https-insecure-skip-verify",
+		"DESTINATION_ENDPOINT_HINT_KEY":                   "destination-endpoint-hint-key",
+		"POOL_NAME":                                       "pool-name",
+		"POOL_NAMESPACE":                                  "pool-namespace",
 		// durations & bools work too; flag.Set expects the *string* form
 		"REFRESH_METRICS_INTERVAL": "refresh-metrics-interval",
 		"SECURE_SERVING":           "secure-serving",
@@ -235,10 +248,26 @@ func (r *Runner) Run(ctx context.Context) error {
 		return err
 	}
 	verifyMetricMapping(*mapping, setupLog)
+
+	var metricsHttpClient *http.Client
+	if *modelServerMetricsScheme == "https" {
+		metricsHttpClient = &http.Client{
+			Transport: &http.Transport{
+				TLSClientConfig: &tls.Config{
+					InsecureSkipVerify: *modelServerMetricsHttpsInsecureSkipVerify,
+				},
+			},
+		}
+	} else {
+		metricsHttpClient = http.DefaultClient
+	}
+
 	pmf := backendmetrics.NewPodMetricsFactory(&backendmetrics.PodMetricsClientImpl{
-		MetricMapping:          mapping,
-		ModelServerMetricsPort: int32(*modelServerMetricsPort),
-		ModelServerMetricsPath: *modelServerMetricsPath,
+		MetricMapping:            mapping,
+		ModelServerMetricsPort:   int32(*modelServerMetricsPort),
+		ModelServerMetricsPath:   *modelServerMetricsPath,
+		ModelServerMetricsScheme: *modelServerMetricsScheme,
+		Client:                   metricsHttpClient,
 	}, *refreshMetricsInterval)
 
 	datastore := datastore.NewDatastore(ctx, pmf)
@@ -335,6 +364,23 @@ func (r *Runner) Run(ctx context.Context) error {
 	return nil
 }
 
+// registerInTreePlugins registers the factory functions of all known plugins
+func (r *Runner) registerInTreePlugins() {
+	plugins.Register(filter.DecisionTreeFilterType, filter.DecisionTreeFilterFactory)
+	plugins.Register(filter.LeastKVCacheFilterType, filter.LeastKVCacheFilterFactory)
+	plugins.Register(filter.LeastQueueFilterType, filter.LeastQueueFilterFactory)
+	plugins.Register(filter.LoraAffinityFilterType, filter.LoraAffinityFilterFactory)
+	plugins.Register(filter.LowQueueFilterType, filter.LowQueueFilterFactory)
+	plugins.Register(prefix.PrefixCachePluginType, prefix.PrefixCachePluginFactory)
+	plugins.Register(picker.MaxScorePickerType, picker.MaxScorePickerFactory)
+	plugins.Register(picker.RandomPickerType, picker.RandomPickerFactory)
+	plugins.Register(profile.SingleProfileHandlerType, profile.SingleProfileHandlerFactory)
+	plugins.Register(scorer.KvCacheScorerType, scorer.KvCacheScorerFactory)
+	plugins.Register(scorer.QueueScorerType, scorer.QueueScorerFactory)
+	// register filter for test purpose only (used in conformance tests)
+	plugins.Register(testfilter.HeaderBasedTestingFilterType, testfilter.HeaderBasedTestingFilterFactory)
+}
+
 func (r *Runner) parsePluginsConfiguration(ctx context.Context) error {
 	if *configText == "" && *configFile == "" {
 		return nil // configuring through code, not through file
@@ -351,7 +397,8 @@ func (r *Runner) parsePluginsConfiguration(ctx context.Context) error {
 		}
 	}
 
-	handle := newEppHandle(ctx)
+	r.registerInTreePlugins()
+	handle := plugins.NewEppHandle(ctx)
 	config, err := loader.LoadConfig(configBytes, handle)
 	if err != nil {
 		return fmt.Errorf("failed to load the configuration - %w", err)
@@ -421,6 +468,9 @@ func validateFlags() error {
 	if *configText != "" && *configFile != "" {
 		return fmt.Errorf("both the %q and %q flags can not be set at the same time", "configText", "configFile")
 	}
+	if *modelServerMetricsScheme != "http" && *modelServerMetricsScheme != "https" {
+		return fmt.Errorf("unexpected %q value for %q flag, it can only be set to 'http' or 'https'", *modelServerMetricsScheme, "model-server-metrics-scheme")
+	}
 
 	return nil
 }
diff --git a/config/charts/inferencepool/templates/epp-deployment.yaml b/config/charts/inferencepool/templates/epp-deployment.yaml
index 01973cf..5ab9e2d 100644
--- a/config/charts/inferencepool/templates/epp-deployment.yaml
+++ b/config/charts/inferencepool/templates/epp-deployment.yaml
@@ -39,6 +39,9 @@ spec:
         - "config/{{ .Values.inferenceExtension.pluginsConfigFile }}"
         # https://pkg.go.dev/flag#hdr-Command_line_flag_syntax; space is only for non-bool flags
         - "--enable-pprof={{ .Values.inferenceExtension.enablePprof }}"
+        - "--model-server-metrics-path={{ .Values.inferenceExtension.modelServerMetricsPath }}"
+        - "--model-server-metrics-scheme={{ .Values.inferenceExtension.modelServerMetricsScheme }}"
+        - "--model-server-metrics-https-insecure-skip-verify={{ .Values.inferenceExtension.modelServerMetricsHttpsInsecureSkipVerify }}"
         {{- if eq (.Values.inferencePool.modelServerType | default "vllm") "triton-tensorrt-llm" }}
         - --total-queued-requests-metric
         - "nv_trt_llm_request_metrics{request_type=waiting}"
diff --git a/config/charts/inferencepool/templates/gke.yaml b/config/charts/inferencepool/templates/gke.yaml
index 70e05b5..382549f 100644
--- a/config/charts/inferencepool/templates/gke.yaml
+++ b/config/charts/inferencepool/templates/gke.yaml
@@ -9,7 +9,7 @@ metadata:
     {{- include "gateway-api-inference-extension.labels" . | nindent 4 }}
 spec:
   targetRef:
-    group: "inference.networking.x-k8s.io"
+    group: "inference.networking.k8s.io"
     kind: InferencePool
     name: {{ .Release.Name }}
   default:
@@ -28,7 +28,7 @@ metadata:
     {{- include "gateway-api-inference-extension.labels" . | nindent 4 }}
 spec:
   targetRef:
-    group: "inference.networking.x-k8s.io"
+    group: "inference.networking.k8s.io"
     kind: InferencePool
     name: {{ .Release.Name }}
   default:
diff --git a/config/charts/inferencepool/templates/inferencepool.yaml b/config/charts/inferencepool/templates/inferencepool.yaml
index 4b279cb..f9d04df 100644
--- a/config/charts/inferencepool/templates/inferencepool.yaml
+++ b/config/charts/inferencepool/templates/inferencepool.yaml
@@ -1,5 +1,5 @@
 {{ include "gateway-api-inference-extension.validations.inferencepool.common" $ }}
-apiVersion: inference.networking.x-k8s.io/v1alpha2
+apiVersion: inference.networking.k8s.io/v1
 kind: InferencePool
 metadata:
   name: {{ .Release.Name }}
diff --git a/config/charts/inferencepool/templates/rbac.yaml b/config/charts/inferencepool/templates/rbac.yaml
index 4cb5d7b..217fd24 100644
--- a/config/charts/inferencepool/templates/rbac.yaml
+++ b/config/charts/inferencepool/templates/rbac.yaml
@@ -8,6 +8,9 @@ rules:
 - apiGroups: ["inference.networking.x-k8s.io"]
   resources: ["inferencemodels", "inferencepools"]
   verbs: ["get", "watch", "list"]
+- apiGroups: ["inference.networking.k8s.io"]
+  resources: ["inferencepools"]
+  verbs: ["get", "watch", "list"]
 - apiGroups: [""]
   resources: ["pods"]
   verbs: ["get", "watch", "list"]
diff --git a/config/charts/inferencepool/values.yaml b/config/charts/inferencepool/values.yaml
index 47689a0..df8d947 100644
--- a/config/charts/inferencepool/values.yaml
+++ b/config/charts/inferencepool/values.yaml
@@ -8,6 +8,9 @@ inferenceExtension:
   extProcPort: 9002
   env: []
   enablePprof: true # Enable pprof handlers for profiling and debugging
+  modelServerMetricsPath: "/metrics"
+  modelServerMetricsScheme: "http"
+  modelServerMetricsHttpsInsecureSkipVerify: true
   # This is the plugins configuration file. 
   pluginsConfigFile: "default-plugins.yaml"
   # pluginsCustomConfig:
diff --git a/config/manifests/gateway/gke/gcp-backend-policy.yaml b/config/manifests/gateway/gke/gcp-backend-policy.yaml
index 7b29430..9367865 100644
--- a/config/manifests/gateway/gke/gcp-backend-policy.yaml
+++ b/config/manifests/gateway/gke/gcp-backend-policy.yaml
@@ -4,7 +4,7 @@ metadata:
   name: inferencepool-backend-policy
 spec:
   targetRef:
-    group: "inference.networking.x-k8s.io"
+    group: "inference.networking.k8s.io"
     kind: InferencePool
     name: vllm-llama3-8b-instruct
   default:
diff --git a/config/manifests/inferencepool-resources.yaml b/config/manifests/inferencepool-resources.yaml
index aa8c829..d24e498 100644
--- a/config/manifests/inferencepool-resources.yaml
+++ b/config/manifests/inferencepool-resources.yaml
@@ -3,7 +3,7 @@
 #  - ./conformance/resources/manifests/manifests.yaml
 #  - ./site-src/guides/inferencepool-rollout.md
 ---
-apiVersion: inference.networking.x-k8s.io/v1alpha2
+apiVersion: inference.networking.k8s.io/v1
 kind: InferencePool
 metadata:
   name: vllm-llama3-8b-instruct
diff --git a/config/manifests/vllm/sim-deployment.yaml b/config/manifests/vllm/sim-deployment.yaml
index 196fe86..17b6891 100644
--- a/config/manifests/vllm/sim-deployment.yaml
+++ b/config/manifests/vllm/sim-deployment.yaml
@@ -14,7 +14,7 @@ spec:
     spec:
       containers:
       - name: vllm-sim
-        image: ghcr.io/llm-d/llm-d-inference-sim:v0.1.2
+        image: ghcr.io/llm-d/llm-d-inference-sim:v0.3.0
         imagePullPolicy: Always
         args:
         - --model
@@ -23,8 +23,8 @@ spec:
         - "8000"
         - --max-loras
         - "2"
-        - --lora
-        - food-review-1
+        - --lora-modules
+        - '{"name": "food-review-1"}'
         env:
         - name: POD_NAME
           valueFrom:
diff --git a/conformance/conformance.go b/conformance/conformance.go
index ba2b962..97ce63e 100644
--- a/conformance/conformance.go
+++ b/conformance/conformance.go
@@ -30,14 +30,14 @@ import (
 	apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
 	apierrors "k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/apimachinery/pkg/types"
-	"k8s.io/apimachinery/pkg/util/wait"
-	clientset "k8s.io/client-go/kubernetes"
-	clientsetscheme "k8s.io/client-go/kubernetes/scheme"
 
 	// Import runtime package for scheme creation
 	"k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/apimachinery/pkg/types"
 	"k8s.io/apimachinery/pkg/util/sets"
+	"k8s.io/apimachinery/pkg/util/wait"
+	clientset "k8s.io/client-go/kubernetes"
+	clientsetscheme "k8s.io/client-go/kubernetes/scheme"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 	k8sconfig "sigs.k8s.io/controller-runtime/pkg/client/config"
 
@@ -50,21 +50,18 @@ import (
 	"sigs.k8s.io/gateway-api/conformance/utils/tlog"
 	"sigs.k8s.io/gateway-api/pkg/features"
 
+	// Import the Inference Extension API types
+	inferencev1 "sigs.k8s.io/gateway-api-inference-extension/api/v1"
+	inferencev1alpha2 "sigs.k8s.io/gateway-api-inference-extension/apix/v1alpha2"
+
 	// Import the test definitions package to access the ConformanceTests slice
 	"sigs.k8s.io/gateway-api-inference-extension/conformance/tests"
-	"sigs.k8s.io/gateway-api-inference-extension/version"
-
 	// Import test packages using blank identifier
 	// This triggers the init() functions in these packages, which register the tests
 	// by appending them to the tests.ConformanceTests slice.
 	_ "sigs.k8s.io/gateway-api-inference-extension/conformance/tests/basic"
-	// TODO: Add blank imports for other test categories as they are created.
-	// _ "sigs.k8s.io/gateway-api-inference-extension/conformance/tests/model_routing"
-
-	// Import the Inference Extension API types
-	inferencev1 "sigs.k8s.io/gateway-api-inference-extension/api/v1"
-	inferencev1alpha2 "sigs.k8s.io/gateway-api-inference-extension/apix/v1alpha2"
 	inferenceconfig "sigs.k8s.io/gateway-api-inference-extension/conformance/utils/config"
+	"sigs.k8s.io/gateway-api-inference-extension/version"
 )
 
 const (
diff --git a/conformance/reports/v0.5.0/gateway/gke-gateway/README.md b/conformance/reports/v0.5.0/gateway/gke-gateway/README.md
new file mode 100644
index 0000000..783d498
--- /dev/null
+++ b/conformance/reports/v0.5.0/gateway/gke-gateway/README.md
@@ -0,0 +1,46 @@
+# GKE (Google Kubernetes Engine) Gateway
+
+## Table of Contents
+
+| Extension Version Tested | Profile Tested | Implementation Version | Mode    | Report                                                                     |
+|--------------------------|----------------|------------------------|---------|----------------------------------------------------------------------------|
+| v0.5.0                   | Gateway        | 1.32.4-gke.1415000                | gke-l7-regional-external-managed | [v1.32.4 Gateway report](./standard-v1.32.4-rxlb-gateway-report.yaml) |
+| ...                      | ...            | ...                    | ...     | ...                                                                        |
+
+## Reproduce
+
+GKE Gateway conformance report can be reproduced by the following steps.
+
+1. Create a GKE cluster with Gateway API enabled.
+
+    ```
+    gcloud container clusters create "${cluster_name}" --gateway-api=standard --location="${location}"
+    ```
+1. Deploy GKE gateway following [guide](https://cloud.google.com/kubernetes-engine/docs/how-to/deploying-gateways#configure_a_proxy-only_subnet).
+
+1. Install the InferencePool and InferenceModel Custom Resource Definition (CRDs) in your GKE cluster, run the following command:
+    ```
+    kubectl apply -f https://github.com/kubernetes-sigs/gateway-api-inference-extension/releases/download/v0.5.0/manifests.yaml
+    ```
+
+1. Run the following command from within the [Gateway API inference extension repo](https://github.com/kubernetes-sigs/gateway-api-inference-extension).
+
+    ```
+    go test -timeout 30m ./conformance -v -args \
+        --gateway-class=gke-l7-regional-external-managed \
+        --conformance-profiles=Gateway \
+        --organization=GKE \
+        --project=gke-gateway \
+        --url=https://cloud.google.com/kubernetes-engine/docs/concepts/gateway-api \
+        --version=1.32.4-gke.1415000 \
+        --contact=gke-gateway-dev@google.com \
+        --report-output="/path/to/report"
+    ```
+
+    or run a single conformance test case.
+
+    ```
+    go test ./conformance -v -args \
+        -gateway-class=gke-l7-regional-external-managed \
+        -run-test=InferencePoolAccepted
+    ```
\ No newline at end of file
diff --git a/conformance/reports/v0.5.0/gateway/gke-gateway/standard-v1.32.4-rxlb-gateway-report.yaml b/conformance/reports/v0.5.0/gateway/gke-gateway/standard-v1.32.4-rxlb-gateway-report.yaml
new file mode 100644
index 0000000..2ad5b7b
--- /dev/null
+++ b/conformance/reports/v0.5.0/gateway/gke-gateway/standard-v1.32.4-rxlb-gateway-report.yaml
@@ -0,0 +1,23 @@
+GatewayAPIInferenceExtensionVersion: v0.5.0
+apiVersion: gateway.networking.k8s.io/v1
+date: "2025-07-21T22:52:10Z"
+gatewayAPIChannel: standard
+gatewayAPIVersion: v1.2.1
+implementation:
+  contact:
+  - gke-gateway-dev@google.com
+  organization: GKE
+  project: gke-gateway
+  url: https://cloud.google.com/kubernetes-engine/docs/concepts/gateway-api
+  version: 1.32.4-gke.1415000
+kind: ConformanceReport
+mode: default
+profiles:
+- core:
+    result: success
+    statistics:
+      Failed: 0
+      Passed: 9
+      Skipped: 0
+  name: Gateway
+  summary: Core tests succeeded.
diff --git a/conformance/utils/config/timing.go b/conformance/utils/config/timing.go
index 00aefda..03cf078 100644
--- a/conformance/utils/config/timing.go
+++ b/conformance/utils/config/timing.go
@@ -19,8 +19,6 @@ package config
 import (
 	"time"
 
-	// Import the upstream Gateway API timeout config
-
 	gatewayconfig "sigs.k8s.io/gateway-api/conformance/utils/config"
 )
 
diff --git a/conformance/utils/kubernetes/helpers.go b/conformance/utils/kubernetes/helpers.go
index 93866bf..8884788 100644
--- a/conformance/utils/kubernetes/helpers.go
+++ b/conformance/utils/kubernetes/helpers.go
@@ -33,12 +33,12 @@ import (
 	"k8s.io/apimachinery/pkg/types"
 	"k8s.io/apimachinery/pkg/util/wait"
 	"sigs.k8s.io/controller-runtime/pkg/client"
-
-	inferenceapi "sigs.k8s.io/gateway-api-inference-extension/api/v1"
-	"sigs.k8s.io/gateway-api-inference-extension/conformance/utils/config"
 	gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
 	gatewayapiconfig "sigs.k8s.io/gateway-api/conformance/utils/config"
 	gatewayk8sutils "sigs.k8s.io/gateway-api/conformance/utils/kubernetes"
+
+	inferenceapi "sigs.k8s.io/gateway-api-inference-extension/api/v1"
+	"sigs.k8s.io/gateway-api-inference-extension/conformance/utils/config"
 )
 
 // checkCondition is a helper function similar to findConditionInList or CheckCondition
diff --git a/hack/release-quickstart.sh b/hack/release-quickstart.sh
index 14303c8..8f25cbd 100755
--- a/hack/release-quickstart.sh
+++ b/hack/release-quickstart.sh
@@ -35,7 +35,7 @@ VLLM_GPU="${VLLM_GPU:-0.9.1}"
 # The CPU image is from https://gallery.ecr.aws/q9t5s3a7/vllm-cpu-release-repo
 VLLM_CPU="${VLLM_CPU:-0.9.1}"
 # The sim image is from https://github.com/llm-d/llm-d-inference-sim/pkgs/container/llm-d-inference-sim
-VLLM_SIM="${VLLM_SIM:-0.1.1}"
+VLLM_SIM="${VLLM_SIM:-0.3.0}"
 
 echo "Using release tag: ${RELEASE_TAG}"
 echo "Using vLLM GPU image version: ${VLLM_GPU}"
diff --git a/mkdocs.yml b/mkdocs.yml
index efa7aef..4bb94f5 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -87,4 +87,3 @@ nav:
     - Overview: gieps/overview.md
   - Contributing:
     - How to Get Involved: contributing/index.md
-    - Developer Guide: contributing/devguide.md
diff --git a/pkg/bbr/handlers/request.go b/pkg/bbr/handlers/request.go
index 0a3b893..1145e6e 100644
--- a/pkg/bbr/handlers/request.go
+++ b/pkg/bbr/handlers/request.go
@@ -25,6 +25,7 @@ import (
 	eppb "github.com/envoyproxy/go-control-plane/envoy/service/ext_proc/v3"
 	extProcPb "github.com/envoyproxy/go-control-plane/envoy/service/ext_proc/v3"
 	"sigs.k8s.io/controller-runtime/pkg/log"
+
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/bbr/metrics"
 	logutil "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/util/logging"
 )
diff --git a/pkg/bbr/handlers/server.go b/pkg/bbr/handlers/server.go
index aca17ff..ad93b39 100644
--- a/pkg/bbr/handlers/server.go
+++ b/pkg/bbr/handlers/server.go
@@ -26,6 +26,7 @@ import (
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
 	"sigs.k8s.io/controller-runtime/pkg/log"
+
 	logutil "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/util/logging"
 	requtil "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/util/request"
 )
diff --git a/pkg/bbr/server/runserver.go b/pkg/bbr/server/runserver.go
index 2001b7f..ec2880b 100644
--- a/pkg/bbr/server/runserver.go
+++ b/pkg/bbr/server/runserver.go
@@ -25,6 +25,7 @@ import (
 	"google.golang.org/grpc"
 	"google.golang.org/grpc/credentials"
 	"sigs.k8s.io/controller-runtime/pkg/manager"
+
 	"sigs.k8s.io/gateway-api-inference-extension/internal/runnable"
 	tlsutil "sigs.k8s.io/gateway-api-inference-extension/internal/tls"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/bbr/handlers"
diff --git a/pkg/epp/backend/metrics/fake.go b/pkg/epp/backend/metrics/fake.go
index 6828318..284a264 100644
--- a/pkg/epp/backend/metrics/fake.go
+++ b/pkg/epp/backend/metrics/fake.go
@@ -24,6 +24,7 @@ import (
 	corev1 "k8s.io/api/core/v1"
 	"k8s.io/apimachinery/pkg/types"
 	"sigs.k8s.io/controller-runtime/pkg/log"
+
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/backend"
 	logutil "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/util/logging"
 )
diff --git a/pkg/epp/backend/metrics/logger.go b/pkg/epp/backend/metrics/logger.go
index 259d6f1..8cd4880 100644
--- a/pkg/epp/backend/metrics/logger.go
+++ b/pkg/epp/backend/metrics/logger.go
@@ -23,6 +23,7 @@ import (
 
 	"github.com/go-logr/logr"
 	"sigs.k8s.io/controller-runtime/pkg/log"
+
 	v1 "sigs.k8s.io/gateway-api-inference-extension/api/v1"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/metrics"
 	logutil "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/util/logging"
diff --git a/pkg/epp/backend/metrics/metrics.go b/pkg/epp/backend/metrics/metrics.go
index 590685c..9f53661 100644
--- a/pkg/epp/backend/metrics/metrics.go
+++ b/pkg/epp/backend/metrics/metrics.go
@@ -26,6 +26,7 @@ import (
 	dto "github.com/prometheus/client_model/go"
 	"github.com/prometheus/common/expfmt"
 	"go.uber.org/multierr"
+
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/backend"
 )
 
@@ -37,9 +38,12 @@ const (
 )
 
 type PodMetricsClientImpl struct {
-	MetricMapping          *MetricMapping
-	ModelServerMetricsPort int32
-	ModelServerMetricsPath string
+	MetricMapping            *MetricMapping
+	ModelServerMetricsPort   int32
+	ModelServerMetricsPath   string
+	ModelServerMetricsScheme string
+
+	Client *http.Client
 }
 
 // FetchMetrics fetches metrics from a given pod, clones the existing metrics object and returns an updated one.
@@ -49,7 +53,7 @@ func (p *PodMetricsClientImpl) FetchMetrics(ctx context.Context, pod *backend.Po
 	if err != nil {
 		return nil, fmt.Errorf("failed to create request: %v", err)
 	}
-	resp, err := http.DefaultClient.Do(req)
+	resp, err := p.Client.Do(req)
 	if err != nil {
 		return nil, fmt.Errorf("failed to fetch metrics from %s: %w", pod.NamespacedName, err)
 	}
@@ -73,7 +77,7 @@ func (p *PodMetricsClientImpl) getMetricEndpoint(pod *backend.Pod, targetPortNum
 	if p.ModelServerMetricsPort == 0 {
 		p.ModelServerMetricsPort = targetPortNumber
 	}
-	return fmt.Sprintf("http://%s:%d%s", pod.Address, p.ModelServerMetricsPort, p.ModelServerMetricsPath)
+	return fmt.Sprintf("%s://%s:%d%s", p.ModelServerMetricsScheme, pod.Address, p.ModelServerMetricsPort, p.ModelServerMetricsPath)
 }
 
 // promToPodMetrics updates internal pod metrics with scraped Prometheus metrics.
diff --git a/pkg/epp/backend/metrics/types.go b/pkg/epp/backend/metrics/types.go
index 80b7085..a760ff4 100644
--- a/pkg/epp/backend/metrics/types.go
+++ b/pkg/epp/backend/metrics/types.go
@@ -24,6 +24,7 @@ import (
 
 	corev1 "k8s.io/api/core/v1"
 	"sigs.k8s.io/controller-runtime/pkg/log"
+
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/backend"
 )
 
diff --git a/pkg/epp/controller/inferencemodel_reconciler.go b/pkg/epp/controller/inferencemodel_reconciler.go
index 9ef87fd..cc06e5c 100644
--- a/pkg/epp/controller/inferencemodel_reconciler.go
+++ b/pkg/epp/controller/inferencemodel_reconciler.go
@@ -28,6 +28,7 @@ import (
 	"sigs.k8s.io/controller-runtime/pkg/event"
 	"sigs.k8s.io/controller-runtime/pkg/log"
 	"sigs.k8s.io/controller-runtime/pkg/predicate"
+
 	"sigs.k8s.io/gateway-api-inference-extension/apix/v1alpha2"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/datastore"
 	logutil "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/util/logging"
diff --git a/pkg/epp/controller/inferencepool_reconciler.go b/pkg/epp/controller/inferencepool_reconciler.go
index c983e5e..783ef86 100644
--- a/pkg/epp/controller/inferencepool_reconciler.go
+++ b/pkg/epp/controller/inferencepool_reconciler.go
@@ -24,6 +24,7 @@ import (
 	ctrl "sigs.k8s.io/controller-runtime"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 	"sigs.k8s.io/controller-runtime/pkg/log"
+
 	v1 "sigs.k8s.io/gateway-api-inference-extension/api/v1"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/datastore"
 	logutil "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/util/logging"
diff --git a/pkg/epp/controller/pod_reconciler.go b/pkg/epp/controller/pod_reconciler.go
index bf8cb44..9972b3c 100644
--- a/pkg/epp/controller/pod_reconciler.go
+++ b/pkg/epp/controller/pod_reconciler.go
@@ -29,6 +29,7 @@ import (
 	"sigs.k8s.io/controller-runtime/pkg/event"
 	"sigs.k8s.io/controller-runtime/pkg/log"
 	"sigs.k8s.io/controller-runtime/pkg/predicate"
+
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/datastore"
 	logutil "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/util/logging"
 	podutil "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/util/pod"
diff --git a/pkg/epp/datastore/datastore.go b/pkg/epp/datastore/datastore.go
index c676475..7275d6f 100644
--- a/pkg/epp/datastore/datastore.go
+++ b/pkg/epp/datastore/datastore.go
@@ -28,6 +28,7 @@ import (
 	"k8s.io/apimachinery/pkg/types"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 	"sigs.k8s.io/controller-runtime/pkg/log"
+
 	v1 "sigs.k8s.io/gateway-api-inference-extension/api/v1"
 	"sigs.k8s.io/gateway-api-inference-extension/apix/v1alpha2"
 	backendmetrics "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/backend/metrics"
diff --git a/pkg/epp/flowcontrol/framework/mocks/mocks.go b/pkg/epp/flowcontrol/framework/mocks/mocks.go
index 141b735..804ba71 100644
--- a/pkg/epp/flowcontrol/framework/mocks/mocks.go
+++ b/pkg/epp/flowcontrol/framework/mocks/mocks.go
@@ -21,7 +21,7 @@ import (
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/types"
 )
 
-// MockItemComparator provides a mock implementation of the `framework.ItemComparator` interface.
+// MockItemComparator is a simple stub mock for the `framework.ItemComparator` interface.
 type MockItemComparator struct {
 	FuncV      framework.ItemComparatorFunc
 	ScoreTypeV string
@@ -30,12 +30,11 @@ type MockItemComparator struct {
 func (m *MockItemComparator) Func() framework.ItemComparatorFunc { return m.FuncV }
 func (m *MockItemComparator) ScoreType() string                  { return m.ScoreTypeV }
 
-var _ framework.ItemComparator = &MockItemComparator{}
-
-// MockFlowQueueAccessor is a mock implementation of the `framework.FlowQueueAccessor` interface.
+// MockFlowQueueAccessor is a simple stub mock for the `framework.FlowQueueAccessor` interface.
+// It is used for tests that require static, predictable return values from a queue accessor.
+// For complex, stateful queue behavior, use the mock in `contracts/mocks.MockManagedQueue`.
 type MockFlowQueueAccessor struct {
 	NameV         string
-	CapabilitiesV []framework.QueueCapability
 	LenV          int
 	ByteSizeV     uint64
 	PeekHeadV     types.QueueItemAccessor
@@ -44,12 +43,15 @@ type MockFlowQueueAccessor struct {
 	PeekTailErrV  error
 	FlowSpecV     types.FlowSpecification
 	ComparatorV   framework.ItemComparator
+	CapabilitiesV []framework.QueueCapability
 }
 
 func (m *MockFlowQueueAccessor) Name() string                              { return m.NameV }
-func (m *MockFlowQueueAccessor) Capabilities() []framework.QueueCapability { return m.CapabilitiesV }
 func (m *MockFlowQueueAccessor) Len() int                                  { return m.LenV }
 func (m *MockFlowQueueAccessor) ByteSize() uint64                          { return m.ByteSizeV }
+func (m *MockFlowQueueAccessor) Comparator() framework.ItemComparator      { return m.ComparatorV }
+func (m *MockFlowQueueAccessor) FlowSpec() types.FlowSpecification         { return m.FlowSpecV }
+func (m *MockFlowQueueAccessor) Capabilities() []framework.QueueCapability { return m.CapabilitiesV }
 
 func (m *MockFlowQueueAccessor) PeekHead() (types.QueueItemAccessor, error) {
 	return m.PeekHeadV, m.PeekHeadErrV
@@ -59,51 +61,47 @@ func (m *MockFlowQueueAccessor) PeekTail() (types.QueueItemAccessor, error) {
 	return m.PeekTailV, m.PeekTailErrV
 }
 
-func (m *MockFlowQueueAccessor) Comparator() framework.ItemComparator { return m.ComparatorV }
-func (m *MockFlowQueueAccessor) FlowSpec() types.FlowSpecification    { return m.FlowSpecV }
-
 var _ framework.FlowQueueAccessor = &MockFlowQueueAccessor{}
 
-// MockPriorityBandAccessor is a mock implementation of the `framework.PriorityBandAccessor` interface.
+// MockPriorityBandAccessor is a behavioral mock for the `framework.MockPriorityBandAccessor` interface.
+// Simple accessors are configured with public value fields (e.g., `PriorityV`).
+// Complex methods with logic are configured with function fields (e.g., `IterateQueuesFunc`).
 type MockPriorityBandAccessor struct {
-	PriorityV      uint
-	PriorityNameV  string
-	FlowIDsV       []string
-	QueueV         framework.FlowQueueAccessor // Value to return for any Queue(flowID) call
-	QueueFuncV     func(flowID string) framework.FlowQueueAccessor
-	IterateQueuesV func(callback func(queue framework.FlowQueueAccessor) bool)
+	PriorityV         uint
+	PriorityNameV     string
+	FlowIDsFunc       func() []string
+	QueueFunc         func(flowID string) framework.FlowQueueAccessor
+	IterateQueuesFunc func(callback func(queue framework.FlowQueueAccessor) (keepIterating bool))
 }
 
 func (m *MockPriorityBandAccessor) Priority() uint       { return m.PriorityV }
 func (m *MockPriorityBandAccessor) PriorityName() string { return m.PriorityNameV }
-func (m *MockPriorityBandAccessor) FlowIDs() []string    { return m.FlowIDsV }
+
+func (m *MockPriorityBandAccessor) FlowIDs() []string {
+	if m.FlowIDsFunc != nil {
+		return m.FlowIDsFunc()
+	}
+	return nil
+}
 
 func (m *MockPriorityBandAccessor) Queue(flowID string) framework.FlowQueueAccessor {
-	if m.QueueFuncV != nil {
-		return m.QueueFuncV(flowID)
+	if m.QueueFunc != nil {
+		return m.QueueFunc(flowID)
 	}
-	return m.QueueV
+	return nil
 }
 
 func (m *MockPriorityBandAccessor) IterateQueues(callback func(queue framework.FlowQueueAccessor) bool) {
-	if m.IterateQueuesV != nil {
-		m.IterateQueuesV(callback)
-	} else {
-		// Default behavior: iterate based on FlowIDsV and QueueV/QueueFuncV
-		for _, id := range m.FlowIDsV {
-			q := m.Queue(id)
-			if q != nil { // Only call callback if queue exists
-				if !callback(q) {
-					return
-				}
-			}
-		}
+	if m.IterateQueuesFunc != nil {
+		m.IterateQueuesFunc(callback)
 	}
 }
 
 var _ framework.PriorityBandAccessor = &MockPriorityBandAccessor{}
 
-// MockSafeQueue is a mock implementation of the `framework.SafeQueue` interface.
+// MockSafeQueue is a simple stub mock for the `framework.SafeQueue` interface.
+// It is used for tests that need to control the exact return values of a queue's methods without simulating the queue's
+// internal logic or state.
 type MockSafeQueue struct {
 	NameV         string
 	CapabilitiesV []framework.QueueCapability
@@ -162,24 +160,48 @@ func (m *MockSafeQueue) Drain() ([]types.QueueItemAccessor, error) {
 
 var _ framework.SafeQueue = &MockSafeQueue{}
 
-// MockIntraFlowDispatchPolicy is a mock implementation of the `framework.IntraFlowDispatchPolicy` interface.
+// MockIntraFlowDispatchPolicy is a behavioral mock for the `framework.IntraFlowDispatchPolicy` interface.
+// Simple accessors are configured with public value fields (e.g., `NameV`).
+// Complex methods with logic are configured with function fields (e.g., `SelectItemFunc`).
 type MockIntraFlowDispatchPolicy struct {
 	NameV                      string
-	SelectItemV                types.QueueItemAccessor
-	SelectItemErrV             error
 	ComparatorV                framework.ItemComparator
 	RequiredQueueCapabilitiesV []framework.QueueCapability
+	SelectItemFunc             func(queue framework.FlowQueueAccessor) (types.QueueItemAccessor, error)
 }
 
 func (m *MockIntraFlowDispatchPolicy) Name() string                         { return m.NameV }
 func (m *MockIntraFlowDispatchPolicy) Comparator() framework.ItemComparator { return m.ComparatorV }
+func (m *MockIntraFlowDispatchPolicy) RequiredQueueCapabilities() []framework.QueueCapability {
+	return m.RequiredQueueCapabilitiesV
+}
 
 func (m *MockIntraFlowDispatchPolicy) SelectItem(queue framework.FlowQueueAccessor) (types.QueueItemAccessor, error) {
-	return m.SelectItemV, m.SelectItemErrV
+	if m.SelectItemFunc != nil {
+		return m.SelectItemFunc(queue)
+	}
+	return nil, nil
 }
 
-func (m *MockIntraFlowDispatchPolicy) RequiredQueueCapabilities() []framework.QueueCapability {
-	return m.RequiredQueueCapabilitiesV
+var _ framework.IntraFlowDispatchPolicy = &MockIntraFlowDispatchPolicy{}
+
+// MockInterFlowDispatchPolicy is a behavioral mock for the `framework.InterFlowDispatchPolicy` interface.
+// Simple accessors are configured with public value fields (e.g., `NameV`).
+// Complex methods with logic are configured with function fields (e.g., `SelectQueueFunc`).
+type MockInterFlowDispatchPolicy struct {
+	NameV           string
+	SelectQueueFunc func(band framework.PriorityBandAccessor) (framework.FlowQueueAccessor, error)
 }
 
-var _ framework.IntraFlowDispatchPolicy = &MockIntraFlowDispatchPolicy{}
+func (m *MockInterFlowDispatchPolicy) Name() string {
+	return m.NameV
+}
+
+func (m *MockInterFlowDispatchPolicy) SelectQueue(band framework.PriorityBandAccessor) (framework.FlowQueueAccessor, error) {
+	if m.SelectQueueFunc != nil {
+		return m.SelectQueueFunc(band)
+	}
+	return nil, nil
+}
+
+var _ framework.InterFlowDispatchPolicy = &MockInterFlowDispatchPolicy{}
diff --git a/pkg/epp/handlers/request.go b/pkg/epp/handlers/request.go
index ab93e02..5789b3c 100644
--- a/pkg/epp/handlers/request.go
+++ b/pkg/epp/handlers/request.go
@@ -24,6 +24,7 @@ import (
 	configPb "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
 	extProcPb "github.com/envoyproxy/go-control-plane/envoy/service/ext_proc/v3"
 	"google.golang.org/protobuf/types/known/structpb"
+
 	errutil "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/util/error"
 )
 
diff --git a/pkg/epp/handlers/response.go b/pkg/epp/handlers/response.go
index a776bd1..47c0b9d 100644
--- a/pkg/epp/handlers/response.go
+++ b/pkg/epp/handlers/response.go
@@ -24,6 +24,7 @@ import (
 	configPb "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
 	extProcPb "github.com/envoyproxy/go-control-plane/envoy/service/ext_proc/v3"
 	"sigs.k8s.io/controller-runtime/pkg/log"
+
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/metrics"
 	logutil "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/util/logging"
 )
diff --git a/pkg/epp/handlers/server.go b/pkg/epp/handlers/server.go
index d4a5ade..b8e6f52 100644
--- a/pkg/epp/handlers/server.go
+++ b/pkg/epp/handlers/server.go
@@ -29,6 +29,7 @@ import (
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
 	"sigs.k8s.io/controller-runtime/pkg/log"
+
 	v1 "sigs.k8s.io/gateway-api-inference-extension/api/v1"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/backend"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/metrics"
diff --git a/pkg/epp/plugins/handle.go b/pkg/epp/plugins/handle.go
index f00aa50..8c9153c 100644
--- a/pkg/epp/plugins/handle.go
+++ b/pkg/epp/plugins/handle.go
@@ -44,6 +44,55 @@ type HandlePlugins interface {
 	GetAllPluginsWithNames() map[string]Plugin
 }
 
+// eppHandle is an implementation of the interface plugins.Handle
+type eppHandle struct {
+	ctx context.Context
+	HandlePlugins
+}
+
+// Context returns a context the plugins can use, if they need one
+func (h *eppHandle) Context() context.Context {
+	return h.ctx
+}
+
+// eppHandlePlugins implements the set of APIs to work with instantiated plugins
+type eppHandlePlugins struct {
+	plugins map[string]Plugin
+}
+
+// Plugin returns the named plugin instance
+func (h *eppHandlePlugins) Plugin(name string) Plugin {
+	return h.plugins[name]
+}
+
+// AddPlugin adds a plugin to the set of known plugin instances
+func (h *eppHandlePlugins) AddPlugin(name string, plugin Plugin) {
+	h.plugins[name] = plugin
+}
+
+// GetAllPlugins returns all of the known plugins
+func (h *eppHandlePlugins) GetAllPlugins() []Plugin {
+	result := make([]Plugin, 0)
+	for _, plugin := range h.plugins {
+		result = append(result, plugin)
+	}
+	return result
+}
+
+// GetAllPluginsWithNames returns al of the known plugins with their names
+func (h *eppHandlePlugins) GetAllPluginsWithNames() map[string]Plugin {
+	return h.plugins
+}
+
+func NewEppHandle(ctx context.Context) Handle {
+	return &eppHandle{
+		ctx: ctx,
+		HandlePlugins: &eppHandlePlugins{
+			plugins: map[string]Plugin{},
+		},
+	}
+}
+
 // PluginByType retrieves the specified plugin by name and verifies its type
 func PluginByType[P Plugin](handlePlugins HandlePlugins, name string) (P, error) {
 	var zero P
diff --git a/pkg/epp/requestcontrol/director.go b/pkg/epp/requestcontrol/director.go
index 2ad28b8..39337d4 100644
--- a/pkg/epp/requestcontrol/director.go
+++ b/pkg/epp/requestcontrol/director.go
@@ -29,6 +29,7 @@ import (
 
 	"github.com/go-logr/logr"
 	"sigs.k8s.io/controller-runtime/pkg/log"
+
 	"sigs.k8s.io/gateway-api-inference-extension/apix/v1alpha2"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/backend"
 	backendmetrics "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/backend/metrics"
diff --git a/pkg/epp/saturationdetector/config.go b/pkg/epp/saturationdetector/config.go
index 78a5833..54cd21c 100644
--- a/pkg/epp/saturationdetector/config.go
+++ b/pkg/epp/saturationdetector/config.go
@@ -20,6 +20,7 @@ import (
 	"time"
 
 	"sigs.k8s.io/controller-runtime/pkg/log"
+
 	commonconfig "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/common/config"
 	envutil "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/util/env"
 )
diff --git a/pkg/epp/saturationdetector/saturationdetector.go b/pkg/epp/saturationdetector/saturationdetector.go
index 6ac0881..59a2648 100644
--- a/pkg/epp/saturationdetector/saturationdetector.go
+++ b/pkg/epp/saturationdetector/saturationdetector.go
@@ -36,6 +36,7 @@ import (
 
 	"github.com/go-logr/logr"
 	"sigs.k8s.io/controller-runtime/pkg/log"
+
 	backendmetrics "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/backend/metrics"
 	logutil "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/util/logging"
 )
diff --git a/pkg/epp/scheduling/config/config.go b/pkg/epp/scheduling/config/config.go
index e7fd0a3..a96184d 100644
--- a/pkg/epp/scheduling/config/config.go
+++ b/pkg/epp/scheduling/config/config.go
@@ -18,6 +18,7 @@ package config
 
 import (
 	"sigs.k8s.io/controller-runtime/pkg/log"
+
 	commonconfig "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/common/config"
 	envutil "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/util/env"
 	logutil "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/util/logging"
diff --git a/pkg/epp/scheduling/framework/plugins/filter/decision_tree_filter.go b/pkg/epp/scheduling/framework/plugins/filter/decision_tree_filter.go
index a9a0a7c..df39231 100644
--- a/pkg/epp/scheduling/framework/plugins/filter/decision_tree_filter.go
+++ b/pkg/epp/scheduling/framework/plugins/filter/decision_tree_filter.go
@@ -23,6 +23,7 @@ import (
 	"fmt"
 
 	"sigs.k8s.io/controller-runtime/pkg/log"
+
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/plugins"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/scheduling/framework"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/scheduling/types"
diff --git a/pkg/epp/scheduling/framework/plugins/filter/low_queue_filter.go b/pkg/epp/scheduling/framework/plugins/filter/low_queue_filter.go
index 597c2a1..e3d4de9 100644
--- a/pkg/epp/scheduling/framework/plugins/filter/low_queue_filter.go
+++ b/pkg/epp/scheduling/framework/plugins/filter/low_queue_filter.go
@@ -18,9 +18,8 @@ package filter
 
 import (
 	"context"
-	"fmt"
-
 	"encoding/json"
+	"fmt"
 
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/plugins"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/scheduling/config"
diff --git a/pkg/epp/scheduling/framework/plugins/multi/prefix/indexer.go b/pkg/epp/scheduling/framework/plugins/multi/prefix/indexer.go
index 1b75f0f..0a209a8 100644
--- a/pkg/epp/scheduling/framework/plugins/multi/prefix/indexer.go
+++ b/pkg/epp/scheduling/framework/plugins/multi/prefix/indexer.go
@@ -23,6 +23,7 @@ import (
 
 	lru "github.com/hashicorp/golang-lru/v2"
 	"sigs.k8s.io/controller-runtime/pkg/log"
+
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/metrics"
 	logutil "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/util/logging"
 )
diff --git a/pkg/epp/scheduling/framework/plugins/multi/prefix/plugin.go b/pkg/epp/scheduling/framework/plugins/multi/prefix/plugin.go
index 42e6303..64c23bf 100644
--- a/pkg/epp/scheduling/framework/plugins/multi/prefix/plugin.go
+++ b/pkg/epp/scheduling/framework/plugins/multi/prefix/plugin.go
@@ -25,6 +25,7 @@ import (
 	"github.com/cespare/xxhash/v2"
 	k8stypes "k8s.io/apimachinery/pkg/types"
 	"sigs.k8s.io/controller-runtime/pkg/log"
+
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/metrics"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/plugins"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/scheduling/framework"
diff --git a/pkg/epp/scheduling/framework/plugins/picker/max_score_picker.go b/pkg/epp/scheduling/framework/plugins/picker/max_score_picker.go
index bf3ca8d..e7ee333 100644
--- a/pkg/epp/scheduling/framework/plugins/picker/max_score_picker.go
+++ b/pkg/epp/scheduling/framework/plugins/picker/max_score_picker.go
@@ -20,7 +20,9 @@ import (
 	"context"
 	"encoding/json"
 	"fmt"
+	"math/rand"
 	"slices"
+	"time"
 
 	"sigs.k8s.io/controller-runtime/pkg/log"
 
@@ -58,13 +60,15 @@ func NewMaxScorePicker(maxNumOfEndpoints int) *MaxScorePicker {
 	return &MaxScorePicker{
 		typedName:         plugins.TypedName{Type: MaxScorePickerType, Name: MaxScorePickerType},
 		maxNumOfEndpoints: maxNumOfEndpoints,
+		randomGenerator:   rand.New(rand.NewSource(time.Now().UnixNano())),
 	}
 }
 
 // MaxScorePicker picks pod(s) with the maximum score from the list of candidates.
 type MaxScorePicker struct {
 	typedName         plugins.TypedName
-	maxNumOfEndpoints int // maximum number of endpoints to pick
+	maxNumOfEndpoints int        // maximum number of endpoints to pick
+	randomGenerator   *rand.Rand // randomGenerator for randomly pick endpoint on tie-break
 }
 
 // WithName sets the picker's name
@@ -83,6 +87,11 @@ func (p *MaxScorePicker) Pick(ctx context.Context, cycleState *types.CycleState,
 	log.FromContext(ctx).V(logutil.DEBUG).Info(fmt.Sprintf("Selecting maximum '%d' pods from %d candidates sorted by max score: %+v", p.maxNumOfEndpoints,
 		len(scoredPods), scoredPods))
 
+	// Shuffle in-place - needed for random tie break when scores are equal
+	p.randomGenerator.Shuffle(len(scoredPods), func(i, j int) {
+		scoredPods[i], scoredPods[j] = scoredPods[j], scoredPods[i]
+	})
+
 	slices.SortStableFunc(scoredPods, func(i, j *types.ScoredPod) int { // highest score first
 		if i.Score > j.Score {
 			return -1
diff --git a/pkg/epp/scheduling/framework/plugins/picker/random_picker.go b/pkg/epp/scheduling/framework/plugins/picker/random_picker.go
index bb272f1..eb62c37 100644
--- a/pkg/epp/scheduling/framework/plugins/picker/random_picker.go
+++ b/pkg/epp/scheduling/framework/plugins/picker/random_picker.go
@@ -21,6 +21,7 @@ import (
 	"encoding/json"
 	"fmt"
 	"math/rand"
+	"time"
 
 	"sigs.k8s.io/controller-runtime/pkg/log"
 
@@ -57,6 +58,7 @@ func NewRandomPicker(maxNumOfEndpoints int) *RandomPicker {
 	return &RandomPicker{
 		typedName:         plugins.TypedName{Type: RandomPickerType, Name: RandomPickerType},
 		maxNumOfEndpoints: maxNumOfEndpoints,
+		randomGenerator:   rand.New(rand.NewSource(time.Now().UnixNano())),
 	}
 }
 
@@ -64,6 +66,7 @@ func NewRandomPicker(maxNumOfEndpoints int) *RandomPicker {
 type RandomPicker struct {
 	typedName         plugins.TypedName
 	maxNumOfEndpoints int
+	randomGenerator   *rand.Rand // randomGenerator for randomly pick endpoint on tie-break
 }
 
 // WithName sets the name of the picker.
@@ -83,7 +86,7 @@ func (p *RandomPicker) Pick(ctx context.Context, _ *types.CycleState, scoredPods
 		len(scoredPods), scoredPods))
 
 	// Shuffle in-place
-	rand.Shuffle(len(scoredPods), func(i, j int) {
+	p.randomGenerator.Shuffle(len(scoredPods), func(i, j int) {
 		scoredPods[i], scoredPods[j] = scoredPods[j], scoredPods[i]
 	})
 
diff --git a/pkg/epp/scheduling/framework/scheduler_profile.go b/pkg/epp/scheduling/framework/scheduler_profile.go
index c65d201..0ca806d 100644
--- a/pkg/epp/scheduling/framework/scheduler_profile.go
+++ b/pkg/epp/scheduling/framework/scheduler_profile.go
@@ -22,6 +22,7 @@ import (
 	"time"
 
 	"sigs.k8s.io/controller-runtime/pkg/log"
+
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/metrics"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/plugins"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/scheduling/types"
diff --git a/pkg/epp/scheduling/scheduler.go b/pkg/epp/scheduling/scheduler.go
index 51e188d..231b29e 100644
--- a/pkg/epp/scheduling/scheduler.go
+++ b/pkg/epp/scheduling/scheduler.go
@@ -23,6 +23,7 @@ import (
 	"time"
 
 	"sigs.k8s.io/controller-runtime/pkg/log"
+
 	backendmetrics "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/backend/metrics"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/metrics"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/scheduling/framework"
diff --git a/pkg/epp/server/controller_manager.go b/pkg/epp/server/controller_manager.go
index 969c098..7ab935e 100644
--- a/pkg/epp/server/controller_manager.go
+++ b/pkg/epp/server/controller_manager.go
@@ -31,6 +31,7 @@ import (
 	"sigs.k8s.io/controller-runtime/pkg/client"
 	"sigs.k8s.io/controller-runtime/pkg/manager"
 	metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
+
 	v1 "sigs.k8s.io/gateway-api-inference-extension/api/v1"
 	"sigs.k8s.io/gateway-api-inference-extension/apix/v1alpha2"
 )
diff --git a/pkg/epp/server/runserver.go b/pkg/epp/server/runserver.go
index de14a2d..b0afb23 100644
--- a/pkg/epp/server/runserver.go
+++ b/pkg/epp/server/runserver.go
@@ -31,6 +31,7 @@ import (
 	"k8s.io/apimachinery/pkg/types"
 	ctrl "sigs.k8s.io/controller-runtime"
 	"sigs.k8s.io/controller-runtime/pkg/manager"
+
 	"sigs.k8s.io/gateway-api-inference-extension/internal/runnable"
 	tlsutil "sigs.k8s.io/gateway-api-inference-extension/internal/tls"
 	backendmetrics "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/backend/metrics"
diff --git a/pkg/generator/main.go b/pkg/generator/main.go
index 6ca70ed..641cc12 100644
--- a/pkg/generator/main.go
+++ b/pkg/generator/main.go
@@ -25,8 +25,9 @@ import (
 	"sigs.k8s.io/controller-tools/pkg/crd"
 	"sigs.k8s.io/controller-tools/pkg/loader"
 	"sigs.k8s.io/controller-tools/pkg/markers"
-	"sigs.k8s.io/gateway-api-inference-extension/version"
 	"sigs.k8s.io/yaml"
+
+	"sigs.k8s.io/gateway-api-inference-extension/version"
 )
 
 // This generation code is largely copied from
diff --git a/site-src/api-types/inferencepool.md b/site-src/api-types/inferencepool.md
index 1494d31..d279447 100644
--- a/site-src/api-types/inferencepool.md
+++ b/site-src/api-types/inferencepool.md
@@ -28,7 +28,7 @@ In summary, the InferencePoolSpec consists of 3 major parts:
 Here is an example InferencePool configuration:
 
 ```
-apiVersion: inference.networking.x-k8s.io/v1alpha2
+apiVersion: inference.networking.k8s.io/v1
 kind: InferencePool
 metadata:
   name: vllm-llama3-8b-instruct
diff --git a/site-src/contributing/devguide.md b/site-src/contributing/devguide.md
deleted file mode 100644
index bc0ceab..0000000
--- a/site-src/contributing/devguide.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# Developer Guide
-
-TODO
\ No newline at end of file
diff --git a/site-src/guides/implementers.md b/site-src/guides/implementers.md
index fe3b018..4fb6ee7 100644
--- a/site-src/guides/implementers.md
+++ b/site-src/guides/implementers.md
@@ -22,7 +22,7 @@ spec:
     name: inference-gateway
   rules:
   - backendRefs:
-    - group: inference.networking.x-k8s.io
+    - group: inference.networking.k8s.io
       kind: InferencePool
       name: base-model
     matches:
@@ -42,7 +42,7 @@ The general idea of implementing a Gateway controller supporting the InferencePo
 ### Endpoint Tracking
 Consider a simple inference pool like this:
 ```
-apiVersion: inference.networking.x-k8s.io/v1alpha2
+apiVersion: inference.networking.k8s.io/v1
 kind: InferencePool
 metadata:
   name: vllm-llama3-8b-instruct
diff --git a/site-src/guides/inferencepool-rollout.md b/site-src/guides/inferencepool-rollout.md
index c02db5b..88bfe07 100644
--- a/site-src/guides/inferencepool-rollout.md
+++ b/site-src/guides/inferencepool-rollout.md
@@ -204,7 +204,7 @@ data:
         - id: food-review-1
           source: Kawon/llama3.1-food-finetune_v14_r8
 ---
-apiVersion: inference.networking.x-k8s.io/v1alpha2
+apiVersion: inference.networking.k8s.io/v1
 kind: InferencePool
 metadata:
   name: vllm-llama3-8b-instruct-new
@@ -400,11 +400,11 @@ spec:
       name: inference-gateway
   rules:
     - backendRefs:
-        - group: inference.networking.x-k8s.io
+        - group: inference.networking.k8s.io
           kind: InferencePool
           name: vllm-llama3-8b-instruct
           weight: 90
-        - group: inference.networking.x-k8s.io
+        - group: inference.networking.k8s.io
           kind: InferencePool
           name: vllm-llama3-8b-instruct-new
           weight: 10
@@ -448,7 +448,7 @@ spec:
       name: inference-gateway
   rules:
     - backendRefs:
-        - group: inference.networking.x-k8s.io
+        - group: inference.networking.k8s.io
           kind: InferencePool
           name: vllm-llama3-8b-instruct-new
           weight: 100
diff --git a/site-src/reference/spec.md b/site-src/reference/spec.md
index 263f54d..4260597 100644
--- a/site-src/reference/spec.md
+++ b/site-src/reference/spec.md
@@ -1,42 +1,20 @@
 # API Reference
 
 ## Packages
-- [inference.networking.x-k8s.io/v1alpha2](#inferencenetworkingx-k8siov1alpha2)
+- [inference.networking.k8s.io/v1](#inferencenetworkingk8siov1)
 
 
-## inference.networking.x-k8s.io/v1alpha2
+## inference.networking.k8s.io/v1
 
-Package v1alpha2 contains API Schema definitions for the
-inference.networking.x-k8s.io API group.
+Package v1 contains API Schema definitions for the
+inference.networking.k8s.io API group.
 
 
 ### Resource Types
-- [InferenceModel](#inferencemodel)
 - [InferencePool](#inferencepool)
 
 
 
-#### Criticality
-
-_Underlying type:_ _string_
-
-Criticality defines how important it is to serve the model compared to other models.
-Criticality is intentionally a bounded enum to contain the possibilities that need to be supported by the load balancing algorithm. Any reference to the Criticality field must be optional(use a pointer), and set no default.
-This allows us to union this with a oneOf field in the future should we wish to adjust/extend this behavior.
-
-_Validation:_
-- Enum: [Critical Standard Sheddable]
-
-_Appears in:_
-- [InferenceModelSpec](#inferencemodelspec)
-
-| Field | Description |
-| --- | --- |
-| `Critical` | Critical defines the highest level of criticality. Requests to this band will be shed last.<br /> |
-| `Standard` | Standard defines the base criticality level and is more important than Sheddable but less<br />important than Critical. Requests in this band will be shed before critical traffic.<br />Most models are expected to fall within this band.<br /> |
-| `Sheddable` | Sheddable defines the lowest level of criticality. Requests to this band will be shed before<br />all other bands.<br /> |
-
-
 #### EndpointPickerConfig
 
 
@@ -69,7 +47,7 @@ _Appears in:_
 | Field | Description | Default | Validation |
 | --- | --- | --- | --- |
 | `group` _[Group](#group)_ | Group is the group of the referent.<br />The default value is "", representing the Core API group. |  | MaxLength: 253 <br />Pattern: `^$\|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` <br /> |
-| `kind` _[Kind](#kind)_ | Kind is the Kubernetes resource kind of the referent. For example<br />"Service".<br />Defaults to "Service" when not specified.<br />ExternalName services can refer to CNAME DNS records that may live<br />outside of the cluster and as such are difficult to reason about in<br />terms of conformance. They also may not be safe to forward to (see<br />CVE-2021-25740 for more information). Implementations MUST NOT<br />support ExternalName Services. | Service | MaxLength: 63 <br />MinLength: 1 <br />Pattern: `^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$` <br /> |
+| `kind` _[Kind](#kind)_ | Kind is the Kubernetes resource kind of the referent.<br />Defaults to "Service" when not specified.<br />ExternalName services can refer to CNAME DNS records that may live<br />outside of the cluster and as such are difficult to reason about in<br />terms of conformance. They also may not be safe to forward to (see<br />CVE-2021-25740 for more information). Implementations MUST NOT<br />support ExternalName Services. | Service | MaxLength: 63 <br />MinLength: 1 <br />Pattern: `^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$` <br /> |
 | `name` _[ObjectName](#objectname)_ | Name is the name of the referent. |  | MaxLength: 253 <br />MinLength: 1 <br />Required: \{\} <br /> |
 | `portNumber` _[PortNumber](#portnumber)_ | The port number on the service running the extension. When unspecified,<br />implementations SHOULD infer a default value of 9002 when the Kind is<br />Service. |  | Maximum: 65535 <br />Minimum: 1 <br /> |
 | `failureMode` _[ExtensionFailureMode](#extensionfailuremode)_ | Configures how the gateway handles the case when the extension is not responsive.<br />Defaults to failClose. | FailClose | Enum: [FailOpen FailClose] <br /> |
@@ -107,15 +85,19 @@ _Appears in:_
 
 | Field | Description |
 | --- | --- |
-| `FailOpen` | FailOpen specifies that the proxy should not drop the request and forward the request to and endpoint of its picking.<br /> |
-| `FailClose` | FailClose specifies that the proxy should drop the request.<br /> |
+| `FailOpen` | FailOpen specifies that the proxy should forward the request to an endpoint of its picking when the Endpoint Picker fails.<br /> |
+| `FailClose` | FailClose specifies that the proxy should drop the request when the Endpoint Picker fails.<br /> |
 
 
 #### ExtensionReference
 
 
 
-ExtensionReference is a reference to the extension deployment.
+ExtensionReference is a reference to the extension.
+
+If a reference is invalid, the implementation MUST update the `ResolvedRefs`
+Condition on the InferencePool's status to `status: False`. A 5XX status code MUST be returned
+for the request that would have otherwise been routed to the invalid backend.
 
 
 
@@ -125,7 +107,7 @@ _Appears in:_
 | Field | Description | Default | Validation |
 | --- | --- | --- | --- |
 | `group` _[Group](#group)_ | Group is the group of the referent.<br />The default value is "", representing the Core API group. |  | MaxLength: 253 <br />Pattern: `^$\|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` <br /> |
-| `kind` _[Kind](#kind)_ | Kind is the Kubernetes resource kind of the referent. For example<br />"Service".<br />Defaults to "Service" when not specified.<br />ExternalName services can refer to CNAME DNS records that may live<br />outside of the cluster and as such are difficult to reason about in<br />terms of conformance. They also may not be safe to forward to (see<br />CVE-2021-25740 for more information). Implementations MUST NOT<br />support ExternalName Services. | Service | MaxLength: 63 <br />MinLength: 1 <br />Pattern: `^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$` <br /> |
+| `kind` _[Kind](#kind)_ | Kind is the Kubernetes resource kind of the referent.<br />Defaults to "Service" when not specified.<br />ExternalName services can refer to CNAME DNS records that may live<br />outside of the cluster and as such are difficult to reason about in<br />terms of conformance. They also may not be safe to forward to (see<br />CVE-2021-25740 for more information). Implementations MUST NOT<br />support ExternalName Services. | Service | MaxLength: 63 <br />MinLength: 1 <br />Pattern: `^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$` <br /> |
 | `name` _[ObjectName](#objectname)_ | Name is the name of the referent. |  | MaxLength: 253 <br />MinLength: 1 <br />Required: \{\} <br /> |
 | `portNumber` _[PortNumber](#portnumber)_ | The port number on the service running the extension. When unspecified,<br />implementations SHOULD infer a default value of 9002 when the Kind is<br />Service. |  | Maximum: 65535 <br />Minimum: 1 <br /> |
 
@@ -157,80 +139,8 @@ _Validation:_
 _Appears in:_
 - [Extension](#extension)
 - [ExtensionReference](#extensionreference)
-- [PoolObjectReference](#poolobjectreference)
-
-
-
-#### InferenceModel
-
-
-
-InferenceModel is the Schema for the InferenceModels API.
-
-
-
-
-
-| Field | Description | Default | Validation |
-| --- | --- | --- | --- |
-| `apiVersion` _string_ | `inference.networking.x-k8s.io/v1alpha2` | | |
-| `kind` _string_ | `InferenceModel` | | |
-| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. |  |  |
-| `spec` _[InferenceModelSpec](#inferencemodelspec)_ |  |  |  |
-| `status` _[InferenceModelStatus](#inferencemodelstatus)_ |  |  |  |
-
-
-
-
-
-
-#### InferenceModelSpec
-
-
-
-InferenceModelSpec represents the desired state of a specific model use case. This resource is
-managed by the "Inference Workload Owner" persona.
-
-The Inference Workload Owner persona is someone that trains, verifies, and
-leverages a large language model from a model frontend, drives the lifecycle
-and rollout of new versions of those models, and defines the specific
-performance and latency goals for the model. These workloads are
-expected to operate within an InferencePool sharing compute capacity with other
-InferenceModels, defined by the Inference Platform Admin.
-
-InferenceModel's modelName (not the ObjectMeta name) is unique for a given InferencePool,
-if the name is reused, an error will be shown on the status of a
-InferenceModel that attempted to reuse. The oldest InferenceModel, based on
-creation timestamp, will be selected to remain valid. In the event of a race
-condition, one will be selected at random.
-
-
-
-_Appears in:_
-- [InferenceModel](#inferencemodel)
-
-| Field | Description | Default | Validation |
-| --- | --- | --- | --- |
-| `modelName` _string_ | ModelName is the name of the model as it will be set in the "model" parameter for an incoming request.<br />ModelNames must be unique for a referencing InferencePool<br />(names can be reused for a different pool in the same cluster).<br />The modelName with the oldest creation timestamp is retained, and the incoming<br />InferenceModel's Ready status is set to false with a corresponding reason.<br />In the rare case of a race condition, one Model will be selected randomly to be considered valid, and the other rejected.<br />Names can be reserved without an underlying model configured in the pool.<br />This can be done by specifying a target model and setting the weight to zero,<br />an error will be returned specifying that no valid target model is found. |  | MaxLength: 256 <br />Required: \{\} <br /> |
-| `criticality` _[Criticality](#criticality)_ | Criticality defines how important it is to serve the model compared to other models referencing the same pool.<br />Criticality impacts how traffic is handled in resource constrained situations. It handles this by<br />queuing or rejecting requests of lower criticality. InferenceModels of an equivalent Criticality will<br />fairly share resources over throughput of tokens. In the future, the metric used to calculate fairness,<br />and the proportionality of fairness will be configurable.<br />Default values for this field will not be set, to allow for future additions of new field that may 'one of' with this field.<br />Any implementations that may consume this field may treat an unset value as the 'Standard' range. |  | Enum: [Critical Standard Sheddable] <br /> |
-| `targetModels` _[TargetModel](#targetmodel) array_ | TargetModels allow multiple versions of a model for traffic splitting.<br />If not specified, the target model name is defaulted to the modelName parameter.<br />modelName is often in reference to a LoRA adapter. |  | MaxItems: 10 <br /> |
-| `poolRef` _[PoolObjectReference](#poolobjectreference)_ | PoolRef is a reference to the inference pool, the pool must exist in the same namespace. |  | Required: \{\} <br /> |
-
+- [ParentGatewayReference](#parentgatewayreference)
 
-#### InferenceModelStatus
-
-
-
-InferenceModelStatus defines the observed state of InferenceModel
-
-
-
-_Appears in:_
-- [InferenceModel](#inferencemodel)
-
-| Field | Description | Default | Validation |
-| --- | --- | --- | --- |
-| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#condition-v1-meta) array_ | Conditions track the state of the InferenceModel.<br />Known condition types are:<br />* "Accepted" | [map[lastTransitionTime:1970-01-01T00:00:00Z message:Waiting for controller reason:Pending status:Unknown type:Ready]] | MaxItems: 8 <br /> |
 
 
 #### InferencePool
@@ -243,13 +153,14 @@ InferencePool is the Schema for the InferencePools API.
 
 
 
+
 | Field | Description | Default | Validation |
 | --- | --- | --- | --- |
-| `apiVersion` _string_ | `inference.networking.x-k8s.io/v1alpha2` | | |
+| `apiVersion` _string_ | `inference.networking.k8s.io/v1` | | |
 | `kind` _string_ | `InferencePool` | | |
 | `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. |  |  |
 | `spec` _[InferencePoolSpec](#inferencepoolspec)_ |  |  |  |
-| `status` _[InferencePoolStatus](#inferencepoolstatus)_ |  |  |  |
+| `status` _[InferencePoolStatus](#inferencepoolstatus)_ | Status defines the observed state of InferencePool. | \{ parent:[map[conditions:[map[lastTransitionTime:1970-01-01T00:00:00Z message:Waiting for controller reason:Pending status:Unknown type:Accepted]] parentRef:map[kind:Status name:default]]] \} |  |
 
 
 
@@ -269,8 +180,8 @@ _Appears in:_
 
 | Field | Description | Default | Validation |
 | --- | --- | --- | --- |
-| `selector` _object (keys:[LabelKey](#labelkey), values:[LabelValue](#labelvalue))_ | Selector defines a map of labels to watch model server pods<br />that should be included in the InferencePool.<br />In some cases, implementations may translate this field to a Service selector, so this matches the simple<br />map used for Service selectors instead of the full Kubernetes LabelSelector type.<br />If sepecified, it will be applied to match the model server pods in the same namespace as the InferencePool.<br />Cross namesoace selector is not supported. |  | Required: \{\} <br /> |
-| `targetPortNumber` _integer_ | TargetPortNumber defines the port number to access the selected model servers.<br />The number must be in the range 1 to 65535. |  | Maximum: 65535 <br />Minimum: 1 <br />Required: \{\} <br /> |
+| `selector` _object (keys:[LabelKey](#labelkey), values:[LabelValue](#labelvalue))_ | Selector defines a map of labels to watch model server Pods<br />that should be included in the InferencePool.<br />In some cases, implementations may translate this field to a Service selector, so this matches the simple<br />map used for Service selectors instead of the full Kubernetes LabelSelector type.<br />If specified, it will be applied to match the model server pods in the same namespace as the InferencePool.<br />Cross namesoace selector is not supported. |  | Required: \{\} <br /> |
+| `targetPortNumber` _integer_ | TargetPortNumber defines the port number to access the selected model server Pods.<br />The number must be in the range 1 to 65535. |  | Maximum: 65535 <br />Minimum: 1 <br />Required: \{\} <br /> |
 | `extensionRef` _[Extension](#extension)_ | Extension configures an endpoint picker as an extension service. |  | Required: \{\} <br /> |
 
 
@@ -278,7 +189,7 @@ _Appears in:_
 
 
 
-InferencePoolStatus defines the observed state of InferencePool
+InferencePoolStatus defines the observed state of InferencePool.
 
 
 
@@ -287,7 +198,7 @@ _Appears in:_
 
 | Field | Description | Default | Validation |
 | --- | --- | --- | --- |
-| `parent` _[PoolStatus](#poolstatus) array_ | Parents is a list of parent resources (usually Gateways) that are<br />associated with the route, and the status of the InferencePool with respect to<br />each parent.<br />A maximum of 32 Gateways will be represented in this list. An empty list<br />means the route has not been attached to any Gateway. |  | MaxItems: 32 <br /> |
+| `parent` _[PoolStatus](#poolstatus) array_ | Parents is a list of parent resources (usually Gateways) that are<br />associated with the InferencePool, and the status of the InferencePool with respect to<br />each parent.<br />A maximum of 32 Gateways will be represented in this list. When the list contains<br />`kind: Status, name: default`, it indicates that the InferencePool is not<br />associated with any Gateway and a controller must perform the following:<br /> - Remove the parent when setting the "Accepted" condition.<br /> - Add the parent when the controller will no longer manage the InferencePool<br />   and no other parents exist. |  | MaxItems: 32 <br /> |
 
 
 #### Kind
@@ -313,7 +224,7 @@ _Validation:_
 _Appears in:_
 - [Extension](#extension)
 - [ExtensionReference](#extensionreference)
-- [PoolObjectReference](#poolobjectreference)
+- [ParentGatewayReference](#parentgatewayreference)
 
 
 
@@ -376,6 +287,36 @@ _Appears in:_
 
 
 
+#### Namespace
+
+_Underlying type:_ _string_
+
+Namespace refers to a Kubernetes namespace. It must be a RFC 1123 label.
+
+This validation is based off of the corresponding Kubernetes validation:
+https://github.com/kubernetes/apimachinery/blob/02cfb53916346d085a6c6c7c66f882e3c6b0eca6/pkg/util/validation/validation.go#L187
+
+This is used for Namespace name validation here:
+https://github.com/kubernetes/apimachinery/blob/02cfb53916346d085a6c6c7c66f882e3c6b0eca6/pkg/api/validation/generic.go#L63
+
+Valid values include:
+
+* "example"
+
+Invalid values include:
+
+* "example.com" - "." is an invalid character
+
+_Validation:_
+- MaxLength: 63
+- MinLength: 1
+- Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?$`
+
+_Appears in:_
+- [ParentGatewayReference](#parentgatewayreference)
+
+
+
 #### ObjectName
 
 _Underlying type:_ _string_
@@ -391,27 +332,28 @@ _Validation:_
 _Appears in:_
 - [Extension](#extension)
 - [ExtensionReference](#extensionreference)
-- [PoolObjectReference](#poolobjectreference)
+- [ParentGatewayReference](#parentgatewayreference)
 
 
 
-#### PoolObjectReference
+#### ParentGatewayReference
 
 
 
-PoolObjectReference identifies an API object within the namespace of the
-referrer.
+ParentGatewayReference identifies an API object including its namespace,
+defaulting to Gateway.
 
 
 
 _Appears in:_
-- [InferenceModelSpec](#inferencemodelspec)
+- [PoolStatus](#poolstatus)
 
 | Field | Description | Default | Validation |
 | --- | --- | --- | --- |
-| `group` _[Group](#group)_ | Group is the group of the referent. | inference.networking.x-k8s.io | MaxLength: 253 <br />Pattern: `^$\|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` <br /> |
-| `kind` _[Kind](#kind)_ | Kind is kind of the referent. For example "InferencePool". | InferencePool | MaxLength: 63 <br />MinLength: 1 <br />Pattern: `^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$` <br /> |
-| `name` _[ObjectName](#objectname)_ | Name is the name of the referent. |  | MaxLength: 253 <br />MinLength: 1 <br />Required: \{\} <br /> |
+| `group` _[Group](#group)_ | Group is the group of the referent. | gateway.networking.k8s.io | MaxLength: 253 <br />Pattern: `^$\|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` <br /> |
+| `kind` _[Kind](#kind)_ | Kind is kind of the referent. For example "Gateway". | Gateway | MaxLength: 63 <br />MinLength: 1 <br />Pattern: `^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$` <br /> |
+| `name` _[ObjectName](#objectname)_ | Name is the name of the referent. |  | MaxLength: 253 <br />MinLength: 1 <br /> |
+| `namespace` _[Namespace](#namespace)_ | Namespace is the namespace of the referent.  If not present,<br />the namespace of the referent is assumed to be the same as<br />the namespace of the referring object. |  | MaxLength: 63 <br />MinLength: 1 <br />Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?$` <br /> |
 
 
 #### PoolStatus
@@ -427,7 +369,7 @@ _Appears in:_
 
 | Field | Description | Default | Validation |
 | --- | --- | --- | --- |
-| `parentRef` _[ObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#objectreference-v1-core)_ | GatewayRef indicates the gateway that observed state of InferencePool. |  |  |
+| `parentRef` _[ParentGatewayReference](#parentgatewayreference)_ | GatewayRef indicates the gateway that observed state of InferencePool. |  |  |
 | `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#condition-v1-meta) array_ | Conditions track the state of the InferencePool.<br />Known condition types are:<br />* "Accepted"<br />* "ResolvedRefs" | [map[lastTransitionTime:1970-01-01T00:00:00Z message:Waiting for controller reason:Pending status:Unknown type:Accepted]] | MaxItems: 8 <br /> |
 
 
@@ -447,26 +389,3 @@ _Appears in:_
 
 
 
-#### TargetModel
-
-
-
-TargetModel represents a deployed model or a LoRA adapter. The
-Name field is expected to match the name of the LoRA adapter
-(or base model) as it is registered within the model server. Inference
-Gateway assumes that the model exists on the model server and it's the
-responsibility of the user to validate a correct match. Should a model fail
-to exist at request time, the error is processed by the Inference Gateway
-and emitted on the appropriate InferenceModel object.
-
-
-
-_Appears in:_
-- [InferenceModelSpec](#inferencemodelspec)
-
-| Field | Description | Default | Validation |
-| --- | --- | --- | --- |
-| `name` _string_ | Name is the name of the adapter or base model, as expected by the ModelServer. |  | MaxLength: 253 <br />Required: \{\} <br /> |
-| `weight` _integer_ | Weight is used to determine the proportion of traffic that should be<br />sent to this model when multiple target models are specified.<br />Weight defines the proportion of requests forwarded to the specified<br />model. This is computed as weight/(sum of all weights in this<br />TargetModels list). For non-zero values, there may be some epsilon from<br />the exact proportion defined here depending on the precision an<br />implementation supports. Weight is not a percentage and the sum of<br />weights does not need to equal 100.<br />If a weight is set for any targetModel, it must be set for all targetModels.<br />Conversely weights are optional, so long as ALL targetModels do not specify a weight. |  | Maximum: 1e+06 <br />Minimum: 1 <br /> |
-
-
diff --git a/site-src/reference/x-spec.md b/site-src/reference/x-spec.md
new file mode 100644
index 0000000..5791e8d
--- /dev/null
+++ b/site-src/reference/x-spec.md
@@ -0,0 +1,535 @@
+# API Reference
+
+## Packages
+- [inference.networking.x-k8s.io/v1alpha2](#inferencenetworkingx-k8siov1alpha2)
+
+
+## inference.networking.x-k8s.io/v1alpha2
+
+Package v1alpha2 contains API Schema definitions for the
+inference.networking.x-k8s.io API group.
+
+
+### Resource Types
+- [InferenceModel](#inferencemodel)
+- [InferencePool](#inferencepool)
+
+
+
+#### Criticality
+
+_Underlying type:_ _string_
+
+Criticality defines how important it is to serve the model compared to other models.
+Criticality is intentionally a bounded enum to contain the possibilities that need to be supported by the load balancing algorithm. Any reference to the Criticality field must be optional (use a pointer), and set no default.
+This allows us to union this with a oneOf field in the future should we wish to adjust/extend this behavior.
+
+_Validation:_
+- Enum: [Critical Standard Sheddable]
+
+_Appears in:_
+- [InferenceModelSpec](#inferencemodelspec)
+
+| Field | Description |
+| --- | --- |
+| `Critical` | Critical defines the highest level of criticality. Requests to this band will be shed last.<br /> |
+| `Standard` | Standard defines the base criticality level and is more important than Sheddable but less<br />important than Critical. Requests in this band will be shed before critical traffic.<br />Most models are expected to fall within this band.<br /> |
+| `Sheddable` | Sheddable defines the lowest level of criticality. Requests to this band will be shed before<br />all other bands.<br /> |
+
+
+#### EndpointPickerConfig
+
+
+
+EndpointPickerConfig specifies the configuration needed by the proxy to discover and connect to the endpoint picker extension.
+This type is intended to be a union of mutually exclusive configuration options that we may add in the future.
+
+
+
+_Appears in:_
+- [InferencePoolSpec](#inferencepoolspec)
+
+| Field | Description | Default | Validation |
+| --- | --- | --- | --- |
+| `extensionRef` _[Extension](#extension)_ | Extension configures an endpoint picker as an extension service. |  | Required: \{\} <br /> |
+
+
+#### Extension
+
+
+
+Extension specifies how to configure an extension that runs the endpoint picker.
+
+
+
+_Appears in:_
+- [EndpointPickerConfig](#endpointpickerconfig)
+- [InferencePoolSpec](#inferencepoolspec)
+
+| Field | Description | Default | Validation |
+| --- | --- | --- | --- |
+| `group` _[Group](#group)_ | Group is the group of the referent.<br />The default value is "", representing the Core API group. |  | MaxLength: 253 <br />Pattern: `^$\|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` <br /> |
+| `kind` _[Kind](#kind)_ | Kind is the Kubernetes resource kind of the referent.<br />Defaults to "Service" when not specified.<br />ExternalName services can refer to CNAME DNS records that may live<br />outside of the cluster and as such are difficult to reason about in<br />terms of conformance. They also may not be safe to forward to (see<br />CVE-2021-25740 for more information). Implementations MUST NOT<br />support ExternalName Services. | Service | MaxLength: 63 <br />MinLength: 1 <br />Pattern: `^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$` <br /> |
+| `name` _[ObjectName](#objectname)_ | Name is the name of the referent. |  | MaxLength: 253 <br />MinLength: 1 <br />Required: \{\} <br /> |
+| `portNumber` _[PortNumber](#portnumber)_ | The port number on the service running the extension. When unspecified,<br />implementations SHOULD infer a default value of 9002 when the Kind is<br />Service. |  | Maximum: 65535 <br />Minimum: 1 <br /> |
+| `failureMode` _[ExtensionFailureMode](#extensionfailuremode)_ | Configures how the gateway handles the case when the extension is not responsive.<br />Defaults to failClose. | FailClose | Enum: [FailOpen FailClose] <br /> |
+
+
+#### ExtensionConnection
+
+
+
+ExtensionConnection encapsulates options that configures the connection to the extension.
+
+
+
+_Appears in:_
+- [Extension](#extension)
+
+| Field | Description | Default | Validation |
+| --- | --- | --- | --- |
+| `failureMode` _[ExtensionFailureMode](#extensionfailuremode)_ | Configures how the gateway handles the case when the extension is not responsive.<br />Defaults to failClose. | FailClose | Enum: [FailOpen FailClose] <br /> |
+
+
+#### ExtensionFailureMode
+
+_Underlying type:_ _string_
+
+ExtensionFailureMode defines the options for how the gateway handles the case when the extension is not
+responsive.
+
+_Validation:_
+- Enum: [FailOpen FailClose]
+
+_Appears in:_
+- [Extension](#extension)
+- [ExtensionConnection](#extensionconnection)
+
+| Field | Description |
+| --- | --- |
+| `FailOpen` | FailOpen specifies that the proxy should forward the request to an endpoint of its picking when the Endpoint Picker fails.<br /> |
+| `FailClose` | FailClose specifies that the proxy should drop the request when the Endpoint Picker fails.<br /> |
+
+
+#### ExtensionReference
+
+
+
+ExtensionReference is a reference to the extension.
+
+Connections to this extension MUST use TLS by default. Implementations MAY
+provide a way to customize this connection to use cleartext, a different
+protocol, or custom TLS configuration.
+
+If a reference is invalid, the implementation MUST update the `ResolvedRefs`
+Condition on the InferencePool's status to `status: False`. A 5XX status code
+MUST be returned for the request that would have otherwise been routed to the
+invalid backend.
+
+
+
+_Appears in:_
+- [Extension](#extension)
+
+| Field | Description | Default | Validation |
+| --- | --- | --- | --- |
+| `group` _[Group](#group)_ | Group is the group of the referent.<br />The default value is "", representing the Core API group. |  | MaxLength: 253 <br />Pattern: `^$\|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` <br /> |
+| `kind` _[Kind](#kind)_ | Kind is the Kubernetes resource kind of the referent.<br />Defaults to "Service" when not specified.<br />ExternalName services can refer to CNAME DNS records that may live<br />outside of the cluster and as such are difficult to reason about in<br />terms of conformance. They also may not be safe to forward to (see<br />CVE-2021-25740 for more information). Implementations MUST NOT<br />support ExternalName Services. | Service | MaxLength: 63 <br />MinLength: 1 <br />Pattern: `^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$` <br /> |
+| `name` _[ObjectName](#objectname)_ | Name is the name of the referent. |  | MaxLength: 253 <br />MinLength: 1 <br />Required: \{\} <br /> |
+| `portNumber` _[PortNumber](#portnumber)_ | The port number on the service running the extension. When unspecified,<br />implementations SHOULD infer a default value of 9002 when the Kind is<br />Service. |  | Maximum: 65535 <br />Minimum: 1 <br /> |
+
+
+#### Group
+
+_Underlying type:_ _string_
+
+Group refers to a Kubernetes Group. It must either be an empty string or a
+RFC 1123 subdomain.
+
+This validation is based off of the corresponding Kubernetes validation:
+https://github.com/kubernetes/apimachinery/blob/02cfb53916346d085a6c6c7c66f882e3c6b0eca6/pkg/util/validation/validation.go#L208
+
+Valid values include:
+
+* "" - empty string implies core Kubernetes API group
+* "gateway.networking.k8s.io"
+* "foo.example.com"
+
+Invalid values include:
+
+* "example.com/bar" - "/" is an invalid character
+
+_Validation:_
+- MaxLength: 253
+- Pattern: `^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
+
+_Appears in:_
+- [Extension](#extension)
+- [ExtensionReference](#extensionreference)
+- [ParentGatewayReference](#parentgatewayreference)
+- [PoolObjectReference](#poolobjectreference)
+
+
+
+#### InferenceModel
+
+
+
+InferenceModel is the Schema for the InferenceModels API.
+
+
+
+
+
+| Field | Description | Default | Validation |
+| --- | --- | --- | --- |
+| `apiVersion` _string_ | `inference.networking.x-k8s.io/v1alpha2` | | |
+| `kind` _string_ | `InferenceModel` | | |
+| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. |  |  |
+| `spec` _[InferenceModelSpec](#inferencemodelspec)_ |  |  |  |
+| `status` _[InferenceModelStatus](#inferencemodelstatus)_ |  |  |  |
+
+
+
+
+
+
+#### InferenceModelSpec
+
+
+
+InferenceModelSpec represents the desired state of a specific model use case. This resource is
+managed by the "Inference Workload Owner" persona.
+
+The Inference Workload Owner persona is someone that trains, verifies, and
+leverages a large language model from a model frontend, drives the lifecycle
+and rollout of new versions of those models, and defines the specific
+performance and latency goals for the model. These workloads are
+expected to operate within an InferencePool sharing compute capacity with other
+InferenceModels, defined by the Inference Platform Admin.
+
+InferenceModel's modelName (not the ObjectMeta name) is unique for a given InferencePool,
+if the name is reused, an error will be shown on the status of a
+InferenceModel that attempted to reuse. The oldest InferenceModel, based on
+creation timestamp, will be selected to remain valid. In the event of a race
+condition, one will be selected at random.
+
+
+
+_Appears in:_
+- [InferenceModel](#inferencemodel)
+
+| Field | Description | Default | Validation |
+| --- | --- | --- | --- |
+| `modelName` _string_ | ModelName is the name of the model as it will be set in the "model" parameter for an incoming request.<br />ModelNames must be unique for a referencing InferencePool<br />(names can be reused for a different pool in the same cluster).<br />The modelName with the oldest creation timestamp is retained, and the incoming<br />InferenceModel's Ready status is set to false with a corresponding reason.<br />In the rare case of a race condition, one Model will be selected randomly to be considered valid, and the other rejected.<br />Names can be reserved without an underlying model configured in the pool.<br />This can be done by specifying a target model and setting the weight to zero,<br />an error will be returned specifying that no valid target model is found. |  | MaxLength: 256 <br />Required: \{\} <br /> |
+| `criticality` _[Criticality](#criticality)_ | Criticality defines how important it is to serve the model compared to other models referencing the same pool.<br />Criticality impacts how traffic is handled in resource constrained situations. It handles this by<br />queuing or rejecting requests of lower criticality. InferenceModels of an equivalent Criticality will<br />fairly share resources over throughput of tokens. In the future, the metric used to calculate fairness,<br />and the proportionality of fairness will be configurable.<br />Default values for this field will not be set, to allow for future additions of new field that may 'one of' with this field.<br />Any implementations that may consume this field may treat an unset value as the 'Standard' range. |  | Enum: [Critical Standard Sheddable] <br /> |
+| `targetModels` _[TargetModel](#targetmodel) array_ | TargetModels allow multiple versions of a model for traffic splitting.<br />If not specified, the target model name is defaulted to the modelName parameter.<br />modelName is often in reference to a LoRA adapter. |  | MaxItems: 10 <br /> |
+| `poolRef` _[PoolObjectReference](#poolobjectreference)_ | PoolRef is a reference to the inference pool, the pool must exist in the same namespace. |  | Required: \{\} <br /> |
+
+
+#### InferenceModelStatus
+
+
+
+InferenceModelStatus defines the observed state of InferenceModel
+
+
+
+_Appears in:_
+- [InferenceModel](#inferencemodel)
+
+| Field | Description | Default | Validation |
+| --- | --- | --- | --- |
+| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#condition-v1-meta) array_ | Conditions track the state of the InferenceModel.<br />Known condition types are:<br />* "Accepted" | [map[lastTransitionTime:1970-01-01T00:00:00Z message:Waiting for controller reason:Pending status:Unknown type:Ready]] | MaxItems: 8 <br /> |
+
+
+#### InferencePool
+
+
+
+InferencePool is the Schema for the InferencePools API.
+
+
+
+
+
+
+| Field | Description | Default | Validation |
+| --- | --- | --- | --- |
+| `apiVersion` _string_ | `inference.networking.x-k8s.io/v1alpha2` | | |
+| `kind` _string_ | `InferencePool` | | |
+| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. |  |  |
+| `spec` _[InferencePoolSpec](#inferencepoolspec)_ |  |  |  |
+| `status` _[InferencePoolStatus](#inferencepoolstatus)_ | Status defines the observed state of InferencePool. | \{ parent:[map[conditions:[map[lastTransitionTime:1970-01-01T00:00:00Z message:Waiting for controller reason:Pending status:Unknown type:Accepted]] parentRef:map[kind:Status name:default]]] \} |  |
+
+
+
+
+
+
+#### InferencePoolSpec
+
+
+
+InferencePoolSpec defines the desired state of InferencePool
+
+
+
+_Appears in:_
+- [InferencePool](#inferencepool)
+
+| Field | Description | Default | Validation |
+| --- | --- | --- | --- |
+| `selector` _object (keys:[LabelKey](#labelkey), values:[LabelValue](#labelvalue))_ | Selector defines a map of labels to watch model server Pods<br />that should be included in the InferencePool.<br />In some cases, implementations may translate this field to a Service selector, so this matches the simple<br />map used for Service selectors instead of the full Kubernetes LabelSelector type.<br />If specified, it will be applied to match the model server pods in the same namespace as the InferencePool.<br />Cross namesoace selector is not supported. |  | Required: \{\} <br /> |
+| `targetPortNumber` _integer_ | TargetPortNumber defines the port number to access the selected model server Pods.<br />The number must be in the range 1 to 65535. |  | Maximum: 65535 <br />Minimum: 1 <br />Required: \{\} <br /> |
+| `extensionRef` _[Extension](#extension)_ | Extension configures an endpoint picker as an extension service. |  | Required: \{\} <br /> |
+
+
+#### InferencePoolStatus
+
+
+
+InferencePoolStatus defines the observed state of InferencePool.
+
+
+
+_Appears in:_
+- [InferencePool](#inferencepool)
+
+| Field | Description | Default | Validation |
+| --- | --- | --- | --- |
+| `parent` _[PoolStatus](#poolstatus) array_ | Parents is a list of parent resources (usually Gateways) that are<br />associated with the InferencePool, and the status of the InferencePool with respect to<br />each parent.<br />A maximum of 32 Gateways will be represented in this list. When the list contains<br />`kind: Status, name: default`, it indicates that the InferencePool is not<br />associated with any Gateway and a controller must perform the following:<br /> - Remove the parent when setting the "Accepted" condition.<br /> - Add the parent when the controller will no longer manage the InferencePool<br />   and no other parents exist. |  | MaxItems: 32 <br /> |
+
+
+#### Kind
+
+_Underlying type:_ _string_
+
+Kind refers to a Kubernetes Kind.
+
+Valid values include:
+
+* "Service"
+* "HTTPRoute"
+
+Invalid values include:
+
+* "invalid/kind" - "/" is an invalid character
+
+_Validation:_
+- MaxLength: 63
+- MinLength: 1
+- Pattern: `^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$`
+
+_Appears in:_
+- [Extension](#extension)
+- [ExtensionReference](#extensionreference)
+- [ParentGatewayReference](#parentgatewayreference)
+- [PoolObjectReference](#poolobjectreference)
+
+
+
+#### LabelKey
+
+_Underlying type:_ _string_
+
+LabelKey was originally copied from: https://github.com/kubernetes-sigs/gateway-api/blob/99a3934c6bc1ce0874f3a4c5f20cafd8977ffcb4/apis/v1/shared_types.go#L694-L731
+Duplicated as to not take an unexpected dependency on gw's API.
+
+LabelKey is the key of a label. This is used for validation
+of maps. This matches the Kubernetes "qualified name" validation that is used for labels.
+Labels are case sensitive, so: my-label and My-Label are considered distinct.
+
+Valid values include:
+
+* example
+* example.com
+* example.com/path
+* example.com/path.html
+
+Invalid values include:
+
+* example~ - "~" is an invalid character
+* example.com. - can not start or end with "."
+
+_Validation:_
+- MaxLength: 253
+- MinLength: 1
+- Pattern: `^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?([A-Za-z0-9][-A-Za-z0-9_.]{0,61})?[A-Za-z0-9]$`
+
+_Appears in:_
+- [InferencePoolSpec](#inferencepoolspec)
+
+
+
+#### LabelValue
+
+_Underlying type:_ _string_
+
+LabelValue is the value of a label. This is used for validation
+of maps. This matches the Kubernetes label validation rules:
+* must be 63 characters or less (can be empty),
+* unless empty, must begin and end with an alphanumeric character ([a-z0-9A-Z]),
+* could contain dashes (-), underscores (_), dots (.), and alphanumerics between.
+
+Valid values include:
+
+* MyValue
+* my.name
+* 123-my-value
+
+_Validation:_
+- MaxLength: 63
+- MinLength: 0
+- Pattern: `^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$`
+
+_Appears in:_
+- [InferencePoolSpec](#inferencepoolspec)
+
+
+
+#### Namespace
+
+_Underlying type:_ _string_
+
+Namespace refers to a Kubernetes namespace. It must be a RFC 1123 label.
+
+This validation is based off of the corresponding Kubernetes validation:
+https://github.com/kubernetes/apimachinery/blob/02cfb53916346d085a6c6c7c66f882e3c6b0eca6/pkg/util/validation/validation.go#L187
+
+This is used for Namespace name validation here:
+https://github.com/kubernetes/apimachinery/blob/02cfb53916346d085a6c6c7c66f882e3c6b0eca6/pkg/api/validation/generic.go#L63
+
+Valid values include:
+
+* "example"
+
+Invalid values include:
+
+* "example.com" - "." is an invalid character
+
+_Validation:_
+- MaxLength: 63
+- MinLength: 1
+- Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?$`
+
+_Appears in:_
+- [ParentGatewayReference](#parentgatewayreference)
+
+
+
+#### ObjectName
+
+_Underlying type:_ _string_
+
+ObjectName refers to the name of a Kubernetes object.
+Object names can have a variety of forms, including RFC 1123 subdomains,
+RFC 1123 labels, or RFC 1035 labels.
+
+_Validation:_
+- MaxLength: 253
+- MinLength: 1
+
+_Appears in:_
+- [Extension](#extension)
+- [ExtensionReference](#extensionreference)
+- [ParentGatewayReference](#parentgatewayreference)
+- [PoolObjectReference](#poolobjectreference)
+
+
+
+#### ParentGatewayReference
+
+
+
+ParentGatewayReference identifies an API object including its namespace,
+defaulting to Gateway.
+
+
+
+_Appears in:_
+- [PoolStatus](#poolstatus)
+
+| Field | Description | Default | Validation |
+| --- | --- | --- | --- |
+| `group` _[Group](#group)_ | Group is the group of the referent. | gateway.networking.k8s.io | MaxLength: 253 <br />Pattern: `^$\|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` <br /> |
+| `kind` _[Kind](#kind)_ | Kind is kind of the referent. For example "Gateway". | Gateway | MaxLength: 63 <br />MinLength: 1 <br />Pattern: `^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$` <br /> |
+| `name` _[ObjectName](#objectname)_ | Name is the name of the referent. |  | MaxLength: 253 <br />MinLength: 1 <br /> |
+| `namespace` _[Namespace](#namespace)_ | Namespace is the namespace of the referent.  If not present,<br />the namespace of the referent is assumed to be the same as<br />the namespace of the referring object. |  | MaxLength: 63 <br />MinLength: 1 <br />Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?$` <br /> |
+
+
+#### PoolObjectReference
+
+
+
+PoolObjectReference identifies an API object within the namespace of the
+referrer.
+
+
+
+_Appears in:_
+- [InferenceModelSpec](#inferencemodelspec)
+
+| Field | Description | Default | Validation |
+| --- | --- | --- | --- |
+| `group` _[Group](#group)_ | Group is the group of the referent. | inference.networking.x-k8s.io | MaxLength: 253 <br />Pattern: `^$\|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` <br /> |
+| `kind` _[Kind](#kind)_ | Kind is kind of the referent. For example "InferencePool". | InferencePool | MaxLength: 63 <br />MinLength: 1 <br />Pattern: `^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$` <br /> |
+| `name` _[ObjectName](#objectname)_ | Name is the name of the referent. |  | MaxLength: 253 <br />MinLength: 1 <br />Required: \{\} <br /> |
+
+
+#### PoolStatus
+
+
+
+PoolStatus defines the observed state of InferencePool from a Gateway.
+
+
+
+_Appears in:_
+- [InferencePoolStatus](#inferencepoolstatus)
+
+| Field | Description | Default | Validation |
+| --- | --- | --- | --- |
+| `parentRef` _[ParentGatewayReference](#parentgatewayreference)_ | GatewayRef indicates the gateway that observed state of InferencePool. |  |  |
+| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#condition-v1-meta) array_ | Conditions track the state of the InferencePool.<br />Known condition types are:<br />* "Accepted"<br />* "ResolvedRefs" | [map[lastTransitionTime:1970-01-01T00:00:00Z message:Waiting for controller reason:Pending status:Unknown type:Accepted]] | MaxItems: 8 <br /> |
+
+
+#### PortNumber
+
+_Underlying type:_ _integer_
+
+PortNumber defines a network port.
+
+_Validation:_
+- Maximum: 65535
+- Minimum: 1
+
+_Appears in:_
+- [Extension](#extension)
+- [ExtensionReference](#extensionreference)
+
+
+
+#### TargetModel
+
+
+
+TargetModel represents a deployed model or a LoRA adapter. The
+Name field is expected to match the name of the LoRA adapter
+(or base model) as it is registered within the model server. Inference
+Gateway assumes that the model exists on the model server and it's the
+responsibility of the user to validate a correct match. Should a model fail
+to exist at request time, the error is processed by the Inference Gateway
+and emitted on the appropriate InferenceModel object.
+
+
+
+_Appears in:_
+- [InferenceModelSpec](#inferencemodelspec)
+
+| Field | Description | Default | Validation |
+| --- | --- | --- | --- |
+| `name` _string_ | Name is the name of the adapter or base model, as expected by the ModelServer. |  | MaxLength: 253 <br />Required: \{\} <br /> |
+| `weight` _integer_ | Weight is used to determine the proportion of traffic that should be<br />sent to this model when multiple target models are specified.<br />Weight defines the proportion of requests forwarded to the specified<br />model. This is computed as weight/(sum of all weights in this<br />TargetModels list). For non-zero values, there may be some epsilon from<br />the exact proportion defined here depending on the precision an<br />implementation supports. Weight is not a percentage and the sum of<br />weights does not need to equal 100.<br />If a weight is set for any targetModel, it must be set for all targetModels.<br />Conversely weights are optional, so long as ALL targetModels do not specify a weight. |  | Maximum: 1e+06 <br />Minimum: 1 <br /> |
+
+



Test patch:
diff --git a/conformance/tests/basic/gateway_following_epp_routing.go b/conformance/tests/basic/gateway_following_epp_routing.go
index 30a5a6f..83d0e2b 100644
--- a/conformance/tests/basic/gateway_following_epp_routing.go
+++ b/conformance/tests/basic/gateway_following_epp_routing.go
@@ -26,6 +26,7 @@ import (
 	"github.com/stretchr/testify/require"
 	"golang.org/x/sync/errgroup"
 	"k8s.io/apimachinery/pkg/types"
+	gwhttp "sigs.k8s.io/gateway-api/conformance/utils/http"
 	"sigs.k8s.io/gateway-api/conformance/utils/suite"
 	"sigs.k8s.io/gateway-api/pkg/features"
 
@@ -33,7 +34,6 @@ import (
 	k8sutils "sigs.k8s.io/gateway-api-inference-extension/conformance/utils/kubernetes"
 	"sigs.k8s.io/gateway-api-inference-extension/conformance/utils/traffic"
 	trafficutils "sigs.k8s.io/gateway-api-inference-extension/conformance/utils/traffic"
-	gwhttp "sigs.k8s.io/gateway-api/conformance/utils/http"
 )
 
 func init() {
diff --git a/conformance/tests/basic/inferencepool_invalid_epp_service.go b/conformance/tests/basic/inferencepool_invalid_epp_service.go
index e2a52d5..0fce85a 100644
--- a/conformance/tests/basic/inferencepool_invalid_epp_service.go
+++ b/conformance/tests/basic/inferencepool_invalid_epp_service.go
@@ -21,12 +21,12 @@ import (
 
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/types"
-	inferenceapi "sigs.k8s.io/gateway-api-inference-extension/api/v1"
 	gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
 	"sigs.k8s.io/gateway-api/conformance/utils/kubernetes"
 	"sigs.k8s.io/gateway-api/conformance/utils/suite"
 	"sigs.k8s.io/gateway-api/pkg/features"
 
+	inferenceapi "sigs.k8s.io/gateway-api-inference-extension/api/v1"
 	"sigs.k8s.io/gateway-api-inference-extension/conformance/tests"
 	k8sutils "sigs.k8s.io/gateway-api-inference-extension/conformance/utils/kubernetes"
 	trafficutils "sigs.k8s.io/gateway-api-inference-extension/conformance/utils/traffic"
diff --git a/pkg/bbr/handlers/request_test.go b/pkg/bbr/handlers/request_test.go
index 67c96de..e597953 100644
--- a/pkg/bbr/handlers/request_test.go
+++ b/pkg/bbr/handlers/request_test.go
@@ -28,6 +28,7 @@ import (
 	"google.golang.org/protobuf/testing/protocmp"
 	metricsutils "k8s.io/component-base/metrics/testutil"
 	crmetrics "sigs.k8s.io/controller-runtime/pkg/metrics"
+
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/bbr/metrics"
 	logutil "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/util/logging"
 )
diff --git a/pkg/bbr/handlers/server_test.go b/pkg/bbr/handlers/server_test.go
index f4e8e25..7bc50a6 100644
--- a/pkg/bbr/handlers/server_test.go
+++ b/pkg/bbr/handlers/server_test.go
@@ -25,6 +25,7 @@ import (
 	"github.com/google/go-cmp/cmp"
 	"google.golang.org/protobuf/testing/protocmp"
 	"sigs.k8s.io/controller-runtime/pkg/log"
+
 	logutil "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/util/logging"
 )
 
diff --git a/pkg/epp/backend/metrics/metrics_test.go b/pkg/epp/backend/metrics/metrics_test.go
index 9f7c2b8..2dd8ca5 100644
--- a/pkg/epp/backend/metrics/metrics_test.go
+++ b/pkg/epp/backend/metrics/metrics_test.go
@@ -19,6 +19,7 @@ package metrics
 import (
 	"context"
 	"errors"
+	"net/http"
 	"reflect"
 	"strconv"
 	"strings"
@@ -495,7 +496,13 @@ func TestFetchMetrics(t *testing.T) {
 		},
 	}
 	existing := &MetricsState{}
-	p := &PodMetricsClientImpl{ModelServerMetricsPort: 9999, ModelServerMetricsPath: "/metrics"} // No MetricMapping needed for this basic test
+	// No MetricMapping needed for this basic test
+	p := &PodMetricsClientImpl{
+		ModelServerMetricsScheme: "http",
+		ModelServerMetricsPort:   9999,
+		ModelServerMetricsPath:   "/metrics",
+		Client:                   http.DefaultClient,
+	}
 
 	_, err := p.FetchMetrics(ctx, pod, existing, 9999) // Use a port that's unlikely to be in use
 	if err == nil {
diff --git a/pkg/epp/backend/metrics/pod_metrics_test.go b/pkg/epp/backend/metrics/pod_metrics_test.go
index 74aa7ce..f3d5cbc 100644
--- a/pkg/epp/backend/metrics/pod_metrics_test.go
+++ b/pkg/epp/backend/metrics/pod_metrics_test.go
@@ -26,6 +26,7 @@ import (
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/types"
+
 	v1 "sigs.k8s.io/gateway-api-inference-extension/api/v1"
 )
 
diff --git a/pkg/epp/controller/inferencemodel_reconciler_test.go b/pkg/epp/controller/inferencemodel_reconciler_test.go
index e826fa1..2df46d1 100644
--- a/pkg/epp/controller/inferencemodel_reconciler_test.go
+++ b/pkg/epp/controller/inferencemodel_reconciler_test.go
@@ -30,6 +30,7 @@ import (
 	ctrl "sigs.k8s.io/controller-runtime"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 	"sigs.k8s.io/controller-runtime/pkg/client/fake"
+
 	v1 "sigs.k8s.io/gateway-api-inference-extension/api/v1"
 	"sigs.k8s.io/gateway-api-inference-extension/apix/v1alpha2"
 	backendmetrics "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/backend/metrics"
diff --git a/pkg/epp/controller/inferencepool_reconciler_test.go b/pkg/epp/controller/inferencepool_reconciler_test.go
index eb5fa78..1be41d1 100644
--- a/pkg/epp/controller/inferencepool_reconciler_test.go
+++ b/pkg/epp/controller/inferencepool_reconciler_test.go
@@ -30,6 +30,7 @@ import (
 	ctrl "sigs.k8s.io/controller-runtime"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 	"sigs.k8s.io/controller-runtime/pkg/client/fake"
+
 	v1 "sigs.k8s.io/gateway-api-inference-extension/api/v1"
 	"sigs.k8s.io/gateway-api-inference-extension/apix/v1alpha2"
 	backendmetrics "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/backend/metrics"
diff --git a/pkg/epp/controller/pod_reconciler_test.go b/pkg/epp/controller/pod_reconciler_test.go
index f078675..15a898b 100644
--- a/pkg/epp/controller/pod_reconciler_test.go
+++ b/pkg/epp/controller/pod_reconciler_test.go
@@ -31,6 +31,7 @@ import (
 	ctrl "sigs.k8s.io/controller-runtime"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 	"sigs.k8s.io/controller-runtime/pkg/client/fake"
+
 	v1 "sigs.k8s.io/gateway-api-inference-extension/api/v1"
 	backendmetrics "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/backend/metrics"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/datastore"
diff --git a/pkg/epp/datastore/datastore_test.go b/pkg/epp/datastore/datastore_test.go
index fdb1a5a..b2ba5d1 100644
--- a/pkg/epp/datastore/datastore_test.go
+++ b/pkg/epp/datastore/datastore_test.go
@@ -31,6 +31,7 @@ import (
 	"k8s.io/apimachinery/pkg/types"
 	clientgoscheme "k8s.io/client-go/kubernetes/scheme"
 	"sigs.k8s.io/controller-runtime/pkg/client/fake"
+
 	v1 "sigs.k8s.io/gateway-api-inference-extension/api/v1"
 	"sigs.k8s.io/gateway-api-inference-extension/apix/v1alpha2"
 	backendmetrics "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/backend/metrics"
diff --git a/pkg/epp/flowcontrol/framework/plugins/policies/interflow/dispatch/besthead/besthead_test.go b/pkg/epp/flowcontrol/framework/plugins/policies/interflow/dispatch/besthead/besthead_test.go
index ef7cbb3..eb3077b 100644
--- a/pkg/epp/flowcontrol/framework/plugins/policies/interflow/dispatch/besthead/besthead_test.go
+++ b/pkg/epp/flowcontrol/framework/plugins/policies/interflow/dispatch/besthead/besthead_test.go
@@ -31,8 +31,9 @@ import (
 )
 
 const (
-	flow1 = "flow1"
-	flow2 = "flow2"
+	flow1           = "flow1"
+	flow2           = "flow2"
+	commonScoreType = "enqueue_time_ns_asc"
 )
 
 // enqueueTimeComparatorFunc is a test utility. Lower enqueue time is better.
@@ -40,8 +41,6 @@ func enqueueTimeComparatorFunc(a, b types.QueueItemAccessor) bool {
 	return a.EnqueueTime().Before(b.EnqueueTime())
 }
 
-const commonScoreType = "enqueue_time_ns_asc"
-
 func newTestComparator() *frameworkmocks.MockItemComparator {
 	return &frameworkmocks.MockItemComparator{
 		ScoreTypeV: commonScoreType,
@@ -49,6 +48,26 @@ func newTestComparator() *frameworkmocks.MockItemComparator {
 	}
 }
 
+func newTestBand(queues map[string]framework.FlowQueueAccessor) *frameworkmocks.MockPriorityBandAccessor {
+	flowIDs := make([]string, 0, len(queues))
+	for id := range queues {
+		flowIDs = append(flowIDs, id)
+	}
+	return &frameworkmocks.MockPriorityBandAccessor{
+		FlowIDsFunc: func() []string { return flowIDs },
+		QueueFunc: func(id string) framework.FlowQueueAccessor {
+			return queues[id]
+		},
+		IterateQueuesFunc: func(iterator func(queue framework.FlowQueueAccessor) bool) {
+			for _, id := range flowIDs {
+				if !iterator(queues[id]) {
+					break
+				}
+			}
+		},
+	}
+}
+
 func TestBestHead_Name(t *testing.T) {
 	t.Parallel()
 	policy := newBestHead()
@@ -58,269 +77,155 @@ func TestBestHead_Name(t *testing.T) {
 func TestBestHead_SelectQueue(t *testing.T) {
 	t.Parallel()
 	policy := newBestHead()
+	now := time.Now()
+
+	itemBetter := typesmocks.NewMockQueueItemAccessor(10, "itemBetter", flow1)
+	itemBetter.EnqueueTimeV = now.Add(-10 * time.Second)
+	itemWorse := typesmocks.NewMockQueueItemAccessor(20, "itemWorse", flow2)
+	itemWorse.EnqueueTimeV = now.Add(-5 * time.Second)
+
+	queue1 := &frameworkmocks.MockFlowQueueAccessor{
+		LenV:        1,
+		PeekHeadV:   itemBetter,
+		FlowSpecV:   types.FlowSpecification{ID: flow1},
+		ComparatorV: newTestComparator(),
+	}
+	queue2 := &frameworkmocks.MockFlowQueueAccessor{
+		LenV:        1,
+		PeekHeadV:   itemWorse,
+		FlowSpecV:   types.FlowSpecification{ID: flow2},
+		ComparatorV: newTestComparator(),
+	}
+	queueEmpty := &frameworkmocks.MockFlowQueueAccessor{
+		LenV:         0,
+		PeekHeadErrV: framework.ErrQueueEmpty,
+		FlowSpecV:    types.FlowSpecification{ID: "flowEmpty"},
+		ComparatorV:  newTestComparator(),
+	}
 
-	t.Run("SelectQueue_Logic", func(t *testing.T) {
-		t.Parallel()
-
-		t.Run("BasicSelection_TwoQueues", func(t *testing.T) {
-			t.Parallel()
-			now := time.Now()
-			itemBetter := typesmocks.NewMockQueueItemAccessor(10, "itemBetter", flow1)
-			itemBetter.EnqueueTimeV = now.Add(-10 * time.Second) // Earlier enqueue time = better
-			queue1 := &frameworkmocks.MockFlowQueueAccessor{
-				LenV:        1,
-				PeekHeadV:   itemBetter,
-				FlowSpecV:   types.FlowSpecification{ID: flow1},
-				ComparatorV: newTestComparator(),
-			}
-
-			itemWorse := typesmocks.NewMockQueueItemAccessor(20, "itemWorse", flow2)
-			itemWorse.EnqueueTimeV = now.Add(-5 * time.Second) // Later enqueue time = worse
-			queue2 := &frameworkmocks.MockFlowQueueAccessor{
-				LenV:        1,
-				PeekHeadV:   itemWorse,
-				FlowSpecV:   types.FlowSpecification{ID: flow2},
-				ComparatorV: newTestComparator(),
-			}
-
-			mockBand := &frameworkmocks.MockPriorityBandAccessor{
-				FlowIDsV: []string{flow1, flow2},
-				QueueFuncV: func(id string) framework.FlowQueueAccessor {
-					if id == flow1 {
-						return queue1
-					}
-					if id == flow2 {
-						return queue2
-					}
-					return nil
+	testCases := []struct {
+		name            string
+		band            framework.PriorityBandAccessor
+		expectedQueueID string
+		expectedErr     error
+		shouldPanic     bool
+	}{
+		{
+			name: "BasicSelection_TwoQueues",
+			band: newTestBand(map[string]framework.FlowQueueAccessor{
+				flow1: queue1,
+				flow2: queue2,
+			}),
+			expectedQueueID: flow1,
+		},
+		{
+			name: "IgnoresEmptyQueues",
+			band: newTestBand(map[string]framework.FlowQueueAccessor{
+				flow1:       queue1,
+				"flowEmpty": queueEmpty,
+				flow2:       queue2,
+			}),
+			expectedQueueID: flow1,
+		},
+		{
+			name:            "SingleNonEmptyQueue",
+			band:            newTestBand(map[string]framework.FlowQueueAccessor{flow1: queue1}),
+			expectedQueueID: flow1,
+		},
+		{
+			name: "ComparatorCompatibility",
+			band: newTestBand(map[string]framework.FlowQueueAccessor{
+				flow1: &frameworkmocks.MockFlowQueueAccessor{
+					LenV:        1,
+					PeekHeadV:   itemBetter,
+					FlowSpecV:   types.FlowSpecification{ID: flow1},
+					ComparatorV: &frameworkmocks.MockItemComparator{ScoreTypeV: "typeA", FuncV: enqueueTimeComparatorFunc},
 				},
-			}
-
-			selected, err := policy.SelectQueue(mockBand)
-			require.NoError(t, err, "SelectQueue should not error with valid inputs")
-			require.NotNil(t, selected, "SelectQueue should select a queue")
-			assert.Equal(t, flow1, selected.FlowSpec().ID, "Should select queue1 with the better item")
-		})
-
-		t.Run("IgnoresEmptyQueues", func(t *testing.T) {
-			t.Parallel()
-			now := time.Now()
-			itemBetter := typesmocks.NewMockQueueItemAccessor(10, "itemBetter", flow1)
-			itemBetter.EnqueueTimeV = now.Add(-10 * time.Second)
-			queue1 := &frameworkmocks.MockFlowQueueAccessor{ // Non-empty
-				LenV:        1,
-				PeekHeadV:   itemBetter,
-				FlowSpecV:   types.FlowSpecification{ID: flow1},
-				ComparatorV: newTestComparator(),
-			}
-			queueEmpty := &frameworkmocks.MockFlowQueueAccessor{ // Empty
-				LenV:         0,
-				PeekHeadErrV: framework.ErrQueueEmpty,
-				FlowSpecV:    types.FlowSpecification{ID: "flowEmpty"},
-				ComparatorV:  newTestComparator(),
-			}
-			itemWorse := typesmocks.NewMockQueueItemAccessor(20, "itemWorse", flow2)
-			itemWorse.EnqueueTimeV = now.Add(-5 * time.Second)
-			queue2 := &frameworkmocks.MockFlowQueueAccessor{ // Non-empty
-				LenV:        1,
-				PeekHeadV:   itemWorse,
-				FlowSpecV:   types.FlowSpecification{ID: flow2},
-				ComparatorV: newTestComparator(),
-			}
-
-			mockBand := &frameworkmocks.MockPriorityBandAccessor{
-				FlowIDsV: []string{"flowEmpty", flow1, flow2},
-				QueueFuncV: func(id string) framework.FlowQueueAccessor {
-					switch id {
-					case flow1:
-						return queue1
-					case "flowEmpty":
-						return queueEmpty
-					case flow2:
-						return queue2
-					}
-					return nil
+				flow2: &frameworkmocks.MockFlowQueueAccessor{
+					LenV:        1,
+					PeekHeadV:   itemWorse,
+					FlowSpecV:   types.FlowSpecification{ID: flow2},
+					ComparatorV: &frameworkmocks.MockItemComparator{ScoreTypeV: "typeB", FuncV: enqueueTimeComparatorFunc},
 				},
-			}
-			selected, err := policy.SelectQueue(mockBand)
-			require.NoError(t, err, "SelectQueue should not error when some queues are empty")
-			require.NotNil(t, selected, "SelectQueue should select a queue from the non-empty set")
-			assert.Equal(t, flow1, selected.FlowSpec().ID, "Should select queue1, ignoring empty queue")
-		})
-
-		t.Run("SingleNonEmptyQueue", func(t *testing.T) {
-			t.Parallel()
-			item := typesmocks.NewMockQueueItemAccessor(10, "item", flow1)
-			queue1 := &frameworkmocks.MockFlowQueueAccessor{
-				LenV:        1,
-				PeekHeadV:   item,
-				FlowSpecV:   types.FlowSpecification{ID: flow1},
-				ComparatorV: newTestComparator(),
-			}
-			mockBand := &frameworkmocks.MockPriorityBandAccessor{
-				FlowIDsV: []string{flow1},
-				QueueFuncV: func(id string) framework.FlowQueueAccessor {
-					if id == flow1 {
-						return queue1
-					}
-					return nil
+			}),
+			expectedErr: framework.ErrIncompatiblePriorityType,
+		},
+		{
+			name: "QueuePeekHeadErrors",
+			band: newTestBand(map[string]framework.FlowQueueAccessor{
+				flow1: &frameworkmocks.MockFlowQueueAccessor{
+					LenV:         1,
+					PeekHeadErrV: errors.New("peek error"),
+					FlowSpecV:    types.FlowSpecification{ID: flow1},
+					ComparatorV:  newTestComparator(),
 				},
-			}
-			selected, err := policy.SelectQueue(mockBand)
-			require.NoError(t, err, "SelectQueue should not error for a single valid queue")
-			require.NotNil(t, selected, "SelectQueue should select the only available queue")
-			assert.Equal(t, flow1, selected.FlowSpec().ID, "Should select the only non-empty queue")
-		})
-	})
-
-	t.Run("SelectQueue_ComparatorCompatibility", func(t *testing.T) {
-		t.Parallel()
-		queue1 := &frameworkmocks.MockFlowQueueAccessor{
-			LenV:      1,
-			PeekHeadV: typesmocks.NewMockQueueItemAccessor(10, "item1", flow1),
-			FlowSpecV: types.FlowSpecification{ID: flow1},
-			ComparatorV: &frameworkmocks.MockItemComparator{
-				ScoreTypeV: "typeA",
-				FuncV:      enqueueTimeComparatorFunc,
-			},
-		}
-		queue2 := &frameworkmocks.MockFlowQueueAccessor{
-			LenV:      1,
-			PeekHeadV: typesmocks.NewMockQueueItemAccessor(20, "item2", flow2),
-			FlowSpecV: types.FlowSpecification{ID: flow2},
-			ComparatorV: &frameworkmocks.MockItemComparator{
-				ScoreTypeV: "typeB", // Different ScoreType
-				FuncV:      enqueueTimeComparatorFunc,
-			},
-		}
-		mockBand := &frameworkmocks.MockPriorityBandAccessor{
-			FlowIDsV: []string{flow1, flow2},
-			QueueFuncV: func(id string) framework.FlowQueueAccessor {
-				if id == flow1 {
-					return queue1
-				}
-				if id == flow2 {
-					return queue2
-				}
-				return nil
-			},
-		}
-		selected, err := policy.SelectQueue(mockBand)
-		assert.Nil(t, selected, "SelectQueue should return a nil queue on incompatible comparator error")
-		require.Error(t, err, "SelectQueue should return an error for incompatible comparators")
-		assert.ErrorIs(t, err, framework.ErrIncompatiblePriorityType, "Error should be ErrIncompatiblePriorityType")
-	})
-
-	t.Run("SelectQueue_EdgeCase", func(t *testing.T) {
-		// Scenarios like NilBand, NoQueuesInBand, AllQueuesEmpty are covered by functional tests.
-		// These tests focus on edge cases more specific to BestHead's logic.
-		t.Parallel()
-
-		t.Run("QueuePeekHeadErrors", func(t *testing.T) {
-			t.Parallel()
-			queue1 := &frameworkmocks.MockFlowQueueAccessor{
-				LenV:         1, // Non-empty
-				PeekHeadErrV: errors.New("internal peek error"),
-				FlowSpecV:    types.FlowSpecification{ID: flow1},
-				ComparatorV:  newTestComparator(),
-			}
-			queue2 := &frameworkmocks.MockFlowQueueAccessor{
-				LenV:        1,
-				PeekHeadV:   typesmocks.NewMockQueueItemAccessor(10, "item2", flow2),
-				FlowSpecV:   types.FlowSpecification{ID: flow2},
-				ComparatorV: newTestComparator(),
-			}
-
-			mockBand := &frameworkmocks.MockPriorityBandAccessor{
-				FlowIDsV: []string{flow1, flow2},
-				QueueFuncV: func(id string) framework.FlowQueueAccessor {
-					if id == flow1 {
-						return queue1
-					}
-					if id == flow2 {
-						return queue2
-					}
-					return nil
+				flow2: queue2,
+			}),
+			expectedQueueID: flow2,
+		},
+		{
+			name: "QueueComparatorIsNil",
+			band: newTestBand(map[string]framework.FlowQueueAccessor{
+				flow1: &frameworkmocks.MockFlowQueueAccessor{
+					LenV:        1,
+					PeekHeadV:   itemBetter,
+					FlowSpecV:   types.FlowSpecification{ID: flow1},
+					ComparatorV: nil,
 				},
-			}
-			selected, err := policy.SelectQueue(mockBand)
-			require.NoError(t, err, "Policy should gracefully skip queue with PeekHead error")
-			require.NotNil(t, selected, "Policy should select the valid queue (flow2)")
-			assert.Equal(t, flow2, selected.FlowSpec().ID, "Should select the valid queue when the other has a peek error")
-		})
+				flow2: queue2,
+			}),
+			shouldPanic: true,
+		},
+		{
+			name: "ComparatorFuncIsNil",
+			band: newTestBand(map[string]framework.FlowQueueAccessor{
+				flow1: &frameworkmocks.MockFlowQueueAccessor{
+					LenV:        1,
+					PeekHeadV:   itemBetter,
+					FlowSpecV:   types.FlowSpecification{ID: flow1},
+					ComparatorV: &frameworkmocks.MockItemComparator{ScoreTypeV: commonScoreType, FuncV: nil},
+				},
+				flow2: queue2,
+			}),
+			shouldPanic: true,
+		},
+		{
+			name: "AllQueuesEmpty",
+			band: newTestBand(map[string]framework.FlowQueueAccessor{
+				"empty1": queueEmpty,
+				"empty2": queueEmpty,
+			}),
+		},
+		{
+			name: "NilBand",
+			band: nil,
+		},
+	}
 
-		t.Run("QueueComparatorIsNil", func(t *testing.T) {
+	for _, tc := range testCases {
+		t.Run(tc.name, func(t *testing.T) {
 			t.Parallel()
-			queue1 := &frameworkmocks.MockFlowQueueAccessor{
-				LenV:        1,
-				PeekHeadV:   typesmocks.NewMockQueueItemAccessor(10, "item1", flow1),
-				FlowSpecV:   types.FlowSpecification{ID: flow1},
-				ComparatorV: nil, // Nil Comparator
-			}
-			queue2 := &frameworkmocks.MockFlowQueueAccessor{ // A valid queue
-				LenV:        1,
-				PeekHeadV:   typesmocks.NewMockQueueItemAccessor(20, "item2", flow2),
-				FlowSpecV:   types.FlowSpecification{ID: flow2},
-				ComparatorV: newTestComparator(),
-			}
 
-			mockBand := &frameworkmocks.MockPriorityBandAccessor{
-				FlowIDsV: []string{flow1, flow2},
-				QueueFuncV: func(id string) framework.FlowQueueAccessor {
-					if id == flow1 {
-						return queue1
-					}
-					if id == flow2 {
-						return queue2
-					}
-					return nil
-				},
+			if tc.shouldPanic {
+				assert.Panics(t, func() { _, _ = policy.SelectQueue(tc.band) }, "SelectQueue should panic for this edge case")
+				return
 			}
 
-			require.NotNil(t, queue1, "Setup: queue1 should not be nil")
-			require.Nil(t, queue1.Comparator(), "Setup: queue1's comparator should be nil for this test")
-			assert.Panics(t, func() {
-				_, _ = policy.SelectQueue(mockBand)
-			}, "Policy should panic if a queue's comparator is nil when it's about to be used.")
-		})
+			selected, err := policy.SelectQueue(tc.band)
 
-		t.Run("ComparatorFuncIsNil", func(t *testing.T) {
-			t.Parallel()
-			queue1 := &frameworkmocks.MockFlowQueueAccessor{
-				LenV:      1,
-				PeekHeadV: typesmocks.NewMockQueueItemAccessor(10, "item1", flow1),
-				FlowSpecV: types.FlowSpecification{ID: flow1},
-				ComparatorV: &frameworkmocks.MockItemComparator{ // Comparator exists
-					ScoreTypeV: commonScoreType,
-					FuncV:      nil, // But its Func is nil
-				},
-			}
-			queue2 := &frameworkmocks.MockFlowQueueAccessor{ // A valid queue
-				LenV:        1,
-				PeekHeadV:   typesmocks.NewMockQueueItemAccessor(20, "item2", flow2),
-				FlowSpecV:   types.FlowSpecification{ID: flow2},
-				ComparatorV: newTestComparator(),
-			}
-			mockBand := &frameworkmocks.MockPriorityBandAccessor{
-				FlowIDsV: []string{flow1, flow2},
-				QueueFuncV: func(id string) framework.FlowQueueAccessor {
-					if id == flow1 {
-						return queue1
-					}
-					if id == flow2 {
-						return queue2
-					}
-					return nil
-				},
+			if tc.expectedErr != nil {
+				require.Error(t, err, "SelectQueue should return an error")
+				assert.ErrorIs(t, err, tc.expectedErr, "The returned error should match the expected error type")
+				assert.Nil(t, selected, "No queue should be selected when an error occurs")
+			} else {
+				require.NoError(t, err, "SelectQueue should not return an error for valid inputs")
+				if tc.expectedQueueID == "" {
+					assert.Nil(t, selected, "No queue should be selected")
+				} else {
+					require.NotNil(t, selected, "A queue should have been selected")
+					assert.Equal(t, tc.expectedQueueID, selected.FlowSpec().ID, "The selected queue should have the expected ID")
+				}
 			}
-
-			// Similar to nil comparator, current bestHead panics if Func is nil.
-			require.NotNil(t, queue1, "Setup: queue1 should not be nil")
-			require.NotNil(t, queue1.Comparator(), "Setup: queue1's comparator should NOT be nil for this test")
-			require.Nil(t, queue1.Comparator().Func(), "Setup: queue1's comparator Func should be nil for this test")
-			assert.Panics(t, func() {
-				_, _ = policy.SelectQueue(mockBand)
-			}, "Policy should panic if a comparator's func is nil when it's about to be used.")
 		})
-	})
+	}
 }
diff --git a/pkg/epp/flowcontrol/framework/plugins/policies/interflow/dispatch/functional_test.go b/pkg/epp/flowcontrol/framework/plugins/policies/interflow/dispatch/functional_test.go
index dd5d31a..9dacc2a 100644
--- a/pkg/epp/flowcontrol/framework/plugins/policies/interflow/dispatch/functional_test.go
+++ b/pkg/epp/flowcontrol/framework/plugins/policies/interflow/dispatch/functional_test.go
@@ -25,10 +25,9 @@ import (
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework"
 	frameworkmocks "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework/mocks"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework/plugins/policies/interflow/dispatch"
-	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/types"
-
 	_ "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework/plugins/policies/interflow/dispatch/besthead"
 	_ "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework/plugins/policies/interflow/dispatch/roundrobin"
+	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/types"
 )
 
 // TestInterFlowDispatchPolicy_Conformance is the main conformance test suite for `framework.InterFlowDispatchPolicy`
@@ -85,8 +84,8 @@ func runSelectQueueConformanceTests(t *testing.T, policy framework.InterFlowDisp
 		{
 			name: "With an empty priority band accessor",
 			band: &frameworkmocks.MockPriorityBandAccessor{
-				FlowIDsV:       []string{},
-				IterateQueuesV: func(callback func(queue framework.FlowQueueAccessor) bool) { /* no-op */ },
+				FlowIDsFunc:       func() []string { return []string{} },
+				IterateQueuesFunc: func(callback func(queue framework.FlowQueueAccessor) bool) { /* no-op */ },
 			},
 			expectErr: false,
 			expectNil: true,
@@ -94,8 +93,8 @@ func runSelectQueueConformanceTests(t *testing.T, policy framework.InterFlowDisp
 		{
 			name: "With a band that has one empty queue",
 			band: &frameworkmocks.MockPriorityBandAccessor{
-				FlowIDsV: []string{flowIDEmpty},
-				QueueFuncV: func(fID string) framework.FlowQueueAccessor {
+				FlowIDsFunc: func() []string { return []string{flowIDEmpty} },
+				QueueFunc: func(fID string) framework.FlowQueueAccessor {
 					if fID == flowIDEmpty {
 						return mockQueueEmpty
 					}
@@ -108,8 +107,8 @@ func runSelectQueueConformanceTests(t *testing.T, policy framework.InterFlowDisp
 		{
 			name: "With a band that has multiple empty queues",
 			band: &frameworkmocks.MockPriorityBandAccessor{
-				FlowIDsV: []string{flowIDEmpty, "flow-empty-2"},
-				QueueFuncV: func(fID string) framework.FlowQueueAccessor {
+				FlowIDsFunc: func() []string { return []string{flowIDEmpty, "flow-empty-2"} },
+				QueueFunc: func(fID string) framework.FlowQueueAccessor {
 					return mockQueueEmpty
 				},
 			},
diff --git a/pkg/epp/flowcontrol/framework/plugins/policies/interflow/dispatch/roundrobin/roundrobin_test.go b/pkg/epp/flowcontrol/framework/plugins/policies/interflow/dispatch/roundrobin/roundrobin_test.go
index 804a4c8..f2255f0 100644
--- a/pkg/epp/flowcontrol/framework/plugins/policies/interflow/dispatch/roundrobin/roundrobin_test.go
+++ b/pkg/epp/flowcontrol/framework/plugins/policies/interflow/dispatch/roundrobin/roundrobin_test.go
@@ -46,8 +46,8 @@ func TestRoundRobin_SelectQueue_Logic(t *testing.T) {
 	queue3 := &frameworkmocks.MockFlowQueueAccessor{LenV: 3, FlowSpecV: types.FlowSpecification{ID: "flow3"}}
 
 	mockBand := &frameworkmocks.MockPriorityBandAccessor{
-		FlowIDsV: []string{"flow3", "flow1", "flow2"}, // Unsorted to test sorting
-		QueueFuncV: func(id string) framework.FlowQueueAccessor {
+		FlowIDsFunc: func() []string { return []string{"flow3", "flow1", "flow2"} }, // Unsorted to test sorting
+		QueueFunc: func(id string) framework.FlowQueueAccessor {
 			switch id {
 			case "flow1":
 				return queue1
@@ -68,7 +68,8 @@ func TestRoundRobin_SelectQueue_Logic(t *testing.T) {
 		selected, err := policy.SelectQueue(mockBand)
 		require.NoError(t, err, "SelectQueue should not error on a valid band")
 		require.NotNil(t, selected, "SelectQueue should have selected a queue")
-		assert.Equal(t, expectedOrder[i], selected.FlowSpec().ID, "Cycle 1, selection %d should be %s", i+1, expectedOrder[i])
+		assert.Equal(t, expectedOrder[i], selected.FlowSpec().ID,
+			"Cycle 1, selection %d should be %s", i+1, expectedOrder[i])
 	}
 
 	// Second cycle (wraps around)
@@ -76,7 +77,8 @@ func TestRoundRobin_SelectQueue_Logic(t *testing.T) {
 		selected, err := policy.SelectQueue(mockBand)
 		require.NoError(t, err, "SelectQueue should not error on a valid band")
 		require.NotNil(t, selected, "SelectQueue should have selected a queue")
-		assert.Equal(t, expectedOrder[i], selected.FlowSpec().ID, "Cycle 2, selection %d should be %s", i+1, expectedOrder[i])
+		assert.Equal(t, expectedOrder[i], selected.FlowSpec().ID,
+			"Cycle 2, selection %d should be %s", i+1, expectedOrder[i])
 	}
 }
 
@@ -90,8 +92,8 @@ func TestRoundRobin_SelectQueue_SkipsEmptyQueues(t *testing.T) {
 	queue3 := &frameworkmocks.MockFlowQueueAccessor{LenV: 3, FlowSpecV: types.FlowSpecification{ID: "flow3"}}
 
 	mockBand := &frameworkmocks.MockPriorityBandAccessor{
-		FlowIDsV: []string{"flow1", "flowEmpty", "flow3"},
-		QueueFuncV: func(id string) framework.FlowQueueAccessor {
+		FlowIDsFunc: func() []string { return []string{"flow1", "flowEmpty", "flow3"} },
+		QueueFunc: func(id string) framework.FlowQueueAccessor {
 			switch id {
 			case "flow1":
 				return queue1
@@ -129,8 +131,8 @@ func TestRoundRobin_SelectQueue_HandlesDynamicFlows(t *testing.T) {
 	queue1 := &frameworkmocks.MockFlowQueueAccessor{LenV: 1, FlowSpecV: types.FlowSpecification{ID: "flow1"}}
 	queue2 := &frameworkmocks.MockFlowQueueAccessor{LenV: 1, FlowSpecV: types.FlowSpecification{ID: "flow2"}}
 	mockBand := &frameworkmocks.MockPriorityBandAccessor{
-		FlowIDsV: []string{"flow1", "flow2"},
-		QueueFuncV: func(id string) framework.FlowQueueAccessor {
+		FlowIDsFunc: func() []string { return []string{"flow1", "flow2"} },
+		QueueFunc: func(id string) framework.FlowQueueAccessor {
 			if id == "flow1" {
 				return queue1
 			}
@@ -146,8 +148,8 @@ func TestRoundRobin_SelectQueue_HandlesDynamicFlows(t *testing.T) {
 
 	// --- Simulate adding a flow ---
 	queue3 := &frameworkmocks.MockFlowQueueAccessor{LenV: 1, FlowSpecV: types.FlowSpecification{ID: "flow3"}}
-	mockBand.FlowIDsV = []string{"flow1", "flow2", "flow3"}
-	mockBand.QueueFuncV = func(id string) framework.FlowQueueAccessor {
+	mockBand.FlowIDsFunc = func() []string { return []string{"flow1", "flow2", "flow3"} }
+	mockBand.QueueFunc = func(id string) framework.FlowQueueAccessor {
 		switch id {
 		case "flow1":
 			return queue1
@@ -172,7 +174,7 @@ func TestRoundRobin_SelectQueue_HandlesDynamicFlows(t *testing.T) {
 	assert.Equal(t, "flow3", selected.FlowSpec().ID, "Next selection should be the new flow3")
 
 	// --- Simulate removing a flow ---
-	mockBand.FlowIDsV = []string{"flow1", "flow3"} // flow2 is removed
+	mockBand.FlowIDsFunc = func() []string { return []string{"flow1", "flow3"} } // flow2 is removed
 
 	// Next selection should wrap around and pick flow1
 	selected, err = policy.SelectQueue(mockBand)
@@ -198,8 +200,8 @@ func TestRoundRobin_SelectQueue_Concurrency(t *testing.T) {
 			numQueues := int64(len(queues))
 
 			mockBand := &frameworkmocks.MockPriorityBandAccessor{
-				FlowIDsV: []string{"flow1", "flow2", "flow3"},
-				QueueFuncV: func(id string) framework.FlowQueueAccessor {
+				FlowIDsFunc: func() []string { return []string{"flow1", "flow2", "flow3"} },
+				QueueFunc: func(id string) framework.FlowQueueAccessor {
 					for _, q := range queues {
 						if q.FlowSpec().ID == id {
 							return q
diff --git a/pkg/epp/flowcontrol/framework/plugins/policies/intraflow/dispatch/functional_test.go b/pkg/epp/flowcontrol/framework/plugins/policies/intraflow/dispatch/functional_test.go
index 5a78d3e..01e8a1c 100644
--- a/pkg/epp/flowcontrol/framework/plugins/policies/intraflow/dispatch/functional_test.go
+++ b/pkg/epp/flowcontrol/framework/plugins/policies/intraflow/dispatch/functional_test.go
@@ -25,7 +25,6 @@ import (
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework"
 	frameworkmocks "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework/mocks"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework/plugins/policies/intraflow/dispatch"
-
 	_ "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework/plugins/policies/intraflow/dispatch/fcfs"
 )
 
diff --git a/pkg/epp/flowcontrol/framework/plugins/queue/functional_test.go b/pkg/epp/flowcontrol/framework/plugins/queue/functional_test.go
index 7e33961..fe01053 100644
--- a/pkg/epp/flowcontrol/framework/plugins/queue/functional_test.go
+++ b/pkg/epp/flowcontrol/framework/plugins/queue/functional_test.go
@@ -27,14 +27,14 @@ import (
 
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
+
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework"
 	frameworkmocks "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework/mocks"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework/plugins/queue"
-	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/types"
-	typesmocks "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/types/mocks"
-
 	_ "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework/plugins/queue/listqueue"
 	_ "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework/plugins/queue/maxminheap"
+	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/types"
+	typesmocks "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/types/mocks"
 )
 
 // enqueueTimeComparator orders items by their enqueue time (earlier first).
diff --git a/pkg/epp/flowcontrol/framework/plugins/queue/maxminheap/maxminheap_test.go b/pkg/epp/flowcontrol/framework/plugins/queue/maxminheap/maxminheap_test.go
index 165d48f..39e82fb 100644
--- a/pkg/epp/flowcontrol/framework/plugins/queue/maxminheap/maxminheap_test.go
+++ b/pkg/epp/flowcontrol/framework/plugins/queue/maxminheap/maxminheap_test.go
@@ -22,6 +22,7 @@ import (
 	"time"
 
 	"github.com/stretchr/testify/require"
+
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework/mocks"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/types"
 	typesmocks "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/types/mocks"
diff --git a/pkg/epp/handlers/response_test.go b/pkg/epp/handlers/response_test.go
index b79f4ee..6eb7734 100644
--- a/pkg/epp/handlers/response_test.go
+++ b/pkg/epp/handlers/response_test.go
@@ -22,6 +22,7 @@ import (
 	"testing"
 
 	"github.com/google/go-cmp/cmp"
+
 	logutil "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/util/logging"
 )
 
diff --git a/pkg/epp/metrics/collectors/inference_pool_test.go b/pkg/epp/metrics/collectors/inference_pool_test.go
index e5befd0..e855c55 100644
--- a/pkg/epp/metrics/collectors/inference_pool_test.go
+++ b/pkg/epp/metrics/collectors/inference_pool_test.go
@@ -28,6 +28,7 @@ import (
 	"k8s.io/apimachinery/pkg/types"
 	"k8s.io/component-base/metrics/testutil"
 	"sigs.k8s.io/controller-runtime/pkg/client/fake"
+
 	v1 "sigs.k8s.io/gateway-api-inference-extension/api/v1"
 	backendmetrics "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/backend/metrics"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/datastore"
diff --git a/pkg/epp/metrics/metrics_test.go b/pkg/epp/metrics/metrics_test.go
index 5dd9705..d2e209b 100644
--- a/pkg/epp/metrics/metrics_test.go
+++ b/pkg/epp/metrics/metrics_test.go
@@ -24,6 +24,7 @@ import (
 
 	"k8s.io/component-base/metrics/testutil"
 	"sigs.k8s.io/controller-runtime/pkg/metrics"
+
 	errutil "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/util/error"
 	logutil "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/util/logging"
 )
diff --git a/pkg/epp/requestcontrol/director_test.go b/pkg/epp/requestcontrol/director_test.go
index 2050491..814af12 100644
--- a/pkg/epp/requestcontrol/director_test.go
+++ b/pkg/epp/requestcontrol/director_test.go
@@ -32,6 +32,7 @@ import (
 	k8stypes "k8s.io/apimachinery/pkg/types"
 	clientgoscheme "k8s.io/client-go/kubernetes/scheme"
 	"sigs.k8s.io/controller-runtime/pkg/client/fake"
+
 	v1 "sigs.k8s.io/gateway-api-inference-extension/api/v1"
 	"sigs.k8s.io/gateway-api-inference-extension/apix/v1alpha2"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/backend"
diff --git a/pkg/epp/saturationdetector/saturationdetector_test.go b/pkg/epp/saturationdetector/saturationdetector_test.go
index 42e81b5..5ec0734 100644
--- a/pkg/epp/saturationdetector/saturationdetector_test.go
+++ b/pkg/epp/saturationdetector/saturationdetector_test.go
@@ -26,6 +26,7 @@ import (
 
 	"github.com/go-logr/logr"
 	"k8s.io/apimachinery/pkg/types"
+
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/backend"
 	backendmetrics "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/backend/metrics"
 )
diff --git a/pkg/epp/scheduling/framework/plugins/multi/prefix/plugin_test.go b/pkg/epp/scheduling/framework/plugins/multi/prefix/plugin_test.go
index 27e13d6..aaf68f0 100644
--- a/pkg/epp/scheduling/framework/plugins/multi/prefix/plugin_test.go
+++ b/pkg/epp/scheduling/framework/plugins/multi/prefix/plugin_test.go
@@ -26,6 +26,7 @@ import (
 
 	"github.com/stretchr/testify/assert"
 	k8stypes "k8s.io/apimachinery/pkg/types"
+
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/backend"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/scheduling/types"
 )
diff --git a/pkg/epp/scheduling/framework/plugins/picker/picker_test.go b/pkg/epp/scheduling/framework/plugins/picker/picker_test.go
index 2089ed3..2c3aceb 100644
--- a/pkg/epp/scheduling/framework/plugins/picker/picker_test.go
+++ b/pkg/epp/scheduling/framework/plugins/picker/picker_test.go
@@ -21,6 +21,7 @@ import (
 	"testing"
 
 	"github.com/google/go-cmp/cmp"
+	"github.com/google/go-cmp/cmp/cmpopts"
 	k8stypes "k8s.io/apimachinery/pkg/types"
 
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/backend"
@@ -34,10 +35,11 @@ func TestPickMaxScorePicker(t *testing.T) {
 	pod3 := &types.PodMetrics{Pod: &backend.Pod{NamespacedName: k8stypes.NamespacedName{Name: "pod3"}}}
 
 	tests := []struct {
-		name   string
-		picker framework.Picker
-		input  []*types.ScoredPod
-		output []types.Pod
+		name               string
+		picker             framework.Picker
+		input              []*types.ScoredPod
+		output             []types.Pod
+		tieBreakCandidates int // tie break is random, specify how many candidate with max score
 	}{
 		{
 			name:   "Single max score",
@@ -63,6 +65,7 @@ func TestPickMaxScorePicker(t *testing.T) {
 				&types.ScoredPod{Pod: pod1, Score: 50},
 				&types.ScoredPod{Pod: pod2, Score: 50},
 			},
+			tieBreakCandidates: 2,
 		},
 		{
 			name:   "Multiple results sorted by highest score, more pods than needed",
@@ -104,6 +107,7 @@ func TestPickMaxScorePicker(t *testing.T) {
 				&types.ScoredPod{Pod: pod3, Score: 30},
 				&types.ScoredPod{Pod: pod2, Score: 25},
 			},
+			tieBreakCandidates: 2,
 		},
 	}
 
@@ -112,6 +116,19 @@ func TestPickMaxScorePicker(t *testing.T) {
 			result := test.picker.Pick(context.Background(), types.NewCycleState(), test.input)
 			got := result.TargetPods
 
+			if test.tieBreakCandidates > 0 {
+				testMaxScoredPods := test.output[:test.tieBreakCandidates]
+				gotMaxScoredPods := got[:test.tieBreakCandidates]
+				diff := cmp.Diff(testMaxScoredPods, gotMaxScoredPods, cmpopts.SortSlices(func(a, b types.Pod) bool {
+					return a.String() < b.String() // predictable order within the pods with equal scores
+				}))
+				if diff != "" {
+					t.Errorf("Unexpected output (-want +got): %v", diff)
+				}
+				test.output = test.output[test.tieBreakCandidates:]
+				got = got[test.tieBreakCandidates:]
+			}
+
 			if diff := cmp.Diff(test.output, got); diff != "" {
 				t.Errorf("Unexpected output (-want +got): %v", diff)
 			}
diff --git a/pkg/epp/scheduling/framework/plugins/scorer/kvcache_test.go b/pkg/epp/scheduling/framework/plugins/scorer/kvcache_test.go
index c0eeb52..81f6d0a 100644
--- a/pkg/epp/scheduling/framework/plugins/scorer/kvcache_test.go
+++ b/pkg/epp/scheduling/framework/plugins/scorer/kvcache_test.go
@@ -21,6 +21,7 @@ import (
 	"testing"
 
 	"github.com/stretchr/testify/assert"
+
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/backend"
 	backendmetrics "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/backend/metrics"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/scheduling/types"
diff --git a/pkg/epp/scheduling/framework/plugins/scorer/queue_test.go b/pkg/epp/scheduling/framework/plugins/scorer/queue_test.go
index a9a8115..ce81936 100644
--- a/pkg/epp/scheduling/framework/plugins/scorer/queue_test.go
+++ b/pkg/epp/scheduling/framework/plugins/scorer/queue_test.go
@@ -21,6 +21,7 @@ import (
 	"testing"
 
 	"github.com/stretchr/testify/assert"
+
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/backend"
 	backendmetrics "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/backend/metrics"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/scheduling/types"
diff --git a/pkg/epp/scheduling/framework/plugins/test/filter/filter_test.go b/pkg/epp/scheduling/framework/plugins/test/filter/filter_test.go
index 1eb1291..28cfcda 100644
--- a/pkg/epp/scheduling/framework/plugins/test/filter/filter_test.go
+++ b/pkg/epp/scheduling/framework/plugins/test/filter/filter_test.go
@@ -21,6 +21,7 @@ import (
 	"testing"
 
 	"github.com/google/go-cmp/cmp"
+
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/backend"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/scheduling/types"
 )
diff --git a/pkg/epp/scheduling/scheduler_test.go b/pkg/epp/scheduling/scheduler_test.go
index 8923c3d..9e5d950 100644
--- a/pkg/epp/scheduling/scheduler_test.go
+++ b/pkg/epp/scheduling/scheduler_test.go
@@ -23,6 +23,7 @@ import (
 	"github.com/google/go-cmp/cmp"
 	"github.com/google/uuid"
 	k8stypes "k8s.io/apimachinery/pkg/types"
+
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/backend"
 	backendmetrics "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/backend/metrics" // Import config for thresholds
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/scheduling/config"
diff --git a/pkg/epp/server/server_test.go b/pkg/epp/server/server_test.go
index c591523..bcf0d07 100644
--- a/pkg/epp/server/server_test.go
+++ b/pkg/epp/server/server_test.go
@@ -24,6 +24,7 @@ import (
 	pb "github.com/envoyproxy/go-control-plane/envoy/service/ext_proc/v3"
 	v1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
 	"sigs.k8s.io/gateway-api-inference-extension/apix/v1alpha2"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/backend"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/handlers"
diff --git a/pkg/epp/util/env/env_test.go b/pkg/epp/util/env/env_test.go
index 4cf0223..10b0b55 100644
--- a/pkg/epp/util/env/env_test.go
+++ b/pkg/epp/util/env/env_test.go
@@ -6,6 +6,7 @@ import (
 	"time"
 
 	"github.com/go-logr/logr/testr"
+
 	logutil "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/util/logging"
 )
 
diff --git a/pkg/epp/util/testing/diff.go b/pkg/epp/util/testing/diff.go
index def3b14..4acd4b9 100644
--- a/pkg/epp/util/testing/diff.go
+++ b/pkg/epp/util/testing/diff.go
@@ -19,6 +19,7 @@ package testing
 import (
 	"github.com/google/go-cmp/cmp"
 	"github.com/google/go-cmp/cmp/cmpopts"
+
 	"sigs.k8s.io/gateway-api-inference-extension/apix/v1alpha2"
 )
 
diff --git a/pkg/epp/util/testing/wrappers.go b/pkg/epp/util/testing/wrappers.go
index 3992916..24102dc 100644
--- a/pkg/epp/util/testing/wrappers.go
+++ b/pkg/epp/util/testing/wrappers.go
@@ -19,6 +19,7 @@ package testing
 import (
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
 	v1 "sigs.k8s.io/gateway-api-inference-extension/api/v1"
 	"sigs.k8s.io/gateway-api-inference-extension/apix/v1alpha2"
 )
diff --git a/test/e2e/epp/e2e_suite_test.go b/test/e2e/epp/e2e_suite_test.go
index d0da4ac..e4ca604 100644
--- a/test/e2e/epp/e2e_suite_test.go
+++ b/test/e2e/epp/e2e_suite_test.go
@@ -40,6 +40,7 @@ import (
 	clientgoscheme "k8s.io/client-go/kubernetes/scheme"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 	"sigs.k8s.io/controller-runtime/pkg/client/config"
+
 	infextv1 "sigs.k8s.io/gateway-api-inference-extension/api/v1"
 	infextv1a2 "sigs.k8s.io/gateway-api-inference-extension/apix/v1alpha2"
 	testutils "sigs.k8s.io/gateway-api-inference-extension/test/utils"
diff --git a/test/e2e/epp/e2e_test.go b/test/e2e/epp/e2e_test.go
index 91aa74e..ec55828 100644
--- a/test/e2e/epp/e2e_test.go
+++ b/test/e2e/epp/e2e_test.go
@@ -33,6 +33,7 @@ import (
 	"k8s.io/apimachinery/pkg/types"
 	"k8s.io/utils/ptr"
 	"sigs.k8s.io/controller-runtime/pkg/client"
+
 	"sigs.k8s.io/gateway-api-inference-extension/apix/v1alpha2"
 	testutils "sigs.k8s.io/gateway-api-inference-extension/test/utils"
 )
diff --git a/test/integration/bbr/hermetic_test.go b/test/integration/bbr/hermetic_test.go
index 8fd479f..69654be 100644
--- a/test/integration/bbr/hermetic_test.go
+++ b/test/integration/bbr/hermetic_test.go
@@ -29,6 +29,7 @@ import (
 	"google.golang.org/grpc"
 	"google.golang.org/grpc/credentials/insecure"
 	"google.golang.org/protobuf/testing/protocmp"
+
 	runserver "sigs.k8s.io/gateway-api-inference-extension/pkg/bbr/server"
 	logutil "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/util/logging"
 	integrationutils "sigs.k8s.io/gateway-api-inference-extension/test/integration"
diff --git a/test/integration/util.go b/test/integration/util.go
index 925107b..996086e 100644
--- a/test/integration/util.go
+++ b/test/integration/util.go
@@ -28,6 +28,7 @@ import (
 	envoyTypePb "github.com/envoyproxy/go-control-plane/envoy/type/v3"
 	"github.com/go-logr/logr"
 	"google.golang.org/protobuf/types/known/structpb"
+
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/server"
 	logutil "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/util/logging"
 )
diff --git a/test/utils/server.go b/test/utils/server.go
index 090d2bc..e83ef60 100644
--- a/test/utils/server.go
+++ b/test/utils/server.go
@@ -32,6 +32,7 @@ import (
 	clientgoscheme "k8s.io/client-go/kubernetes/scheme"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 	"sigs.k8s.io/controller-runtime/pkg/client/fake"
+
 	v1 "sigs.k8s.io/gateway-api-inference-extension/api/v1"
 	"sigs.k8s.io/gateway-api-inference-extension/apix/v1alpha2"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/backend/metrics"
diff --git a/test/utils/utils.go b/test/utils/utils.go
index e814a31..71293f0 100644
--- a/test/utils/utils.go
+++ b/test/utils/utils.go
@@ -36,6 +36,7 @@ import (
 	"k8s.io/client-go/rest"
 	"k8s.io/client-go/tools/remotecommand"
 	"sigs.k8s.io/controller-runtime/pkg/client"
+
 	v1 "sigs.k8s.io/gateway-api-inference-extension/api/v1"
 	"sigs.k8s.io/gateway-api-inference-extension/apix/v1alpha2"
 )
diff --git a/test/utils/wrappers.go b/test/utils/wrappers.go
index 0ad385d..ca0b1cb 100644
--- a/test/utils/wrappers.go
+++ b/test/utils/wrappers.go
@@ -19,6 +19,7 @@ package utils
 import (
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/types"
+
 	v1 "sigs.k8s.io/gateway-api-inference-extension/api/v1"
 	"sigs.k8s.io/gateway-api-inference-extension/apix/v1alpha2"
 )