Skip to content

JTD bytecode codegen via ClassFile API + RFC 8927 conformance#139

Open
simbo1905 wants to merge 4 commits intomainfrom
jtd-gen
Open

JTD bytecode codegen via ClassFile API + RFC 8927 conformance#139
simbo1905 wants to merge 4 commits intomainfrom
jtd-gen

Conversation

@simbo1905
Copy link
Owner

Adds json-java21-jtd-codegen module (JDK 24+, --release 24) that compiles JTD schemas into bytecode validators targeting Java 21. Generated classfiles use the JDK 24 ClassFile API (JEP 484) and are loaded at runtime via MethodHandles.Lookup.defineClass().

Runtime API (json-java21-jtd, Java 21):

  • JtdValidator functional interface: JsonValue -> JtdValidationResult
  • JtdValidator.compile(schema) -- interpreter path, always available
  • JtdValidator.compileGenerated(schema) -- codegen path via reflection
  • JtdValidationResult record with RFC 8927 (instancePath, schemaPath)
  • InterpreterValidator wraps the existing stack machine

Codegen module (json-java21-jtd-codegen, JDK 24+):

  • Modular emitter architecture: EmitNode dispatches to per-form emitters (EmitType, EmitEnum, EmitElements, EmitProperties, EmitValues, EmitDiscriminator)
  • Lazy instance path construction: deferred concat only on error
  • Average 9.4x faster than interpreter on valid documents

RFC 8927 conformance:

  • Schema path corrections per official validation suite: Elements/Values/Properties/Discriminator type guards, Properties conditional guard (/properties vs /optionalProperties), Ref paths use /definitions//...
  • 316/316 official json-typedef-spec validation.json cases pass (interpreter); 314/316 codegen (2 recursive schemas skipped)

Verification:

  • json-java21-jtd: 452 tests (136 unit + 316 spec conformance)
  • json-java21-jtd-codegen: 398 tests (82 cross-validation + 316 spec)
  • Total: 850 tests, all passing

(Optional) When submitting a PR, please consider using a "deep research" tool to sanity check your proposal. Then before submission, run your draft through a strong model with a prompt such as:

"Please review README.md along with this draft PR and check that it does not have any gaps — why it might be insufficient, incomplete, lacking a concrete example, duplicating prior issues or PRs, or not be aligned with the project goals or non‑goals."

If you used an AI assistant while preparing this PR, ensure it followed the contributor/agent workflow rules in AGENTS.md.

(Optional) Please then attach both the prompt and the model's review to the bottom of this template under "Augmented Intelligence Review".


What changed

  • A summary of the changes in this PR

Why this change is needed

  • Motivation / context

How were these changes tested

  • Test plan / manual testing / automated tests etc.

Checklist

  • Code builds / passes tests
  • New tests added if needed
  • Update to use CODING_STYLE_LLM.md convensions
  • Documentation updated if needed
  • AGENTS.md updated if appropriate

(Optional) Augmented Intelligence Review:
Both prompt and model out, asking a strong model to double-check your submission, from the perspective of a maintainer of this repo

Adds json-java21-jtd-codegen module (JDK 24+, --release 24) that
compiles JTD schemas into bytecode validators targeting Java 21.
Generated classfiles use the JDK 24 ClassFile API (JEP 484) and
are loaded at runtime via MethodHandles.Lookup.defineClass().

Runtime API (json-java21-jtd, Java 21):
- JtdValidator functional interface: JsonValue -> JtdValidationResult
- JtdValidator.compile(schema) -- interpreter path, always available
- JtdValidator.compileGenerated(schema) -- codegen path via reflection
- JtdValidationResult record with RFC 8927 (instancePath, schemaPath)
- InterpreterValidator wraps the existing stack machine

Codegen module (json-java21-jtd-codegen, JDK 24+):
- Modular emitter architecture: EmitNode dispatches to per-form
  emitters (EmitType, EmitEnum, EmitElements, EmitProperties,
  EmitValues, EmitDiscriminator)
- Lazy instance path construction: deferred concat only on error
- Average 9.4x faster than interpreter on valid documents

RFC 8927 conformance:
- Schema path corrections per official validation suite:
  Elements/Values/Properties/Discriminator type guards,
  Properties conditional guard (/properties vs /optionalProperties),
  Ref paths use /definitions/<name>/...
- 316/316 official json-typedef-spec validation.json cases pass
  (interpreter); 314/316 codegen (2 recursive schemas skipped)

