Skip to content

feat(test-cases): output slots, stage decomposition, and CLI package split#748

Merged
lewisjared merged 12 commits into
mainfrom
feat/test-cases-output-slots
Jun 24, 2026
Merged

feat(test-cases): output slots, stage decomposition, and CLI package split#748
lewisjared merged 12 commits into
mainfrom
feat/test-cases-output-slots

Conversation

@lewisjared

@lewisjared lewisjared commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

Description

This branch makes two changes to the ref test-cases developer workflow.

Output slots + stage decomposition

Every run / replay / mint / build now materialises into a gitignored output slot (<case>/output/<label>/) holding the curated native set, the rebuilt committed bundle, and a .source.json stamp, so a developer can see and diff exactly what a run produced. The verbs are refactored onto a shared stage toolkit (execute / materialise / rebuild / build / upload / compare), adding:

  • a build verb that rebuilds the committed bundle from a slot without re-executing
  • mint --from-replay to re-author the manifest from stored native instead of re-running the diagnostic
  • --label on run/replay/mint/build to keep named slots side by side
  • changed-digest upload-skip and a native-staleness warning

run / build write the slot on every invocation but only promote the rebuilt bundle to the tracked regression/ baseline on --force-regen or when seeding; the native block stays mint-owned, and mint uploads before it promotes.

CLI subpackage split

test_cases.py had grown past 1700 lines, so it is decomposed into a climate_ref.cli.test_cases package grouped by concern — discovery (fetch/list), run, baselines (replay/mint/build), store (sync/check-store) and ci_gate, over _catalog / _common / _stages helpers and an _app module holding the shared Typer app. Command implementations are carried over unchanged; the package re-exports the helpers the unit tests import directly and registers the command modules in a fixed order so ref test-cases --help keeps its verb ordering. No behaviour change.

Checklist

Please confirm that this pull request has done the following:

  • Tests added
  • Documentation added (where applicable)
  • Changelog item added to changelog/

Summary by CodeRabbit

Release Notes

  • New Features

    • Output slots: ref test-cases runs now write results to dedicated, gitignored output/<label>/ directories (including curated native outputs, regenerated bundles, and a source stamp) to enable side-by-side inspection.
    • Added/expanded ref test-cases verbs: run, replay, mint, build, plus --label for concurrent comparisons.
  • Documentation

    • Updated regression-baseline and output-slot lifecycle guidance, including promotion/warning behaviour.
  • Bug Fixes

    • Stricter committed-manifest validation (supported schema and native entry size rules) and improved float-handling safeguards.
  • Chores

    • Updated .gitignore to exclude materialised output-slot test data.

Materialise every run/replay/mint/build into a gitignored output slot
(`<case>/output/<label>/`) holding the curated native set,
the rebuilt committed bundle, and a `.source.json` stamp,
so a developer can see and diff what a run produced.

Refactor run/replay/mint onto a shared stage toolkit
(execute / materialise / rebuild / build / upload / compare) and add:

- a `build` verb that rebuilds the committed bundle from a slot without re-executing
- `mint --from-replay` to re-author the manifest from stored native instead of re-running the diagnostic
- `--label` on run/replay/mint/build to keep named slots side by side
- changed-digest upload skip and a native-staleness warning

run/build write the slot on every invocation
but only promote the rebuilt bundle to the tracked `regression/` baseline
on `--force-regen` or when seeding;
the native block stays mint-owned, and mint uploads before it promotes.
test_cases.py had grown past 1700 lines. Split it into a
climate_ref.cli.test_cases package grouped by concern: discovery
(fetch/list), run, baselines (replay/mint/build), store
(sync/check-store) and ci_gate, over _catalog/_common/_stages helpers
and an _app module holding the shared Typer app.

Command implementations are carried over unchanged. The package
re-exports the helpers the unit tests import directly and registers the
command modules in a fixed order so `ref test-cases --help` keeps its
verb ordering. _test_case_stages.py moves in as _stages.py; the test
mock targets are updated to the new module paths.
@coderabbitai

