Skip to content

feat(trunk-ir): port validation, parser to arena IR and add SignatureConversion patterns#461

Merged
Kroisse merged 5 commits intomainfrom
feature/arena-signature-conversion
Feb 27, 2026
Merged

feat(trunk-ir): port validation, parser to arena IR and add SignatureConversion patterns#461
Kroisse merged 5 commits intomainfrom
feature/arena-signature-conversion

Conversation

@Kroisse
Copy link
Owner

@Kroisse Kroisse commented Feb 26, 2026

Summary

Implements arena IR validation, parser, and SignatureConversion patterns, closing #440 and #438.

  • Arena IR parser (arena/parser.rs): Full text-format parser producing IrContext using shared winnow combinators. Includes 14 tests covering round-trips, error detection, and validation. The Salsa-based parser is migrated to parser/mod.rs, with shared raw combinators extracted to parser/raw.rs so both parsers reuse them.
  • Arena IR validation (arena/validation.rs): Ports IR validation rules to the arena IR, including use-chain consistency checks (every use points to a valid op, every value's uses list is accurate).
  • Arena IR SignatureConversion patterns (arena/rewrite/signature_conversion.rs): MLIR-style FuncSignatureConversionPattern and WasmFuncSignatureConversionPattern that convert func.func / wasm.func signatures via a type converter, update entry block arg types in-place, and replace the op with a rebuilt function carrying the new signature and original body.
  • Rewrite infrastructure improvements: set_block_arg_type and detach_region added to IrContext; ArenaTypeConverter lifetime threaded through PatternRewriter<'a>; rewrite_function_signature helper extracted to eliminate duplication between the two conversion patterns.
  • Bug fix: update_entry_block_args now returns bool and bails out on arity mismatch, preventing partial IR corruption.

Test plan

  • cargo nextest run -p trunk-ir passes all existing tests
  • 14 new arena parser round-trip / error-detection tests pass
  • 5 new SignatureConversion unit tests pass (i32→i64 conversion, no-change guard, wasm.func, effect attribute preservation, params-only conversion)
  • Arity mismatch test verifies no partial IR mutation occurs

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Arena IR textual parser: transforms text input into arena IR structures with two-stage parsing and comprehensive error handling.
    • Arena IR validation: validates value scope integrity and use-chain consistency across modules and regions.
  • Refactor

    • Function type representation now uses core.func format for improved clarity.
    • Parser module reorganized for better code organization and maintainability.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 26, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between be8abc1 and 30bdb85.

⛔ Files ignored due to path filters (7)
  • crates/trunk-ir/src/parser/snapshots/trunk_ir__parser__tests__roundtrip_adt_struct.snap is excluded by !**/*.snap
  • crates/trunk-ir/src/parser/snapshots/trunk_ir__parser__tests__roundtrip_arith_ops.snap is excluded by !**/*.snap
  • crates/trunk-ir/src/parser/snapshots/trunk_ir__parser__tests__roundtrip_func_call.snap is excluded by !**/*.snap
  • crates/trunk-ir/src/parser/snapshots/trunk_ir__parser__tests__roundtrip_func_effects.snap is excluded by !**/*.snap
  • crates/trunk-ir/src/parser/snapshots/trunk_ir__parser__tests__roundtrip_scf_if.snap is excluded by !**/*.snap
  • crates/trunk-ir/src/parser/snapshots/trunk_ir__parser__tests__roundtrip_scf_loop.snap is excluded by !**/*.snap
  • crates/trunk-ir/src/parser/snapshots/trunk_ir__parser__tests__roundtrip_scf_switch.snap is excluded by !**/*.snap
📒 Files selected for processing (12)
  • crates/trunk-ir/src/arena/dialect/mod.rs
  • crates/trunk-ir/src/arena/mod.rs
  • crates/trunk-ir/src/arena/parser.rs
  • crates/trunk-ir/src/arena/printer.rs
  • crates/trunk-ir/src/arena/rewrite/signature_conversion.rs
  • crates/trunk-ir/src/arena/transforms/dce.rs
  • crates/trunk-ir/src/arena/transforms/global_dce.rs
  • crates/trunk-ir/src/arena/transforms/scf_to_cf.rs
  • crates/trunk-ir/src/arena/validation.rs
  • crates/trunk-ir/src/arena/walk.rs
  • crates/trunk-ir/src/parser/mod.rs
  • crates/trunk-ir/src/parser/raw.rs
🚧 Files skipped from review as they are similar to previous changes (8)
  • crates/trunk-ir/src/arena/walk.rs
  • crates/trunk-ir/src/arena/transforms/dce.rs
  • crates/trunk-ir/src/arena/transforms/global_dce.rs
  • crates/trunk-ir/src/arena/rewrite/signature_conversion.rs
  • crates/trunk-ir/src/parser/raw.rs
  • crates/trunk-ir/src/arena/mod.rs
  • crates/trunk-ir/src/arena/dialect/mod.rs
  • crates/trunk-ir/src/arena/transforms/scf_to_cf.rs

📝 Walkthrough

Walkthrough

This PR introduces a complete textual parser for Arena IR that transforms text input into arena IR structures through a two-stage process (raw parsing to intermediate representation, then IR building to arena references), along with a comprehensive validation module for checking value scope integrity and use-chain consistency. The existing parser module is refactored to separate raw parsing concerns. Function type representation is migrated from func.fn to core.func throughout the codebase.

Changes

Cohort / File(s) Summary
Arena IR Parser
crates/trunk-ir/src/arena/parser.rs, crates/trunk-ir/src/arena/mod.rs
Adds complete textual parser with two-stage process: raw parse generates intermediate structures (RawType, RawAttribute, RawRegion, RawBlock, RawOperation), then ArenaIrBuilder materializes arena references; handles type/attribute conversion, scope management, value resolution, and comprehensive error handling. Exposes parse_module and parse_test_module APIs with extensive test coverage.
Arena IR Validation
crates/trunk-ir/src/arena/validation.rs, crates/trunk-ir/src/arena/mod.rs
Introduces scope validation ensuring inner-region values aren't exposed to outer scopes, and use-chain validation verifying operand-to-use consistency; defines StaleValueError, UseChainError, ValidationResult types; exposes validate_value_integrity, validate_use_chains, validate_all, and debug_assert_valid public APIs with extensive tests.
Parser Module Refactoring
crates/trunk-ir/src/parser/mod.rs, crates/trunk-ir/src/parser/raw.rs
Extracts raw parser logic (~750 LOC) into dedicated raw.rs module with ParseError type, Raw\* AST structures, and Winnow-based combinators for whitespace, identifiers, literals, types, attributes, blocks, regions, and operations; mod.rs now re-exports ParseError and delegates raw parsing details.
Function Type Migration
crates/trunk-ir/src/arena/printer.rs, crates/trunk-ir/src/arena/rewrite/signature_conversion.rs, crates/trunk-ir/src/arena/dialect/mod.rs, crates/trunk-ir/src/arena/transforms/*, crates/trunk-ir/src/arena/walk.rs
Updates function type representation from func.fn to core.func across printer decomposition, signature conversion logic, and test helpers; printer now decomposes core.func signatures with optional effects; all affected tests updated to construct and reference core.func types.

Sequence Diagram(s)

sequenceDiagram
    participant Input as Textual Input
    participant RawParser as Raw Parser
    participant Builder as ArenaIrBuilder
    participant Context as IrContext
    participant Arena as Arena Refs

    Input->>RawParser: parse text
    RawParser->>RawParser: lex and parse (Raw AST)
    RawParser-->>Builder: RawType, RawAttribute, RawRegion, RawBlock, RawOperation
    Builder->>Context: interning types/attributes
    Context-->>Builder: TypeRef, AttributeRef
    Builder->>Builder: construct regions & blocks
    Builder->>Builder: resolve operands & successors
    Builder->>Context: build arena operations
    Context-->>Arena: OpRef, RegionRef, BlockRef, ValueRef
    Builder-->>Arena: fully resolved IR
Loading
sequenceDiagram
    participant Module as ArenaModule
    participant Validator as Validator
    participant Scope as Scope Checker
    participant UseChain as Use-Chain Checker
    participant Result as ValidationResult

    Module->>Validator: validate_all
    Validator->>Scope: collect visible values per region
    Scope->>Scope: recursively verify operands in scope
    Scope-->>Result: stale_errors (if any)
    Validator->>UseChain: enumerate operand uses
    UseChain->>UseChain: verify use-chain entries match operands
    UseChain-->>Result: use_chain_errors (if any)
    Result-->>Validator: combined ValidationResult
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related issues

Possibly related PRs

Suggested labels

enhancement

Poem

🐰 A parser hops through textual fields,
Building arenas with mighty shields,
Validation checks each reference's way,
Core.func types dance—hip hooray!
The IR now speaks and we listen well. 🌿

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly and specifically describes the main changes: porting validation and parser to arena IR, plus adding SignatureConversion patterns.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/arena-signature-conversion

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@crates/trunk-ir/src/arena/parser.rs`:
- Around line 157-167: The code only checks duplicates within a single block
using seen_names but then inserts block-arg names into the shared value_map
without checking for preexisting keys, allowing later blocks to overwrite
earlier bindings; in the block-args insertion site (the loop over all_args and
the shared value_map insert code), add a guard: before inserting into value_map
check if value_map.contains_key(name) and, if it already exists, return a
ParseError (similar shape to the existing duplicate error) or otherwise
disambiguate (e.g. scope the key by block id); update the insertion logic that
currently calls value_map.insert(...) so it either errors on cross-block
collisions or uses a block-scoped key to prevent silent overwrites.
- Around line 129-132: build_region is leaking outer block_map entries into
nested regions because block entries created during build_region_inner are
resolved later against the shared block_map (successor resolution), causing
`^label` in a nested region to match outer blocks; fix by making region parsing
truly scoped: inside build_region (and similarly in the other region entry),
push a fresh scope or clear/shadow block_map after calling save_scopes, then run
build_region_inner so all block registrations go into that isolated scope, and
finally call restore_scopes before any successor resolution runs; ensure
functions named save_scopes, restore_scopes, build_region, and
build_region_inner are adjusted so successor resolution consults only the
current (restored) scope rather than the outer/shared block_map.

In `@crates/trunk-ir/src/arena/rewrite/signature_conversion.rs`:
- Around line 41-43: The current guard only accepts exactly dialect ==
Symbol::new("func") and name == Symbol::new("fn"), which misses synthesized
dialects like "core.func"; update the check around type_data to accept any
dialect that is "func" or ends with ".func" while still requiring the name "fn"
(e.g. replace the strict equality on type_data.dialect with a predicate that
checks type_data.dialect == "func" ||
type_data.dialect.as_str().ends_with(".func")). Apply the same relaxed check in
the other identical block that currently uses Symbol::new("func") /
Symbol::new("fn") so parsed modules like core.func are handled.

In `@crates/trunk-ir/src/arena/validation.rs`:
- Around line 227-233: validate_functions_in_region currently only recognizes
function ops with dialect "func" and name "func" so bodies of "wasm.func" are
skipped; update the check inside the loop that examines ctx.op(op) in
validate_functions_in_region to also treat wasm.func as a function root by
creating a wasm_dialect Symbol::new("wasm") (or equivalent) and including a
condition that accepts either (data.dialect == func_dialect && data.name ==
func_name_sym) or (data.dialect == wasm_dialect && data.name == func_name_sym)
so validate_value_integrity/validate_all will inspect wasm.func bodies as well.
- Around line 330-340: For each value in checked_values, detect duplicate
entries returned by ctx.uses(val) by adding a per-value HashSet (or similar) of
seen (u.user, u.operand_index) pairs: when iterating u in ctx.uses(val) first
check if the pair is already in the seen set and if so push a UseChainError
describing the duplicate entry for that val; otherwise insert the pair into seen
and then continue the existing check against actual_uses (the current membership
test that pushes UseChainError when (val, u.user, u.operand_index) is missing).
This ensures duplicate use-chain entries are reported in addition to missing
ones.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0ad3bb6 and 9dc9827.

⛔ Files ignored due to path filters (7)
  • crates/trunk-ir/src/parser/snapshots/trunk_ir__parser__tests__roundtrip_adt_struct.snap is excluded by !**/*.snap
  • crates/trunk-ir/src/parser/snapshots/trunk_ir__parser__tests__roundtrip_arith_ops.snap is excluded by !**/*.snap
  • crates/trunk-ir/src/parser/snapshots/trunk_ir__parser__tests__roundtrip_func_call.snap is excluded by !**/*.snap
  • crates/trunk-ir/src/parser/snapshots/trunk_ir__parser__tests__roundtrip_func_effects.snap is excluded by !**/*.snap
  • crates/trunk-ir/src/parser/snapshots/trunk_ir__parser__tests__roundtrip_scf_if.snap is excluded by !**/*.snap
  • crates/trunk-ir/src/parser/snapshots/trunk_ir__parser__tests__roundtrip_scf_loop.snap is excluded by !**/*.snap
  • crates/trunk-ir/src/parser/snapshots/trunk_ir__parser__tests__roundtrip_scf_switch.snap is excluded by !**/*.snap
📒 Files selected for processing (12)
  • crates/trunk-ir/src/arena/context.rs
  • crates/trunk-ir/src/arena/mod.rs
  • crates/trunk-ir/src/arena/parser.rs
  • crates/trunk-ir/src/arena/printer.rs
  • crates/trunk-ir/src/arena/rewrite/applicator.rs
  • crates/trunk-ir/src/arena/rewrite/mod.rs
  • crates/trunk-ir/src/arena/rewrite/pattern.rs
  • crates/trunk-ir/src/arena/rewrite/rewriter.rs
  • crates/trunk-ir/src/arena/rewrite/signature_conversion.rs
  • crates/trunk-ir/src/arena/validation.rs
  • crates/trunk-ir/src/parser/mod.rs
  • crates/trunk-ir/src/parser/raw.rs

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
crates/trunk-ir/src/arena/validation.rs (1)

333-343: ⚠️ Potential issue | 🟠 Major

Duplicate use-chain entries are still not reported.

Direction-2 only checks set membership in actual_uses, so repeated identical entries in ctx.uses(val) are silently accepted. That breaks the “exact match” guarantee for use-chain consistency.

Suggested patch
     for &val in &checked_values {
+        let mut seen_uses: HashSet<(OpRef, u32)> = HashSet::new();
         for u in ctx.uses(val) {
+            if !seen_uses.insert((u.user, u.operand_index)) {
+                errors.push(UseChainError {
+                    message: format!(
+                        "duplicate use-chain entry for {:?}: user {:?} operand #{}",
+                        val, u.user, u.operand_index,
+                    ),
+                });
+                continue;
+            }
             if !actual_uses.contains(&(val, u.user, u.operand_index)) {
                 errors.push(UseChainError {
                     message: format!(
                         "use-chain entry for {:?} claims use by {:?} operand #{}, but no such operand exists",
                         val, u.user, u.operand_index,
                     ),
                 });
             }
         }
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/trunk-ir/src/arena/validation.rs` around lines 333 - 343, The loop
over ctx.uses(val) in validation.rs currently only checks membership in
actual_uses and thus ignores duplicate identical entries; modify the logic to
detect and report duplicate use-chain entries by keeping a seen set (e.g., a
HashSet of tuples like (val, u.user, u.operand_index)) and for each u first
check if that tuple was already seen—if so, push a UseChainError describing a
duplicate use-chain entry for that (val, user, operand_index); otherwise insert
into seen and continue to the existing membership check against actual_uses so
both missing and duplicate entries are reported.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@crates/trunk-ir/src/arena/validation.rs`:
- Around line 333-343: The loop over ctx.uses(val) in validation.rs currently
only checks membership in actual_uses and thus ignores duplicate identical
entries; modify the logic to detect and report duplicate use-chain entries by
keeping a seen set (e.g., a HashSet of tuples like (val, u.user,
u.operand_index)) and for each u first check if that tuple was already seen—if
so, push a UseChainError describing a duplicate use-chain entry for that (val,
user, operand_index); otherwise insert into seen and continue to the existing
membership check against actual_uses so both missing and duplicate entries are
reported.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9dc9827 and 4b7a732.

📒 Files selected for processing (2)
  • crates/trunk-ir/src/arena/parser.rs
  • crates/trunk-ir/src/arena/validation.rs

@Kroisse Kroisse self-assigned this Feb 27, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@crates/trunk-ir/src/arena/validation.rs`:
- Around line 197-200: The doc comment that currently states the validation is
for `func.func` only is inaccurate; update the comment to state that
value-integrity validation applies to both `func.func` and `wasm.func`
operations (the same change should be made for the similar comment later).
Locate the docstring above the validation implementation (the comment block
describing validation of value integrity) and revise the wording to mention both
`func.func` and `wasm.func`, keeping the rest of the description (checking that
every operand references a value defined within the function's region tree)
unchanged.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4b7a732 and 8e8c2b7.

📒 Files selected for processing (8)
  • crates/trunk-ir/src/arena/dialect/mod.rs
  • crates/trunk-ir/src/arena/printer.rs
  • crates/trunk-ir/src/arena/rewrite/signature_conversion.rs
  • crates/trunk-ir/src/arena/transforms/dce.rs
  • crates/trunk-ir/src/arena/transforms/global_dce.rs
  • crates/trunk-ir/src/arena/transforms/scf_to_cf.rs
  • crates/trunk-ir/src/arena/validation.rs
  • crates/trunk-ir/src/arena/walk.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/trunk-ir/src/arena/rewrite/signature_conversion.rs

Kroisse and others added 5 commits February 27, 2026 11:28
Add arena IR text format parser (arena/parser.rs) with ArenaIrBuilder
that converts Raw* structures from the shared winnow combinators into
arena-based IR. Includes 14 tests covering round-trips, error detection,
and validation.

Migrate the Salsa-based parser from parser.rs into parser/mod.rs and
extract shared winnow combinators into parser/raw.rs so both the Salsa
and arena parsers can reuse them. Reorder successor_list parsing in
raw.rs to appear before return_type/effects/attrs/result_types, matching
the arena printer output order.

Add arena/validation.rs with walk_region type annotation fixes and
corrected OperationDataBuilder API usage. Extend arena/printer.rs to
decompose core.func types and emit effects inline (` -> T effects E`)
instead of printing the opaque type.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Reject duplicate SSA names across block arguments within the same
  region in the arena IR parser, returning a clear error message
- Clear block_map at the start of build_region to isolate block label
  scope per region, preventing nested regions from resolving outer
  block labels as successors
- Extend validate_functions_in_region to recognise wasm.func as a
  function root alongside func.func, so its body is included in value
  integrity validation
- Add tests covering all three fixes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Align the arena IR function type representation with the canonical
dialect naming convention. All occurrences of (dialect="func", name="fn")
are replaced with (dialect="core", name="func"), covering the production
guard and builder in signature_conversion.rs as well as test helpers
across printer, validation, walk, dce, global_dce, and scf_to_cf.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The function already validated both `func.func` and `wasm.func`
operations, but the public doc comment and an inline comment only
mentioned `func.func`. Updated both to accurately reflect the
actual behavior.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…to outer scopes

The old `collect_defined_in_region` recursively collected all values from
all nested sub-regions into a flat set, then validated operands against that
flat set. This incorrectly allowed outer scopes to reference values defined
only inside inner regions (e.g. a `func.return` consuming a value produced
inside an `scf.if` branch).

Replace the flat-collection approach with visibility-based scoping:
- Remove `collect_defined_in_region` and `collect_defined_in_block`.
- Add `collect_region_top_level`: shallow collection of block args + op
  results at one region level only, without descending into sub-regions.
- Rewrite `check_operands_in_region` to accept an `outer_visible` set,
  extend it with the current region's top-level values, propagate the
  extended set into nested sub-regions, and never leak sub-region values
  back to parent scopes.
- Each function body check starts with an empty outer visible set.
- Add regression test `inner_value_not_visible_in_outer_scope` that
  constructs a `func.return` using a value only defined inside an `scf.if`
  branch and asserts the validator rejects it.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@Kroisse Kroisse force-pushed the feature/arena-signature-conversion branch from be8abc1 to 30bdb85 Compare February 27, 2026 02:28
@codecov
Copy link

codecov bot commented Feb 27, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 78.54%. Comparing base (0ad3bb6) to head (30bdb85).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #461   +/-   ##
=======================================
  Coverage   78.54%   78.54%           
=======================================
  Files          10       10           
  Lines        4935     4935           
=======================================
  Hits         3876     3876           
  Misses       1059     1059           
Components Coverage Δ
TrunkIR ∅ <ø> (∅)
Frontend ∅ <ø> (∅)
Middle End ∅ <ø> (∅)
Driver 78.54% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Kroisse Kroisse merged commit 7dd9e8a into main Feb 27, 2026
12 checks passed
@Kroisse Kroisse deleted the feature/arena-signature-conversion branch February 27, 2026 03:35
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.

1 participant