Verification:
- json-java21-jtd: 452 tests (136 unit + 316 spec conformance)
- json-java21-jtd-codegen: 398 tests (82 cross-validation + 316 spec)
- Total: 850 tests, all passing
@gemini-code-assist
Copy link

Summary of Changes

Hello @simbo1905, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a significant performance enhancement to the JTD validation library by adding an optional bytecode generation module. This new module compiles JTD schemas directly into Java bytecode, offering a substantial speedup over the traditional interpreter. Alongside this, the core validation logic has been rigorously aligned with RFC 8927, ensuring accurate and standardized error reporting. The changes provide developers with a choice between a robust, universally compatible interpreter and a high-performance, bytecode-generated validator, all accessible through a unified functional API.

Highlights

  • New Bytecode Generation Module: Introduced json-java21-jtd-codegen module, enabling compilation of JTD schemas into highly optimized bytecode validators using the JDK 24+ ClassFile API. These generated validators target Java 21 runtimes.
  • Enhanced Validation Performance: The bytecode-generated validators demonstrate an average of 9.4x faster performance compared to the interpreter path on valid documents, providing a significant speedup for hot-path validation scenarios.
  • RFC 8927 Conformance and Error Reporting: The validation logic, for both the new codegen and the existing interpreter, has been refined to ensure full RFC 8927 conformance, particularly in the precise (instancePath, schemaPath) error reporting. All 316 official json-typedef-spec validation cases now pass for the interpreter, and 314/316 for codegen (with two recursive schemas currently skipped).
  • Functional JTD Validator API: A new JtdValidator functional interface has been added to the json-java21-jtd module, offering compile() for the interpreter path and compileGenerated() for the optional bytecode generation path. This provides a cleaner, more flexible API for integrating JTD validation into applications.
  • Comprehensive Testing and Documentation: The pull request includes extensive new test suites (850 tests total across both modules) and detailed specification documents (JTD_CODEGEN_SPEC.md, JTD_STACK_MACHINE_SPEC.md) outlining the design and behavior of both validation approaches.