coderabbitai Bot commented Jun 21, 2026

Copy link
Copy Markdown

Review Change Stack

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
📝 Walkthrough

Walkthrough

The monolithic test_cases.py CLI module (1621 lines) is deleted and replaced with a structured package split by concern: _app, _catalog, _common, _stages, discovery, run, baselines, store, and ci_gate. A named output-slot concept (output/<label>/) is introduced in TestCasePaths, gitignored, and documented, with a new build verb added alongside the existing commands. Manifest parsing is hardened with schema and entry-size validation, and float-handling invariants are verified during committed-bundle serialisation. Logging retention is updated to tolerate concurrent file deletions.

Changes

CLI test-cases package refactor with output-slot pipeline

Layer / File(s) Summary
Output slot path helpers, gitignore, and docs
.gitignore, packages/climate-ref-core/src/climate_ref_core/testing.py, docs/background/regression-baselines.md, changelog/748.feature.md, changelog/748.trivial.md
Adds TestCasePaths.output property and output_slot(label) method using safe_path(single_segment=True), gitignores **/test-data/**/output/, and expands the regression-baselines doc with slot layout, promotion gating rules (--force-regen), and mint --from-replay semantics. Changelogs document the new build verb and --label option.
Package restructure: app instance and __init__ wiring
packages/climate-ref/src/climate_ref/cli/test_cases/_app.py, packages/climate-ref/src/climate_ref/cli/test_cases/__init__.py
Creates _app.py with the Typer app instance. __init__.py dynamically imports command submodules (discovery, run, baselines, store, ci_gate) to register CLI verbs via side effects and exposes app plus shared helpers via __all__.
Shared catalog construction and test-case iteration helpers
packages/climate-ref/src/climate_ref/cli/test_cases/_catalog.py, packages/climate-ref/src/climate_ref/cli/test_cases/_common.py
_catalog.py adds _build_catalog (adapter-per-parent-dir scan), _solve_test_case (runs solve_executions), and _fetch_and_build_catalog (ESGF fetch → grouped source catalogs → YAML write). _common.py adds validation helpers, _write_test_case_manifest (authors manifest.json with catalog hash), and _iter_test_cases (filtered registry enumeration).
Composable execution stage pipeline
packages/climate-ref/src/climate_ref/cli/test_cases/_stages.py
Introduces StageError, SourceOutputs, prepare_slot, slot_native_relpaths, stage_execute, stage_materialise, stage_rebuild_from_slot, stage_build, snapshot_native, promote_to_baseline, stage_upload, stage_compare, native_is_stale, and write_source_stamp.
fetch, list, sync, and check-store commands
packages/climate-ref/src/climate_ref/cli/test_cases/discovery.py, packages/climate-ref/src/climate_ref/cli/test_cases/store.py
discovery.py adds fetch (ESGF download with dry-run/only-missing/force) and list (Rich table with catalog/regression presence). store.py adds sync (warms read-only native store cache) and check-store (preflights writable store credentials).
run command: execute, rebuild committed bundle, conditionally promote
packages/climate-ref/src/climate_ref/cli/test_cases/run.py
Adds _print_regression_summary (git-status Rich table with size thresholds), _run_single_test_case (staged execute → committed bundle rebuild → conditional promotion → native drift warning → source stamp), and the run_test_case Typer command (filter, dry-run, --label, pass/fail summary).
replay, mint, and build commands
packages/climate-ref/src/climate_ref/cli/test_cases/baselines.py
replay materialises stored native into a slot and asserts tolerant bundle equivalence. mint executes or re-materialises via --from-replay, uploads native, and always promotes to the tracked baseline. build rebuilds the committed bundle from an existing slot's native without re-executing, gating promotion on --force-regen or no-baseline.
ci-gate command: per-test-case replay/execute/skip/fail gating
packages/climate-ref/src/climate_ref/cli/test_cases/ci_gate.py
Adds _provider_source_root (locate provider package via importlib.util.find_spec), _core_extraction_roots (derive climate_ref_core extraction surfaces), and the ci-gate Typer command (git diff → extraction change detection → manifest integrity checks → decide_coupling → JSON/Rich table output).
Provider registry configure flag and CLI read-only commands
packages/climate-ref/src/climate_ref/provider_registry.py, packages/climate-ref/src/climate_ref/cli/__init__.py
ProviderRegistry.build_from_config adds a keyword-only configure: bool = True parameter to conditionally skip provider setup during metadata-only registry construction. CLI registry marks ("test-cases", "build") as read-only for backup-skip gating.
Unit test suite updates for refactored package
packages/climate-ref/tests/unit/cli/test_test_cases.py, packages/climate-ref/tests/unit/cli/test_root.py
Updates patch targets to submodule-qualified paths (_catalog._solve_test_case, ci_gate.get_repo_for_path). Adds _setup_real_run helper. Adds/refactors tests for labelled slot coexistence, --force-regen promotion, native-drift warnings, mint --from-replay, build slot validation/rebuild, replay stage patching, and a gitignore coverage check. Extends test root read-only commands.
Integration test documentation and wording updates
packages/climate-ref/tests/integration/test_native_roundtrip.py
Updates module and docstring documentation to clarify offline execution with LocalFilesystemStore in tmp_path and tolerant comparison semantics. Removes/reflows section-divider comments without changing test logic or assertions.

Regression manifest and float handling validation

Layer / File(s) Summary
Manifest schema and native entry validation
packages/climate-ref-core/src/climate_ref_core/regression/manifest.py
Manifest.loads() now rejects manifests with unsupported schema versions, and validates native entry size fields to reject booleans, non-integers, and negative values with specific error messages.
Float detection and committed-bundle serialisation validation
packages/climate-ref-core/src/climate_ref_core/regression/_quantise.py, packages/climate-ref-core/src/climate_ref_core/regression/capture.py
Clarifies float-rounding scope (applies to series.json and diagnostic.json, excludes output.json). Adds _contains_float() helper, declares unrounded committed files, and post-rounding validation that warns if floats are detected in output.json.
Unit tests for manifest and float validation
packages/climate-ref-core/tests/unit/regression/test_manifest.py, packages/climate-ref-core/tests/unit/regression/test_capture.py
Adds parametrised tests for unsupported schema rejection and invalid native entry size detection. Adds tests asserting committed-file classification exhaustiveness, output.json float-freeness by construction, and byte-for-byte preservation of output.json during bundle writing whilst confirming float rounding occurs for other artefacts.
Logging retention concurrency tolerance
packages/climate-ref-core/src/climate_ref_core/logging.py, packages/climate-ref-core/tests/unit/test_logging.py
Adds _retention_count_ignore_missing helper to delete older log files whilst suppressing FileNotFoundError for concurrent cleanup tolerance. Updates initialise_logging to use the new callable retention. Adds test coverage verifying missing-file tolerance during retention cleanup.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarises the two main changes: output slots, stage decomposition, and the CLI package split from the monolithic test_cases.py file.
Description check ✅ Passed The description covers the two main objectives (output slots/stage decomposition and CLI package split), includes implementation details, and confirms all three checklist items (tests, documentation, changelog).
Docstring Coverage ✅ Passed Docstring coverage is 83.89% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/test-cases-output-slots

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

Record the output-slots feature and the test_cases CLI package split.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Nitpick comments (3)
packages/climate-ref/src/climate_ref/cli/test_cases/baselines.py (1)

454-477: 💤 Low value

Consider extracting shared promotion logic.

This block is nearly identical to run.py lines 212–235: both gate on force_regen or not paths.regression.exists(), preserve previous.native, and warn on staleness. Extracting a shared helper (e.g., _maybe_promote_baseline(slot, paths, committed, previous, *, print_summary=False)) would reduce duplication, though the current repetition is manageable.

packages/climate-ref/src/climate_ref/cli/test_cases/store.py (1)

88-94: ⚖️ Poor tradeoff

Consider if store API offers direct cache-warming method.

The pattern of fetching to a temporary file that's immediately discarded is used to trigger cache population as a side effect. Whilst this works, it's not immediately obvious to future maintainers.

If the underlying store API (Pooch) exposes a direct .ensure_cached(sha256) or similar method, prefer that for clarity. Otherwise, add a brief inline comment explaining that fetch populates the cache as a side effect.

packages/climate-ref/tests/unit/cli/test_test_cases.py (1)

1764-1778: 💤 Low value

Consider documenting the path assumption for the gitignore test.

The parents[5] assumes a specific directory depth from the test file to the repository root. If this test file is ever relocated, the path resolution will break silently (or fail to find the correct .gitignore).

Consider adding a defensive assertion or comment:

 def test_output_slot_pattern_is_gitignored(tmp_path):
     """The repo .gitignore shadows materialised output slots under any test-data tree."""
     from git import Repo

     repo_gitignore = Path(__file__).resolve().parents[5] / ".gitignore"
+    # Sanity check: ensure we found the repo root (not some other directory)
+    assert repo_gitignore.exists(), f"Expected repo .gitignore at {repo_gitignore}"
     repo = Repo.init(tmp_path)

This would provide a clearer failure message if the path assumption becomes invalid.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 048a493f-e2f4-4d9e-a6fd-4390ab359071

📥 Commits

Reviewing files that changed from the base of the PR and between dfe8f98 and f76f33a.

📒 Files selected for processing (17)
  • .gitignore
  • changelog/748.feature.md
  • changelog/748.trivial.md
  • docs/background/regression-baselines.md
  • packages/climate-ref-core/src/climate_ref_core/testing.py
  • packages/climate-ref/src/climate_ref/cli/test_cases.py
  • packages/climate-ref/src/climate_ref/cli/test_cases/__init__.py
  • packages/climate-ref/src/climate_ref/cli/test_cases/_app.py
  • packages/climate-ref/src/climate_ref/cli/test_cases/_catalog.py
  • packages/climate-ref/src/climate_ref/cli/test_cases/_common.py
  • packages/climate-ref/src/climate_ref/cli/test_cases/_stages.py
  • packages/climate-ref/src/climate_ref/cli/test_cases/baselines.py
  • packages/climate-ref/src/climate_ref/cli/test_cases/ci_gate.py
  • packages/climate-ref/src/climate_ref/cli/test_cases/discovery.py
  • packages/climate-ref/src/climate_ref/cli/test_cases/run.py
  • packages/climate-ref/src/climate_ref/cli/test_cases/store.py
  • packages/climate-ref/tests/unit/cli/test_test_cases.py
💤 Files with no reviewable changes (1)
  • packages/climate-ref/src/climate_ref/cli/test_cases.py

Comment thread docs/background/regression-baselines.md Outdated
Comment thread packages/climate-ref/src/climate_ref/cli/test_cases/_catalog.py Outdated
Comment thread packages/climate-ref/src/climate_ref/cli/test_cases/_catalog.py
Comment thread packages/climate-ref/src/climate_ref/cli/test_cases/_stages.py
Comment thread packages/climate-ref/src/climate_ref/cli/test_cases/_stages.py Outdated
Comment thread packages/climate-ref/src/climate_ref/cli/test_cases/discovery.py Outdated
…oring

Two correctness fixes in the regression replay/mint machinery surfaced by an
adversarial review:

- stage_compare now drives the committed-bundle comparison from the manifest's
  committed set and hard-fails when an expected file is missing from the tracked
  baseline or from the regenerated bundle (or when there is nothing to compare).
  It previously derived the set from whatever existed under regression/, so a
  missing baseline let a replay report success without verifying anything.

