Skip to content

ORT 1.30.1 Cherry Picks - #33524

Merged
adrastogi merged 15 commits into
rel-1.30.1from
adrastogi/1.30.1-cherry-picks
Oct 27, 2026
Merged

adrastogi merged 15 commits into
rel-1.30.1from
adrastogi/1.30.1-cherry-picks

Conversation

@adrastogi

@adrastogi adrastogi commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Description

This cherry-picks the following commits for the release:

CI fixes:

  • [CUDA] Guard FP8 XQA test by compute capability #32559 (8ec7981a7439546a54196b9cbc777ae5de708b6b): guard FP8 XQA test cases by GPU compute capability. The Windows CUDA runner is an SM86 A10, while FP8 XQA requires SM89 or SM90+. INT4/INT8 XQA coverage remains enabled on supported SM80+ devices. This fixes the two FP8 dispatch assertions without changing product behavior.
  • Raise the Android minimal baseline binary-size threshold by 1 KiB, from 1,589,248 to 1,590,272 bytes (release branch only). CI reports a section total of 1,590,022 bytes, exceeding the previous threshold by 774 bytes. The adjusted threshold leaves 250 bytes of headroom.
  • Move back to main A10 image #32676, then Fix CUDA CICD. Remove unnecessary image override. #33489: rename the old A10-Test image and remove the unnecessary image override, in upstream order.
  • [CICD Stability] Start transition to scaleset based providers #33492: backport the scale-set runner migration across the release branch's 41 affected workflows. The Linux CUDA, CUDA Plugin, and TensorRT test jobs now use ort-github-linux-6-a10-scus-ss. Their previous retries were cancelled by 1es-resource-management[bot] before any steps executed.

The first ten cherry-picks, plus #32676 and #33489, applied cleanly from the original mainline commits, with source commit provenance preserved. #32607 includes the full mainline fix and regression tests rather than the reduced 1.28.3 backport.

#33492 required conflict resolution because the release branch has an older workflow layout:

  • Preserve the existing Linux CI and Linux WebGPU job sets; do not introduce main-only no-exceptions or static-plugin jobs.
  • Leave windows_arm64_python.yml absent. It was introduced after 1.30 branched by Add github action for arm64 windows build #32791; its runner migration does not require adding that workflow to this release.
  • Preserve Windows WebGPU's combined build/test jobs and their check names, keeping them on the new GPU scale set rather than importing main's split build/test topology. The build-only minimal Edge job uses the new CPU scale set.

Motivation and Context

Bring the product fixes from #32806 into ORT 1.30.1, address the Windows CUDA test and Android size-gate failures, and migrate CI runner selection to unblock the cancelled GPU jobs.

The merged EP API version correction from #33525 was brought in by merging the updated rel-1.30.1 base. The uuid-dev CI fix in #32491 was already present in the 1.30 base and is not duplicated.

The OpenVINO changes in #33112 and #33327 are intentionally excluded: the namespace regression fixed by #33327 was introduced by #33112, and neither change is present in the 1.30 base.

Validation:

  • All nine original product cherry-pick patch IDs were verified against their mainline commits; the additional [CUDA] Guard FP8 XQA test by compute capability #32559 patch ID also matches upstream.
  • The upstream test_fp8_xqa_cuda_capability regression passed in an isolated standard-library harness using mocked SM86, SM89, and SM90 capabilities. Additional no-CUDA and external-runner cases passed.
  • Python syntax and Android threshold consistency/arithmetic checks passed.
  • git diff --check 3b0f46f82c HEAD passed.
  • All 41 migrated workflow YAML files parse. Structural comparisons against the pre-migration release workflows confirm that only runner labels, caller pool names, and the reusable pool-input description changed; job sets, steps, triggers, permissions, matrices, and build flags are preserved.
  • All 13 callers of the reusable Linux build workflow use scale-set pool names; all three previously cancelled GPU test jobs use the new A10 scale set.
  • The Android release-specific size threshold remains 1,590,272 bytes.
  • The full helper pytest invocation was not runnable because pytest is not installed in the local virtual environment. No local GPU execution or Android rebuild was performed; CI will validate the integrated changes.