Changelog
  • json-java21-jtd-codegen/pom.xml
    • Added new Maven module for JTD bytecode codegen.
  • json-java21-jtd-codegen/src/main/java/json/java21/jtd/codegen/Descriptors.java
    • Added shared class and method type descriptors for bytecode emission.
  • json-java21-jtd-codegen/src/main/java/json/java21/jtd/codegen/EmitDiscriminator.java
    • Added logic for emitting bytecode for JTD Discriminator schemas.
  • json-java21-jtd-codegen/src/main/java/json/java21/jtd/codegen/EmitElements.java
    • Added logic for emitting bytecode for JTD Elements schemas (array validation).
  • json-java21-jtd-codegen/src/main/java/json/java21/jtd/codegen/EmitEnum.java
    • Added logic for emitting bytecode for JTD Enum schemas.
  • json-java21-jtd-codegen/src/main/java/json/java21/jtd/codegen/EmitError.java
    • Added utility for emitting bytecode to add validation errors.
  • json-java21-jtd-codegen/src/main/java/json/java21/jtd/codegen/EmitNode.java
    • Added central dispatcher for AST node emission to appropriate emitters.
  • json-java21-jtd-codegen/src/main/java/json/java21/jtd/codegen/EmitProperties.java
    • Added logic for emitting bytecode for JTD Properties schemas (object validation).
  • json-java21-jtd-codegen/src/main/java/json/java21/jtd/codegen/EmitScaffold.java
    • Added logic for emitting class skeleton (constructor, toString, validate method shell).
  • json-java21-jtd-codegen/src/main/java/json/java21/jtd/codegen/EmitType.java
    • Added logic for emitting bytecode for JTD Type schemas.
  • json-java21-jtd-codegen/src/main/java/json/java21/jtd/codegen/EmitValues.java
    • Added logic for emitting bytecode for JTD Values schemas.
  • json-java21-jtd-codegen/src/main/java/json/java21/jtd/codegen/JtdCodegen.java
    • Added main class for compiling JTD schemas into bytecode-generated JtdValidator instances.
  • json-java21-jtd-codegen/src/test/java/json/java21/jtd/codegen/BenchmarkTest.java
    • Added benchmark tests comparing codegen vs interpreter performance.
  • json-java21-jtd-codegen/src/test/java/json/java21/jtd/codegen/CodegenSpecConformanceTest.java
    • Added conformance tests for codegen against official JTD spec.
  • json-java21-jtd-codegen/src/test/java/json/java21/jtd/codegen/CodegenTestBase.java
    • Added base class for codegen tests.
  • json-java21-jtd-codegen/src/test/java/json/java21/jtd/codegen/CrossValidationTest.java
    • Added tests to cross-validate interpreter and codegen paths.
  • json-java21-jtd/JTD_CODEGEN_SPEC.md
    • Added specification for JTD code generation.
  • json-java21-jtd/JTD_STACK_MACHINE_SPEC.md
    • Added specification for JTD stack-machine interpreter.
  • json-java21-jtd/PROBE_TESTS_SUMMARY.md
    • Added summary of probe tests for JTD implementation.
  • json-java21-jtd/README.md
    • Updated README to include new functional API, generated validators, and links to new spec documents.
  • json-java21-jtd/src/main/java/json/java21/jtd/Frame.java
    • Modified Frame record to include schemaPath and updated constructors for RFC 8927 compliance.
  • json-java21-jtd/src/main/java/json/java21/jtd/InterpreterValidator.java
    • Added new class for the stack-machine interpreter, implementing JtdValidator.
  • json-java21-jtd/src/main/java/json/java21/jtd/Jtd.java
    • Added compileToSchema method to return the compiled AST.
    • Updated pushChildFrames to pass schemaPath for accurate error reporting.
  • json-java21-jtd/src/main/java/json/java21/jtd/JtdSchema.java
    • Changed JtdSchema to public sealed interface for broader access.
    • Made RefSchema.target() public.
    • Changed TypeSchema.RFC3339 pattern to static final.
  • json-java21-jtd/src/main/java/json/java21/jtd/JtdValidationError.java
    • Added new record for RFC 8927 validation error, capturing instancePath and schemaPath.
  • json-java21-jtd/src/main/java/json/java21/jtd/JtdValidationResult.java
    • Added new record for JTD validation results, encapsulating validity and a list of errors.
  • json-java21-jtd/src/main/java/json/java21/jtd/JtdValidator.java
    • Added new functional interface for JTD validators with compile (interpreter) and compileGenerated (codegen) static factories.
  • json-java21-jtd/src/test/java/json/java21/jtd/DiscriminatorEdgeCaseProbe.java
    • Added probe tests for discriminator edge cases.
  • json-java21-jtd/src/test/java/json/java21/jtd/ElementsEdgeCaseProbe.java
    • Added probe tests for elements edge cases.
  • json-java21-jtd/src/test/java/json/java21/jtd/ErrorFormatComplianceProbe.java
    • Added probe tests for error format compliance.
  • json-java21-jtd/src/test/java/json/java21/jtd/JtdSpecConformanceTest.java
    • Added conformance tests for interpreter against official JTD spec.
  • json-java21-jtd/src/test/java/json/java21/jtd/JtdValidatorTest.java
    • Added tests for JtdValidator and InterpreterValidator.
  • json-java21-jtd/src/test/java/json/java21/jtd/NullableEdgeCaseProbe.java
    • Added probe tests for nullable modifier edge cases.
  • json-java21-jtd/src/test/java/json/java21/jtd/PropertiesEdgeCaseProbe.java
    • Added probe tests for properties edge cases.
  • json-java21-jtd/src/test/java/json/java21/jtd/RefEdgeCaseProbe.java
    • Added probe tests for ref schema edge cases.
  • json-java21-jtd/src/test/java/json/java21/jtd/TypeValidationEdgeCaseProbe.java
    • Added probe tests for type validation edge cases.
  • pom.xml
    • Added json-java21-jtd-codegen module to the parent POM.
Activity
  • The pull request introduces a new json-java21-jtd-codegen module, significantly expanding the project's capabilities by adding bytecode generation for JTD validators.
  • Extensive new Java classes have been added to the codegen module to handle the emission of bytecode for various JTD schema forms, including Descriptors, EmitDiscriminator, EmitElements, EmitEnum, EmitError, EmitNode, EmitProperties, EmitScaffold, EmitType, EmitValues, and JtdCodegen.
  • The core json-java21-jtd module has been refactored to introduce a new JtdValidator functional interface, along with JtdValidationResult and JtdValidationError records, standardizing the validation API and error reporting according to RFC 8927.
  • The existing Jtd class and Frame record in json-java21-jtd have been updated to support the new RFC 8927 error format, including schema path tracking.
  • A new InterpreterValidator class has been added to json-java21-jtd to wrap the existing stack-machine interpreter logic under the new JtdValidator interface.
  • Comprehensive test suites have been added or updated across both modules, including BenchmarkTest, CodegenSpecConformanceTest, CrossValidationTest for the codegen module, and numerous *EdgeCaseProbe tests and JtdSpecConformanceTest, JtdValidatorTest for the core module, ensuring robust validation and RFC compliance.
  • New documentation files (JTD_CODEGEN_SPEC.md, JTD_STACK_MACHINE_SPEC.md, PROBE_TESTS_SUMMARY.md) have been added, and the README.md has been updated to reflect the new features and API.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c1805a981c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +252 to +256
cob.aload(instSlot);
cob.checkcast(CD_JsonNumber);
cob.invokeinterface(CD_JsonNumber, "toLong", MTD_long);
int lSlot = cob.allocateLocal(TypeKind.LONG);
cob.lstore(lSlot);

Choose a reason for hiding this comment

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

P1 Badge Guard toLong overflow before validating int ranges

The generated int-type validator calls JsonNumber.toLong() immediately after checking floor() (see EmitType.emitIntCore), but it never bounds-checks the double value the way the interpreter does. When the instance is a large integer (e.g., 1e20), toLong() can throw JsonAssertionException, which aborts validation instead of returning a schema error. The interpreter explicitly rejects values outside Long range first, so codegen should mirror that guard to avoid runtime exceptions and keep behavior consistent.

Useful? React with 👍 / 👎.

Comment on lines +298 to +302
cob.ldc(":60");
cob.ldc(":59");
cob.invokevirtual(CD_String, "replace", MTD_String_CharSeq_CharSeq);
cob.getstatic(CD_DateTimeFormatter, "ISO_OFFSET_DATE_TIME", CD_DateTimeFormatter);
cob.invokestatic(CD_OffsetDateTime, "parse", MTD_OffsetDateTime_CharSeq_DTF);

Choose a reason for hiding this comment

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

P1 Badge Catch timestamp parse failures to avoid hard exceptions

The timestamp path compiles a regex and then calls OffsetDateTime.parse(...) without any exception handling. The regex accepts values like month/day 00, so parse can throw DateTimeParseException, which will bubble out of validation and crash instead of producing a schema error. The interpreter explicitly catches exceptions and treats them as a validation failure, so generated validators should wrap this parse and fall back to onError to preserve RFC 8927 behavior.

Useful? React with 👍 / 👎.

Comment on lines +60 to +63
try {
final var clazz = Class.forName(CODEGEN_CLASS);
final var method = clazz.getMethod(CODEGEN_METHOD, JsonValue.class);
return (JtdValidator) method.invoke(null, schema);

Choose a reason for hiding this comment

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

P2 Badge Handle UnsupportedClassVersionError in compileGenerated

On Java 21 runtimes, compileGenerated will call Class.forName on the codegen module, which is built with --release 24. This throws UnsupportedClassVersionError (a LinkageError), but the method only catches ClassNotFoundException and ReflectiveOperationException, so callers see a hard error instead of the documented UnsupportedOperationException fallback. Catching LinkageError here would keep the method behavior consistent when the newer codegen module is present but incompatible with the runtime.

Useful? React with 👍 / 👎.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This is an impressive and substantial pull request that introduces bytecode generation for JTD validation, a new functional JtdValidator API, and brings the implementation into conformance with RFC 8927 error reporting. The modular emitter architecture for codegen is well-designed, and the addition of extensive test suites, including spec conformance and cross-validation tests, is excellent.

My review focuses on a few areas for improvement: project consistency in the new module's pom.xml, a performance optimization for regex compilation in the generated code, and enhancing code clarity and maintainability by addressing a known limitation and improving code reuse.

Comment on lines +290 to +291
cob.ldc("^(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:(\\d{2}|60)(\\.\\d+)?(Z|[+-]\\d{2}:\\d{2}))$");
cob.invokestatic(CD_Pattern, "compile", MTD_Pattern_String);

Choose a reason for hiding this comment

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

high

Compiling the regex pattern on every validation call is inefficient. The compiled Pattern should be cached. A good approach is to create a private static final Pattern field in the generated class and initialize it in a static block. This avoids repeated compilation overhead.

Additionally, the regex string is duplicated from JtdSchema.TypeSchema.RFC3339. To avoid this, you could expose the regex string as a public static final String in JtdSchema.TypeSchema and reference it here, or make the Pattern field public and load it directly using getstatic.

<version>0.1.9</version>
</parent>

<artifactId>java.util.json.jtd.codegen</artifactId>

Choose a reason for hiding this comment

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

medium

The artifactId java.util.json.jtd.codegen is inconsistent with the module's directory name (json-java21-jtd-codegen) and the naming convention of other modules in this project (e.g., json-java21-jtd). For consistency and easier project navigation, consider renaming the artifactId to json-java21-jtd-codegen.

Suggested change
<artifactId>java.util.json.jtd.codegen</artifactId>
<artifactId>json-java21-jtd-codegen</artifactId>

Comment on lines +31 to +32
case JtdSchema.RefSchema r ->
emit(cob, r.target(), instSlot, errSlot, instPath, "/definitions/" + r.ref());

Choose a reason for hiding this comment

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

medium

This direct recursive call to emit for RefSchema will cause a StackOverflowError in the code generator for recursive JTD schemas. While the PR description and tests acknowledge this limitation, it would be beneficial to add a comment here to make this explicit for future maintainers. A more robust solution would involve generating separate methods for definitions and using invokevirtual to handle recursion in the generated code, as described in JTD_CODEGEN_SPEC.md.

Comment on lines +102 to 104
static final java.util.regex.Pattern RFC3339 = java.util.regex.Pattern.compile(
"^(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:(\\d{2}|60)(\\.\\d+)?(Z|[+-]\\d{2}:\\d{2}))$"
);

Choose a reason for hiding this comment

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

medium

To allow the codegen module to reuse this pattern and avoid duplicating the regex string, consider making RFC3339 public. This would improve maintainability by having a single source of truth for the pattern and would allow the codegen module to load the pre-compiled pattern directly.

Suggested change
static final java.util.regex.Pattern RFC3339 = java.util.regex.Pattern.compile(
"^(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:(\\d{2}|60)(\\.\\d+)?(Z|[+-]\\d{2}:\\d{2}))$"
);
public static final java.util.regex.Pattern RFC3339 = java.util.regex.Pattern.compile(
"^(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:(\\d{2}|60)(\\.\\d+)?(Z|[+-]\\d{2}:\\d{2}))$"
);

#140)

Previously, two copies of the 78KB jtd-spec-validation.json file were
committed to the repository (156KB total), bloating the PR and git history.

Changes:
- Created JtdTestDataExtractor utility class to extract test data from
  existing jtd-test-suite.zip at test runtime
- Updated JtdSpecConformanceTest and CodegenSpecConformanceTest to use
  extraction instead of classpath resources
- Updated JtdSpecIT and CompilerSpecIT to use shared extractor
- Deleted committed JSON files from both modules
- Codegen module references parent module's ZIP file

Testing:
- Run: ./mvnw -pl json-java21-jtd test
- All 452 tests pass (136 unit + 316 spec conformance)
- Test data is automatically extracted from ZIP on first run
- Reduces PR size by ~156KB (9,390 lines)
cursor bot pushed a commit that referenced this pull request Feb 8, 2026
- Updated CI workflow to use Java 24 (required for JTD codegen module)
- Changed distribution from temurin to oracle for Java 24 availability
- Updated expected test count from 611 to 850 (includes new codegen tests)
- Updated expected skipped count to 2 (recursive schemas in codegen)

The json-java21-jtd-codegen module requires Java 24+ for the ClassFile API (JEP 484).
Previous workflow used Java 21 which caused compilation failure: 'release version 24 not supported'.

Co-authored-by: Simon Massey <simbo1905@users.noreply.github.com>
cursoragent and others added 2 commits February 8, 2026 21:11
- Updated CI workflow to use Java 24 (required for JTD codegen module)
- Changed distribution from temurin to oracle for Java 24 availability
- Updated expected test count from 611 to 850 (includes new codegen tests)
- Updated expected skipped count to 2 (recursive schemas in codegen)

The json-java21-jtd-codegen module requires Java 24+ for the ClassFile API (JEP 484).
Previous workflow used Java 21 which caused compilation failure: 'release version 24 not supported'.

Co-authored-by: Simon Massey <simbo1905@users.noreply.github.com>
The actual test count is 1354, not 850. The previous value was based on
incomplete information. Build logs show:
- tests: 1354
- failures: 0
- errors: 0
- skipped: 0

All tests are passing successfully.

Co-authored-by: Simon Massey <simbo1905@users.noreply.github.com>
cursor bot pushed a commit that referenced this pull request Feb 8, 2026
The actual test count is 1354, not 850. The previous value was based on
incomplete information. Build logs show:
- tests: 1354
- failures: 0
- errors: 0
- skipped: 0

All tests are passing successfully.

Co-authored-by: Simon Massey <simbo1905@users.noreply.github.com>
@simbo1905 simbo1905 mentioned this pull request Feb 8, 2026
5 tasks
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.

2 participants

Comments