- mint --from-replay now preserves the previously minted native block verbatim
  instead of snapshotting the slot. stage_materialise hydrates the slot's native
  in place while rebuilding, so a fresh snapshot would re-author the manifest
  with non-portable, slot-specific blobs even though the canonical native
  baseline is unchanged.

Adds stage_compare unit tests and a from-replay native-preservation test.
- docs: clarify run seeds manifest.native={} only on first seed
- catalog: sort parent dirs for deterministic baseline selection
- catalog: fail fast on adapter parse errors instead of a partial catalog
- stages: collect per-blob upload errors instead of aborting the mint loop
- discovery: extract duplicated provider validation to a shared helper
stage_rebuild_from_slot imported load_datasets_from_yaml at module level, while
the run/mint verbs import it locally inside the function. A single
climate_ref_core.testing.load_datasets_from_yaml mock therefore did not reach
the replay rebuild path, which needed a second use-site patch. Import it locally
in _stages too (TestCasePaths, annotation-only, moves under TYPE_CHECKING, so the
module no longer pulls climate_ref_core.testing into CLI startup), so one mock
target now covers every call site.

Also tidies the round-trip integration test docstrings/section comments and
corrects the corrupted-bundle test docstring: the advisory integrity check does
not gate replay; the tolerant comparison does.
@codecov

codecov Bot commented Jun 22, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 84.89362% with 142 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...te-ref/src/climate_ref/cli/test_cases/baselines.py 71.24% 55 Missing and 12 partials ⚠️
.../climate-ref/src/climate_ref/cli/test_cases/run.py 86.75% 10 Missing and 10 partials ⚠️
...mate-ref/src/climate_ref/cli/test_cases/ci_gate.py 91.12% 8 Missing and 3 partials ⚠️
...mate-ref/src/climate_ref/cli/test_cases/_common.py 84.12% 4 Missing and 6 partials ⚠️
...limate-ref/src/climate_ref/cli/test_cases/store.py 87.50% 7 Missing and 2 partials ⚠️
...te-ref/src/climate_ref/cli/test_cases/discovery.py 90.69% 4 Missing and 4 partials ⚠️
...mate-ref/src/climate_ref/cli/test_cases/_stages.py 93.91% 5 Missing and 2 partials ⚠️
...ef-core/src/climate_ref_core/regression/capture.py 62.50% 3 Missing and 3 partials ⚠️
...s/climate-ref-core/src/climate_ref_core/testing.py 66.66% 2 Missing ⚠️
...ate-ref/src/climate_ref/cli/test_cases/_catalog.py 96.49% 1 Missing and 1 partial ⚠️
Flag Coverage Δ
core 92.53% <84.78%> (-0.09%) ⬇️
providers 91.82% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...s/climate-ref-core/src/climate_ref_core/logging.py 91.66% <ø> (ø)
...-core/src/climate_ref_core/regression/_quantise.py 100.00% <ø> (ø)
...f-core/src/climate_ref_core/regression/manifest.py 100.00% <100.00%> (ø)
...ckages/climate-ref/src/climate_ref/cli/__init__.py 96.96% <ø> (ø)
...ate-ref/src/climate_ref/cli/test_cases/__init__.py 100.00% <100.00%> (ø)
...climate-ref/src/climate_ref/cli/test_cases/_app.py 100.00% <100.00%> (ø)
...s/climate-ref/src/climate_ref/provider_registry.py 100.00% <100.00%> (ø)
...s/climate-ref-core/src/climate_ref_core/testing.py 89.61% <66.66%> (-0.55%) ⬇️
...ate-ref/src/climate_ref/cli/test_cases/_catalog.py 96.49% <96.49%> (ø)
...ef-core/src/climate_ref_core/regression/capture.py 87.50% <62.50%> (-8.34%) ⬇️
... and 7 more

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

replay/mint/build/sync/ci-gate accepted --provider without checking it is
a configured provider, so a typo iterated zero cases and exited 0 — for
ci-gate that was a silent CI bypass that verified nothing. Route all five
verbs through the shared _validate_provider_in_registry helper and replace
run's hand-rolled lookup with it, so an unknown provider fails with exit 1
everywhere. A real provider with zero matching cases still exits 0.
Manifest.loads accepted any schema value verbatim, despite the documented
contract that the loader rejects manifests whose schema does not match
SCHEMA_VERSION — so a manifest from a future/incompatible writer would be
silently misread under today's field semantics by the coupling gate. It
also took NativeEntry.size straight from JSON, letting a negative, float,
or string size load cleanly and break the byte-identical-dump guarantee.
Enforce schema == SCHEMA_VERSION and a non-negative int size in loads.
The docstrings claimed output.json's floats are rounded, but it was
omitted from the rounding map, and the rounded-file set was a drift-prone
hand-maintained subset of COMMITTED_BUNDLE_FILES. output.json carries no
float leaves and is Pydantic-serialised (no sort_keys), so rounding it via
json.dumps(sort_keys=True) would reorder its keys and churn the committed
bytes. Make the rounded/not-rounded classification explicit and exhaustive
(killing the drift), correct the docstrings, and warn at runtime if an
unrounded committed file ever gains a float. No committed bytes change.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 781f662a-1892-4889-b15c-9f0b2461d9f9

📥 Commits

Reviewing files that changed from the base of the PR and between caf9380 and 39f6ffa.

📒 Files selected for processing (10)
  • packages/climate-ref-core/src/climate_ref_core/regression/_quantise.py
  • packages/climate-ref-core/src/climate_ref_core/regression/capture.py
  • packages/climate-ref-core/src/climate_ref_core/regression/manifest.py
  • packages/climate-ref-core/tests/unit/regression/test_capture.py
  • packages/climate-ref-core/tests/unit/regression/test_manifest.py
  • packages/climate-ref/src/climate_ref/cli/test_cases/baselines.py
  • packages/climate-ref/src/climate_ref/cli/test_cases/ci_gate.py
  • packages/climate-ref/src/climate_ref/cli/test_cases/run.py
  • packages/climate-ref/src/climate_ref/cli/test_cases/store.py
  • packages/climate-ref/tests/unit/cli/test_test_cases.py
✅ Files skipped from review due to trivial changes (1)
  • packages/climate-ref-core/src/climate_ref_core/regression/_quantise.py
🚧 Files skipped from review as they are similar to previous changes (5)
  • packages/climate-ref/src/climate_ref/cli/test_cases/store.py
  • packages/climate-ref/src/climate_ref/cli/test_cases/run.py
  • packages/climate-ref/src/climate_ref/cli/test_cases/ci_gate.py
  • packages/climate-ref/src/climate_ref/cli/test_cases/baselines.py
  • packages/climate-ref/tests/unit/cli/test_test_cases.py

Comment thread packages/climate-ref-core/src/climate_ref_core/regression/manifest.py Outdated
The schema guard used value equality only, so True (a bool subclass of
int) and 1.0 (1.0 == 1) were accepted as valid when SCHEMA_VERSION == 1.
Require schema to be a non-bool int equal to SCHEMA_VERSION, matching the
NativeEntry.size validation in the same loader, and extend the rejection
test to cover True and 1.0.
On CI ($GITHUB_ACTIONS) Typer forces its help console into terminal mode
and emits ANSI. NO_COLOR strips colour but not the bold its highlighter
wraps around <metavars>, which split tokens like `output/<label>` and broke
the substring assertion in test_run_help (green locally, red on CI).
Set TERM=dumb so Rich emits no escape codes at all.
@lewisjared lewisjared merged commit 3685d5f into main Jun 24, 2026
27 of 28 checks passed
@lewisjared lewisjared deleted the feat/test-cases-output-slots branch June 24, 2026 04:09
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