Wei Wang (wangw-1991) and others added 9 commits October 21, 2026 16:18
… scalar beta (#32610)

### Description

`EmbedLayerNormalizationShapeInference` validated the `beta` input's
rank using the wrong shape: `beta_dims` was aliased to
`gamma_shape.dim()` instead of `beta_shape.dim()`. As a result, a rank-1
`gamma` would let the rank check pass
even when `beta` is a 0-dim scalar, and execution reached
`beta_shape.dim(0).dim_value()` — an unchecked protobuf repeated-field
access on an empty `dim` list, causing an out-of-bounds read during
session load, before provider/kernel assignment.

### Fix

- Alias `beta_dims` to `beta_shape.dim()` so the rank check guards the
correct input; a scalar `beta` is now rejected via
`fail_shape_inference` instead of reaching the OOB access. This matches
the adjacent `gamma` validation.
- Correct the `gamma` error message ("2 dimension" → "1 dimension") to
reflect the actual check

(cherry picked from commit 7054657)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 3eb3fc9b-6147-4706-b7ad-47bb3476377b
### Description
<!-- Describe your changes. -->
Add an explicit validation in `Node::UpdateInputArgCount()` to reject a
node that supplies actual inputs while its bound operator/function
schema declares no formal input parameters.

### Motivation and Context
<!-- - Why is this change required? What problem does it solve?
- If it fixes an open issue, please link to the issue here. -->
When `op.inputs()` is empty but the node has ≥1 input, the arg-count
adjustment loop was skipped yet the trailing
`input_arg_count.push_back(arg_count_left)` still ran unconditionally,
producing `InputArgCount().size() == 1` against `op.inputs().size() ==
0`. This size-invariant violation later caused an out-of-bounds read at
`op.inputs()[i]` in `InferAndVerifyTypeMatch` during `Graph::Resolve()`.

This is reachable only via a model-local function in a custom domain:
for registered ops, `OpSchema::Verify` in the ONNX checker rejects the
extra inputs first, but for custom-domain function calls the checker
performs no arity validation.

(cherry picked from commit 613bc03)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 3eb3fc9b-6147-4706-b7ad-47bb3476377b
…te finalization (#32641)

### Description
`SessionState::FinalizeSessionStateImpl` iterates over the subgraphs
attached to each node and unconditionally downcasts the node's kernel to
`controlflow::IControlFlowKernel`, then calls
`SetupSubgraphExecutionInfo` on it:

```cpp
// Downcast is safe, since only control flow nodes have subgraphs
auto& control_flow_kernel = static_cast<controlflow::IControlFlowKernel&>(*p_op_kernel);
```

The "only control flow nodes have subgraphs" invariant is not enforced
anywhere. Node::Init materializes a subgraph for any attribute of type
GRAPH, with no schema gate, so an ordinary (non-control-flow) node can
carry a subgraph. When it does, the downcast above is invalid:
IControlFlowKernel adds a vtable slot that a plain OpKernel does not
have, so the call reads an out-of-bounds vtable slot — an
undefined-behavior type confusion that crashes (observed as an access
violation inside FinalizeSessionStateImpl).

This is reachable by loading a crafted/malformed model whose
non-control-flow node has a GRAPH-typed attribute (for example, an op
that permits unchecked attributes). ORT should reject such a model with
a clear error instead of executing the bad cast.

### Fix
Gate the downcast on a virtual predicate:
- Add `OpKernel::IsControlFlowKernel()` returning `false` by default.
- Override it to `true` on `IControlFlowKernel`, which covers
If/Loop/Scan and their CUDA derivatives.
- Check it in `FinalizeSessionStateImpl` before the cast and return an
error otherwise.

A virtual predicate is used rather than `dynamic_cast` because
`onnxruntime_DISABLE_RTTI` is on by default. There is no behavior change
for valid models: only the control-flow kernels inherit
`IControlFlowKernel`, and they always return `true`.

Adds
`InferenceSessionTests.SubgraphAttributeOnNonControlFlowNodeIsRejected`
test case, which builds a model whose non-control-flow node carries a
`GRAPH` attribute and asserts that session initialization fails
gracefully instead of triggering the downcast. Existing If/Loop/Scan
subgraph tests cover the no-regression path.

(cherry picked from commit b95cf78)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 3eb3fc9b-6147-4706-b7ad-47bb3476377b
…full-byte tensor (#32611)

### Description

The allocation planner's `SameSize()` decided buffer reuse by comparing
the C++ carrier size of the element type (`elt_type->Size()`) plus the
logical shape. Packed sub-byte types (`int4`/`uint4`) have the same
1-byte carrier size as `int8`/`uint8`, but one carrier stores 2 logical
elements. As a result a `uint4[N]` tensor (physical `ceil(N/2)` bytes)
and a `uint8[N]` tensor (physical `N` bytes) were treated as the same
size, and the smaller `uint4` buffer was reused for the `uint8` output.
Writing the `uint8` tensor into that half-sized buffer overflows it.

### Fix

- `SameSize()` now also requires the sub-element packing density
(`GetNumSubElems()`) to match, so tensors are only considered the same
size when their physical storage bytes are actually equal.
- `ExecutionFrame::AllocateMLValueTensorPreAllocateBuffer()` adds a
defense-in-depth capacity check that rejects a reuse when the requested
tensor needs more storage bytes than the buffer being reused (the
previous check only compared logical element counts).
- Added
`AllocationPlannerTest.AvoidReuseOfPackedSubByteBufferForFullByteTensor`,
which builds `X(float) → uint4 → float → uint8 → float` so a dead
`uint4[1024]` output would be reused by a `uint8[1024]` output. Without
the fix the planner reuses the buffer (`alloc_kind == kReuse`) and the
output is corrupted; with the fix the test passes and the model runs
correctly

(cherry picked from commit 061eecb)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 3eb3fc9b-6147-4706-b7ad-47bb3476377b
…izer (#32609)

### Problem

`OuterScopeNodeArgLocationAccumulator` (session_state.cc) maps a
Loop/Scan node's explicit inputs onto the subgraph's inputs using
`GraphViewer::GetInputs()`, which *excludes* initializer-backed inputs.
When a body declares an input that is also a
body initializer, `GetInputs()` is shorter than the parent node's input
list, so indexing `subgraph_inputs[arg_idx]` reads past the end of the
vector and dereferences an invalid `NodeArg` pointer during session
initialization. This causes a crash / heap out-of-bounds read
(observable under ASan) when loading a malformed model containing such a
Loop/Scan.

### Fix

In the Loop/Scan≥9 branch of `OuterScopeNodeArgLocationAccumulator`:
- If `subgraph.GetInputs().size()` does not equal the parent node's
input count, return an `INVALID_GRAPH` status naming the parent node and
both counts, instead of indexing. When the size difference is explained
by initializer-backed inputs (`GetInputsIncludingInitializers()` is
larger), the message adds a hint pointing at that as the cause.
- Add `Loop.BodyInputAlsoInitializerIsRejected` test: builds a Loop
whose body input `state_in` is also a body initializer, and asserts
`InferenceSession::Initialize()` fails with `INVALID_GRAPH` and the
expected message — i.e. rejected cleanly rather than crashing. The test
asserts on the status code and message text on purpose, so that it keeps
covering this path rather than silently falling through to the
`ORT_ENFORCE` downstream.

(cherry picked from commit 09dfa6a)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 3eb3fc9b-6147-4706-b7ad-47bb3476377b
### Summary

Strengthens attribute/input validation in three contrib-op
shape-inference functions in bert_defs.cc so malformed or malicious
models are rejected at `Graph::Resolve` instead of triggering
out-of-bounds reads or signed-integer overflow during shape inference.

### Changes

`CausalConvWithState`: validate the ndim attribute is in [1, 3] and
cross-check tensor ranks against it (weight == ndim+2, channels-first
input == ndim+2, channels-last input >= 3) before the spatial-dim loop
indexes input.dim(2+i). Previously only a rank >= 2 guard existed, so
ndim=2/3 with a low-rank input read past the shape's dimensions.
`GatedDeltaNet`: require the head counts/sizes to be positive and add
step-by-step overflow guards before computing the state_update capsule
width, preventing signed int64 overflow (UB) in state_update_capacity *
(num_heads_v + num_heads_k*head_size_qk + num_heads_v*head_size_v).
`GroupQueryAttention` / `SparseAttention`: check the parsed
`total_sequence_length` initializer is non-empty before indexing
data[0].

(cherry picked from commit bca9d15)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 3eb3fc9b-6147-4706-b7ad-47bb3476377b
### Description

Add an explicit rank-consistency check in
`convTransposeWithDynamicPadsShapeInference()` so that a derived
`kernel_shape` (built from the weight tensor's rank when the
`kernel_shape` attribute is absent) must have the same length as
`n_input_dims` (derived from the input tensor's rank) before it is used,
exactly like the existing check on the explicit-attribute path.

### Motivation and Context

`n_input_dims` is computed from input `X`'s rank. When `kernel_shape` is
not given as an attribute, it is instead derived from weight `W`'s rank.
If `W`'s rank disagrees with `X`'s rank, the resulting `kernel_shape`
(and `effective_kernel_shape`, sized identically) is shorter or longer
than `n_input_dims`. Both directions are unsafe:

- **Shorter** (e.g. X rank 5, W rank 3): the output-shape loop iterates
`n_input_dims` times over `effective_kernel_shape`/`pads`, reading past
the end of the shorter vector.
- **Longer** (e.g. X rank 3, W rank 5): the dilation loop iterates
`kernel_shape.size()` times over `dilations`, which is always sized to
`n_input_dims`, reading past the end of `dilations`.

This runs during `Graph::Resolve()` (model load), before any kernel
`Compute()` validation is ever reached.

### Testing

Added `ConvTransposeWithDynamicPads_MismatchedInputWeightRank` (X rank
5, W rank 3, no `kernel_shape` attribute), asserting the model now fails
cleanly at the existing kernel-level rank check (`"X num_dims does not
match W num_dims."`) instead of hitting the shape-inference OOB read
during load.

(cherry picked from commit 2ecddca)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 3eb3fc9b-6147-4706-b7ad-47bb3476377b
### Description
`InferenceContextImpl::getInputData` (graph.cc) indexed
`node_.InputDefs()` directly by
the schema input index during shape inference, with no bounds check. Add
the same bounds
check already used by `DataPropagationContextImpl::getInputData` in the
same file, so
`getInputData` returns `nullptr` (treated as "input not available")
instead of indexing
out of bounds.

### Motivation and Context
ONNX schemas can declare trailing inputs as optional (e.g.
`ConvTransposeWithDynamicPads`'s
`Pads`), so a node can validly omit them entirely, shrinking
`Node::InputDefs()` below the
schema's full input count. A `TypeAndShapeInferenceFunction` that
queries such an omitted
optional input's data (e.g. via `ctx.getInputData(index)`) on such a
node reads past the
end of the vector, causing an out-of-bounds read.

(cherry picked from commit e5f272c)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 3eb3fc9b-6147-4706-b7ad-47bb3476377b
### Description

Forward the caller's stream through the Plugin EP single-tensor
`CopyTensorImpl` path. This matches the existing batched-copy behavior
while preserving a null stream for synchronous copies.

Adds focused callback regression coverage for asynchronous, synchronous,
and batched copies.

### Motivation and Context

The single-tensor Plugin EP data-transfer path discarded the supplied
stream, preventing asynchronous copies from receiving the execution
stream.

Fixes #32643

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

(cherry picked from commit 5899c7c)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 3eb3fc9b-6147-4706-b7ad-47bb3476377b
@tianleiwu

Copy link
Copy Markdown
Contributor

It seems many CI failures. Might need cherry-pick some build related changes.

@adrastogi

Copy link
Copy Markdown
Contributor Author

It seems many CI failures. Might need cherry-pick some build related changes.

Tianlei Wu (@tianleiwu) yeah, there's a versioning fix that didn't make it through. 😢 #33525 should hopefully take care of most of these.

@tianleiwu

Copy link
Copy Markdown
Contributor

adrastogi, you can rebase since that fix is merged. Let's see whether there are other issues.

Aditya Rastogi and others added 3 commits October 21, 2026 20:43
Bring in the merged EP API version assertion correction from #33525.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 3eb3fc9b-6147-4706-b7ad-47bb3476377b
### Description
The Windows CUDA CI runner for PR #32515 uses an SM86 A10-4Q.
`PagedAttention` intentionally enables FP8 XQA only on SM89 or SM90+, so
the FP8 cases in `test_xqa_large_attention_scale_and_k_scale` fell back
to portable kernels and failed the XQA dispatch assertion.

Mirror the runtime capability predicate in the test and include the FP8
variant only on supported GPUs. UINT8 and INT8 remain covered on SM80
and newer devices. This is a capability guard, not a memory guard: the
failed job completed pytest normally and reported two assertion failures
rather than a CUDA allocation failure or process crash.

Failed job:
https://github.com/microsoft/onnxruntime/actions/runs/34435175610/job/102757939916?pr=32515

### Motivation and Context
Fixes the Windows GPU CUDA CI regression introduced by #32515 without
skipping valid XQA coverage on SM86.

### Testing
- `TestPagedAttentionInt4Helpers`: 4 tests passed, including simulated
SM86, SM89, and SM90 capability cases.
- `lintrunner
onnxruntime/test/python/transformers/test_paged_attention_int4.py`
- `python -m py_compile
onnxruntime/test/python/transformers/test_paged_attention_int4.py`
- `git diff --check`

(cherry picked from commit 8ec7981)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 3eb3fc9b-6147-4706-b7ad-47bb3476377b
Raise the release baseline by 1 KiB, from 1,589,248 to 1,590,272 bytes. CI reports a deterministic section total of 1,590,022 bytes, exceeding the old threshold by 774 bytes. The adjusted limit leaves 250 bytes of headroom.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 3eb3fc9b-6147-4706-b7ad-47bb3476377b
eserscor and others added 3 commits October 26, 2026 13:32
This pull request updates the GitHub Actions workflow configurations for
several Linux CUDA-related CI jobs. The main change is to update the
image used for the CI runners from
`onnxruntime-ubuntu2204-CUDA-A10-Test` to
`onnxruntime-ubuntu2204-CUDA-A10`, likely to standardize or align with
the correct runner image.

**CI runner image updates:**

* Updated the `1ES.ImageOverride` setting from
`onnxruntime-ubuntu2204-CUDA-A10-Test` to
`onnxruntime-ubuntu2204-CUDA-A10` in the following workflow files:
  - `.github/workflows/linux_cuda_ci.yml`
  - `.github/workflows/linux_cuda_no_cudnn.yml`
  - `.github/workflows/linux_cuda_plugin_ci.yml`
  - `.github/workflows/linux_tensorrt_ci.yml`

(cherry picked from commit a97735f)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 3eb3fc9b-6147-4706-b7ad-47bb3476377b
This pull request updates several GitHub Actions workflow files related
to Linux CUDA and TensorRT CI jobs. The main change is the removal of
the `1ES.ImageOverride=onnxruntime-ubuntu2204-CUDA-A10` setting from the
`runs-on` configuration in multiple workflows. This may allow the jobs
to use the default image for the specified pool, potentially improving
maintainability or compatibility.

Workflow configuration updates:

* Removed the `1ES.ImageOverride=onnxruntime-ubuntu2204-CUDA-A10` line
from the `runs-on` section in the following workflow files:
  * `.github/workflows/linux_cuda_ci.yml`
  * `.github/workflows/linux_cuda_no_cudnn.yml`
  * `.github/workflows/linux_cuda_plugin_ci.yml`
  * `.github/workflows/linux_tensorrt_ci.yml`

(cherry picked from commit ef1d811)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 3eb3fc9b-6147-4706-b7ad-47bb3476377b
### Description
<!-- Describe your changes. -->

### Motivation and Context
<!-- - Why is this change required? What problem does it solve?
- If it fixes an open issue, please link to the issue here. -->

Backport notes for rel-1.30.1:
- Preserve existing Linux and WebGPU job sets; do not introduce main-only no-exceptions or static-plugin jobs.
- Keep the main-only Windows ARM64 Python workflow absent.
- Preserve combined Windows WebGPU build/test jobs on the GPU scale set; use the CPU scale set for the build-only minimal Edge job.

(cherry picked from commit 973f680)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 3eb3fc9b-6147-4706-b7ad-47bb3476377b
@adrastogi
adrastogi merged commit 77e55fc into rel-1.30.1 Oct 27, 2026
95 of 99 checks passed
@adrastogi
adrastogi deleted the adrastogi/1.30.1-cherry-picks branch October 27, 2026 06:16
adrastogi added a commit that referenced this pull request Oct 27, 2026
### Description
<!-- Describe your changes. -->
This cherry-picks the following commit for the release:

* #33561 (`7ec270791d92a789db39c868e565d05ce7d1654b`): set up Python
3.12 before running package validation in the combined packaging stage.

The cherry-pick applied cleanly, with source commit provenance
preserved. This branch is based on the current `rel-1.30.1`, including
the servicing payload merged in #33524.

### Motivation and Context
<!-- - Why is this change required? What problem does it solve?
- If it fixes an open issue, please link to the issue here. -->
Bring the packaging-stage fix into ORT 1.30.1 so package validation has
an explicitly selected Python interpreter before the next internal
release build.

Validation:

* The cherry-pick patch ID matches the original mainline commit.
* YAML parsing and assertions passed: Python 3.12 setup precedes the
existing package-validation task.
* `git diff --cached --check` passed before committing.
* The internal release pipelines have not been rerun with this change.

Co-authored-by: eserscor <erscor@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 3eb3fc9b-6147-4706-b7ad-47bb3476377b
adrastogi added a commit that referenced this pull request Oct 27, 2026
### Description
<!-- Describe your changes. -->
This cherry-picks the following commit for the release:

* #33142 (`38dc99fba3f5bd72e201d1d942235bf4f600a1b3`): work around the
Windows certificate regression in build-tools setup by installing and
injecting `truststore`, inspecting proxy settings, and sanitizing
`NO_PROXY` before invoking the GitHub Action wrapper.

The full two-file cherry-pick applied cleanly, with source commit
provenance preserved. This branch is based on current `rel-1.30.1`,
including #33524 and #33641.

### Motivation and Context
<!-- - Why is this change required? What problem does it solve?
- If it fixes an open issue, please link to the issue here. -->
The internal release build failed in six Windows packaging jobs while
downloading the build-tools action through `run_gh_action.py`:

`CERTIFICATE_VERIFY_FAILED: unable to get local issuer certificate`

This upstream fix enables Python to use system-trusted certificates
without disabling certificate verification.

The previous Python-version fix (#33561, backported through #33641) is
present and package validation passed in both release runs.

This PR does not address the separate macOS checkout timeout or the
Maven feed connection timeout in the CUDA13 build. Those failures need
targeted infrastructure retries; no additional cherry-picks are
currently indicated.

Validation:

* The cherry-pick patch ID matches the original mainline commit.
* Python AST parsing and YAML parsing/assertions passed: `truststore`
installation/injection and the PowerShell wrapper invocation are
present.
* `git diff --cached --check` passed before committing.
* No end-to-end execution on the affected release agents was performed.
No release pipelines were restarted.

Co-authored-by: eserscor <erscor@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 3eb3fc9b-6147-4706-b7ad-47bb3476377b
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants