Skip to content

feat(domain): add forced Kolmogorov flow to ns-grid, with forward and chained-gradient checks - #272

Merged
dionhaefner merged 61 commits into
mainfrom
feat/kolmogorov-forward
Nov 2, 2026
Merged

dionhaefner merged 61 commits into
mainfrom
feat/kolmogorov-forward

Conversation

@dionhaefner

@dionhaefner dionhaefner commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Relevant issue or PR

All Kolmogorov-flow work in one PR: body forcing for the ns-grid solvers, the three checks and the ground truth. It replaces #267 (forcing inputs) and #310. It builds on #268 (Exponax in 2D ns-grid, including its 2D sign fix) and #317 (experiment-generated references), both now on main. #203 (docs redesign) is now on main too, with the Kolmogorov setup on its scoreboard; the protocol text of the three checks is still to be added here.

The solver-in-the-loop study that led here is in draft #316 for reproduction. It is not meant to merge.

Description of changes

Three checks of the forced 2D Kolmogorov flow (force sin 4y, linear drag), the ground truth they score against, its generator, and the inputs and outputs they need. It also fixes PhiFlow's periodic pressure solve, which made PhiFlow fail both turbulent checks and run for 79 minutes on CI.

Forcing inputs. The canonical ns-grid schema gets two optional, non-differentiable inputs, allowed only on 2D periodic boxes:

inputs = {..., "forcing": f, "linear_drag": np.array([0.1], np.float32)}  # f: (N, N, 1, 2), at cell centers

Each solver applies them inside its own time step, in both apply and VJP, and maps the force to its native locations the same way it maps v0. With both left at None, every solver runs the code it ran before.

Solver Force Drag
JAX-CFD forcing callable of semi_implicit_navier_stokes, averaged onto the faces explicit, in every RK4 stage
PhiFlow resampled to the faces like v0, in the momentum rate of every RK4 stage in every RK4 stage
Warp-NS in tentative_vel_2d_kernel explicit
PICT velocity source set every step, in unit-cell units explicit, from the velocity at the start of the step
INS.jl projected staggered force added to the right-hand side in every RK4 stage
XLB exact-difference method after collision; half-force velocity shift for the output semi-implicit in the half-force velocity
Exponax spectral curl of the force as the injection term of its Kolmogorov stepper (its own injection_mode would put sin κy half a cell off) Exponax's drag; the mean flow decays exactly
OpenFOAM rejected: icoFoam has no momentum source term rejected

With a force, XLB sizes its lattice Mach number from a bound that does not depend on the solution, so a flow that the force spins up from rest stays at the target Mach number.

Snapshots. One more optional input and a non-differentiable output, also 2D periodic boxes only:

inputs = {..., "steps": 400, "snapshot_every": 100}
out["snapshots"]  # (4, N, N, 1, 2): the velocity at the cell centers after 100, 200, 300 and 400 steps

Each solver records them inside its own loop, so its staggered or lattice state never round-trips through the cell centers between times: JAX-CFD slices its trajectory, Exponax, PhiFlow and XLB nest their scans, INS.jl records in its RK4 loop, PICT in a post-step hook, Warp-NS in its step loop. The VJPs skip them. OpenFOAM rejects them, as it rejects the forcing.

forward/kolmogorov_laminar. From rest at ν = 0.05 the flow stays a shear flow with an exact solution, u = (A/λ)(1 − e^{−λt}) sin(κy). The sweep is N ∈ {32, 64, 128} to t = 2. The check is max_error(0.05, at=64) plus min_order(0.8). A correct second-order scheme is off by about 1% at N = 64. A convention bug (a missing 2π/L, a flipped sign, a force half a cell off) is off by 20% or more.

forward/kolmogorov. Each solver runs on a ladder of grids, 32² to 256², at the CFL number of 64² with dt = 0.01, from three turbulent states. Each grid runs once to t = 4, returns the velocity at t = 1, 2, 3 and 4 as snapshots, and is scored on 64² against the truth. From the first non-finite snapshot on, the run counts as diverged. The plot shows error against wall time per time unit. The check is min_refinement_order(0.8): the observed order from 64² to 256² at t = 1 must be at least 0.8, and no grid from 64² up may diverge. The bound comes from the scheme's consistency, not from the other solvers.

gradient/chain_fd_check. Training a model through a solver chains many calls, and its loss is normalized by the target, so each call receives a far smaller cotangent than in the single-call gradient checks. A VJP that is only accurate for large cotangents, for example because its adjoint solves stop at an absolute tolerance, passes those checks and fails this one. The check chains 16 calls of 0.1 time units at 64². It starts from a truth state plus a 1% divergence-free offset, and the loss is the mean relative squared distance to the solver's own unperturbed chain. The VJP is compared with central differences over 8 divergence-free directions at ε ∈ {1, 0.1, 0.01}. The gates are min_cosine(0.99), max_rel_err(1e-2) and rel_err_peer_outlier(50). A correct VJP meets float32 differences to 1e-4–2e-3, and a truncated one is off by tens of percent.

Ground truth. The ground truth is an Exponax run at 1024², with 2/3-rule dealiasing, from three states spun up for 100 time units. Its generator runs through #317's reference path. A 512² run differs from the truth by 0.3% at t = 1. The 0.7 MB file is documented in references/README.md.

PhiFlow's periodic pressure solve. The periodic pressure matrix is singular. Unless the solve states its rank deficiency, phiml adds a Lagrange multiplier to it, which makes the system indefinite, and CG is not guaranteed to converge on that. Under jit, phiml returns an unconverged solve without raising. On the Kolmogorov flow at 256², 852 of 6400 solves to t = 4 stopped unconverged, 128 of them flagged as diverged with residuals up to 10⁴ times the right-hand side. Which grid and state then went non-finite varied from run to run. The solve now passes rank_deficiency=0. make_incompressible already balances the divergence to zero mean, so plain CG on the singular system converges, in about 375 iterations instead of 570. The adjoint solve now stops at the relative tolerance only, because its right-hand side scales with the cotangent. With the absolute tolerance, the chain check's small cotangents stopped it after 0–17 iterations. Both are recorded as interventions. The fix also makes PhiFlow's cost experiments faster, 1.3–7.5× in 2D and 1.4–16× in 3D, growing with N. All four of its ns-grid cost anomalies become ok, so their explanation, which attributed the cost to the sparse matrix-vector product, is removed.

Warp-NS is excluded from the turbulent checks: its explicit-Euler, central-difference scheme is linearly unstable unless dt ≲ 4ν/u², a bound that does not shrink with the grid. OpenFOAM is excluded too: icoFoam has no source term, and OpenFOAM has no VJP.

Results (A100)

forward/kolmogorov_laminar, relative error at N = 32 / 64 / 128. All pass.

Solver 32 64 128
Exponax 3.0e-06 3.5e-05 1.3e-05
JAX-CFD, INS.jl, PhiFlow 2.9e-02 7.4e-03 1.8e-03
PICT 2.9e-02 7.1e-03 1.7e-03
Warp-NS 3.0e-02 7.7e-03 2.2e-03
XLB 7.8e-02 1.9e-02 4.8e-03

forward/kolmogorov (median error at t = 1 per grid, observed order 64² → 256²) and gradient/chain_fd_check (median error and cosine at the best ε):

Solver 32² 64² 128² 256² Order Chain error Chain cosine
Exponax 0.168 0.039 0.0046 0.0028 1.89 1.8e-03 1.0000
JAX-CFD 0.226 0.086 0.029 0.0077 1.73 2.4e-04 1.0000
INS.jl 0.226 0.086 0.029 0.0077 1.73 2.1e-04 1.0000
XLB 0.135 0.032 0.0063 0.0032 1.66 9.8e-05 1.0000
PICT 0.258 0.092 0.034 0.012 1.46 2.1e-04 1.0000
PhiFlow 0.206 0.082 0.028 0.0076 1.72 2.5e-04 1.0000

Every solver passes both checks. Before the PhiFlow fix, its 256² run went non-finite at t = 4 from two of the three states on CI, and its chain gradient was non-finite on CI and off by 12% at the best ε on the A100.

forward/kolmogorov took 1,027 s for all solvers together on the A100: PICT 523 s, PhiFlow 349 s, INS.jl 68 s, the others under 40 s. The last CI run took 6,600 s on its GPU, 4,759 s of it PhiFlow's. Locally, PhiFlow took 5,585 s before the fix.

The chained check also catches the defect that #294 fixed. Before that fix, PICT's adjoint solves stopped at an absolute tolerance, and the check gave a median error of 0.89 at a cosine of 0.51.

Testing done

  • tests/test_schemas.py: the forcing inputs and snapshot_every are rejected outside 2D periodic boxes, and snapshot_every must divide steps. tests/test_ns_grid_forcing.py (Docker, skipped without images) checks every solver image on four things: the laminar transient within 5% at N = 64, a zero force with zero drag against the unforced output, a forced VJP against central differences within 1%, and the snapshots of a forced run against separate runs that stop at their steps, to 1e-5. OpenFOAM must reject both. All 30 pass.
  • tests/test_kolmogorov.py covers: exact resampling of band-limited fields, the laminar solution, the vorticity identities, the forward kernel on a fake solver including a diverged grid and a run that diverges only at its last snapshot, and min_refinement_order. tests/core/test_reference.py checks the layout of the stored truth.
  • tests/test_chain_fd_check.py covers: the loss, the divergence-free directions, a correct VJP, and a VJP that drops small cotangents, which the check must flag.
  • The unit suite passes on this branch merged with main.
  • No regression from the snapshots: with them, every solver's forward/kolmogorov errors match the previous CI run's separate calls to within 1e-4 relative (PhiFlow aside). mosaic run of the ns-grid forward suite, gradient/fd_check, gradient/chain_fd_check and the ns-3d forward suite changes no status against that CI run apart from PhiFlow's two fixes. PhiFlow with the fix also ran every suite of both problems: no other status changed, and best-ε gradient errors stayed where they were (ns-grid fd_check 1.04e-5 against 1.05e-5).
  • No regression from the forcing inputs (A/B on 2026-10-26, unforced multimode, 2D TGV and 3D TGV, forward and VJP). JAX-CFD, XLB and INS.jl were bitwise identical to main. Warp-NS, PICT and PhiFlow were within 2e-7 (forward) and 2e-6 (VJP), the same as main against itself.
  • Results come from the solver images of this PR's previous CI run (built from 83a4d7e, so with fix(solver): tighten PICT's periodic linear-solve tolerance to 1e-6 #287, fix(solver): use XLA's default GEMM autotuning in jax-cfd, PhiFlow and XLB #291 and perf(solver): run INS.jl on its CUDA backend #307), with this push's solver sources and canonical schema layered on top, run on an A100 on 2026-11-02.

🤖 Generated with Claude Code

# Conflicts:
#	mosaic/tesseracts/navier-stokes-grid/xlb/tesseract_api.py
Exponax now runs with its default 2/3-rule dealiasing (#280), and the
truth, its initial states and its convergence check are regenerated with
it. The 512² run tracks the 1024² truth as closely as before (0.3% after
one time unit, 2.3-3.2% after four), and JAX-CFD still converges to it at
observed orders 1.6 and 1.9.
With its default dealiasing (#280) Exponax stays stable on both
configurations of forward/kolmogorov, so the exclusion for its aliasing
instability goes.
Each solver now runs on 32² to 256² at the coarse configuration's CFL
number and records the wall time of one time unit on each grid, so the
result shows how much accuracy each solver buys per second. The status
check asks that refining from 64² to 256² converge at order 0.8 or more
and that no grid from 64² up diverge, in place of the reference-to-coarse
error ratio.
gradient/chain_fd_check differentiates a training-style loss through 16
chained solver calls on the Kolmogorov flow and compares the gradient with
central differences. The loss is relative to its targets, so the cotangents
each call receives are far smaller than in the single-call checks. A VJP
that is only accurate for cotangents of order one fails it. The result has
the shape of fd_check's and goes through the same status checks and plot.
…plot

A perturbed run that diverges leaves NaN differences, which the result
JSON stores as null. The plot passed them to math.isfinite and float and
failed; it now leaves them out, as the status checks already do.
Adds an intervention record to each tesseract's metadata.mosaic block:
the solver's abstraction level, its interventions (level by mechanism,
necessity, and per setup the consequences, symptom and evidence), and
its setup deviations. Discovery parses it into SolverSpec.record, and a
test validates every record and its mosaic-intervention markers.

Records for OpenFOAM, FEniCS (structural and heat), XLB and Warp-NS,
checked against the current code.
Adds intervention records for deal.II, Firedrake, JAX-FEM and torch-fem
(structural and heat), TopOpt.jl, Exponax, INS.jl, jax-cfd, PhiFlow and
PICT, checked against the current code, with markers around their L2
and L3 code. The format check now requires a record on every tesseract.
dionhaefner and others added 4 commits November 1, 2026 22:39
…ecks

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ks use

Drop the spectrum and correlation metrics of forward/kolmogorov, which no
plot or check reads, and the burned-in states that no experiment starts
from.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Records the tuning that merged after the records were written (#296,
#299, #301, #305, #306, #307, #308, #314) and drops what it removed
(#268, #284, #296). Applies the same rules to every solver: `tuned`
marks a setting picked by measuring alternatives, a setup an
intervention was never measured on gets its own `unknown` entry, and
settings that only keep Julia working under juliacall or only let
solvers share the benchmark machine are not recorded.
Split spliced sentences, cut explanations repeated across docstrings, and
use American spelling (including cell_centers). Update the docstrings of
XLB, INS.jl and Warp-NS that still described the unforced solvers.
@read-the-docs-business

read-the-docs-business Bot commented Nov 1, 2026 •

Copy link
Copy Markdown

…ence

Add the body force and drag to the ns-grid description, and list the
2D Kolmogorov flow among the converged spectral references.
dionhaefner added a commit that referenced this pull request Nov 1, 2026
## Summary

Records the interventions and setup deviations of the 14 tesseracts #302
left out: deal.II, Firedrake, JAX-FEM and torch-fem (structural and
heat), TopOpt.jl, Exponax, INS.jl, jax-cfd, PhiFlow and PICT. It also
brings #302's records for OpenFOAM, Warp-NS, XLB and FEniCS up to date
with the tuning PRs that merged after it. L2/L3 code gets
`mosaic-intervention` markers, and the format check now requires a
record on every tesseract.

## Type of change

- [ ] New solver backend
- [ ] Solver tuning / improvement
- [ ] New benchmark domain
- [x] Harness / infrastructure change
- [x] Documentation
- [ ] Bug fix

## What changes

Each record starts from the intervention spike (annotations of 6517f75)
and is checked against `main` at 6e850bb. Interventions the cleanup
removed are dropped, for example XLA autotuning flags (#291), Exponax's
dealiasing (#280), JAX-FEM's `umfpack_solver` (#286), TopOpt.jl's INP
parser patch (#299) and PhiFlow's periodic CG tolerance (#296). Settings
the tuning PRs introduced are recorded as tuned L0 interventions with
their measurements: OpenFOAM's periodic GAMG and MPI decomposition
(#306, #314), the channel CG tolerances of Warp-NS and PhiFlow (#308),
torch-fem's CG tolerance (#301), deal.II heat's AMG preconditioner
(#305) and INS.jl's CUDA backend (#307). Where nobody knows why
something is there, the record says `necessity: unknown`; where an
intervention was never measured on a setup, that setup gets its own
`unknown` entry. Setup caches, warm-ups and the deal.II worker are
runtime adaptations and are not recorded.

The rubric in `docs/tutorial.qmd` now says what `tuned` covers (a
setting picked by measuring alternatives), that runtime settings which
only keep Julia working under juliacall are wrapper fixes, and that
settings which only let solvers share the benchmark machine, such as
JAX's GPU memory fraction, are not recorded.

Highest required level per setup:

| Level | Setups |
| --- | --- |
| L3 | PhiFlow on the periodic boxes (int64 index patch), FEniCS heat |
| L2 | PhiFlow and PICT on the cylinder, Warp-NS everywhere, XLB on the
periodic boxes, Exponax in 2-D |
| L0 | OpenFOAM on the 2-D box and the cylinder, PICT on the 2-D box,
torch-fem |
| none | the rest |

## Benchmark label

`benchmark:none`: YAML metadata, comments and one schema description.

## Notes

- Some evidence is not public yet: PICT's outflow A/B in OpenFOAM,
PhiFlow's semi-Lagrangian accuracy figure and FEniCS's adjoint-patch A/B
live in the unpublished cleanup notes.
- Still to record when they merge: DAFoam (#295) and any setups the
Kolmogorov PRs (#272) add.
- Judgment calls for review are in the first comment.
…nto feat/kolmogorov-forward

# Conflicts:
#	mosaic/tesseracts/navier-stokes-grid/exponax/tesseract_api.py
Exponax sets its stepper's private injection term to place the force at
the cell centers, jax-cfd sums the force and drag itself because
sum_forcings needs jax.tree_map, and XLB applies the exact difference
method by hand because its operator takes only a constant force. Extend
the INS.jl rollout, Exponax mean-flow and XLB sub-stepping records to the
forced runs.
# Conflicts:
#	mosaic/tesseracts/navier-stokes-grid/exponax/tesseract_api.py
#	mosaic/tesseracts/navier-stokes-grid/exponax/tesseract_config.yaml
#	mosaic/tesseracts/navier-stokes-grid/ins-jl/solver.jl
#	mosaic/tesseracts/navier-stokes-grid/ins-jl/tesseract_config.yaml
#	mosaic/tesseracts/navier-stokes-grid/jax-cfd/tesseract_config.yaml
@dionhaefner dionhaefner added the benchmark:domain Benchmark every solver in the domain whose problem definition changed label Nov 1, 2026
@PasteurBot

PasteurBot commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

📊 View the full benchmark results

The rendered docs preview has every plot for this run (forward accuracy, gradients, cost, optimization) merged with existing baseline results on main. The summary below reports pass/fail status.


Mosaic status

Benchmarks: skipped by the benchmark:none label.

Kolmogorov flow is a different problem statement from the decaying
Taylor-Green box, so its experiments (forward/kolmogorov,
forward/kolmogorov_laminar, gradient/chain_fd_check) now belong to a new
ns-2d-kolmogorov setup instead of falling into the periodic box. Results
pages then report them separately, and a solver's flags on the forced flow
no longer count towards its Taylor-Green results.

The forcing interventions of Exponax, jax-cfd and XLB move to the new
setup, since only the forced runs need them. Interventions on the shared
periodic code path apply to both setups and reuse the same reason.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
dionhaefner and others added 3 commits November 2, 2026 17:11
…tiplier

make_incompressible pads the singular periodic pressure system with a
Lagrange multiplier unless the solve states its rank deficiency, which makes
the system indefinite. CG is not guaranteed to converge on it, and under jit
phiml returns unconverged solves silently. On the Kolmogorov flow at 256²,
852 of 6400 solves to t = 4 stopped unconverged, two of three states went
non-finite on CI, and the chain gradient check got a non-finite gradient.

The periodic solve now passes rank_deficiency=0; make_incompressible
balances the divergence to zero mean, so plain CG converges. The adjoint
solve stops at the relative tolerance only, since its right-hand side
scales with the cotangent and the absolute tolerance stopped it after a few
iterations in the chain check.

Every PhiFlow cell of forward/kolmogorov and gradient/chain_fd_check now
passes, no other check changes, and the cost experiments run 1.3-7.5x
faster in 2D and 1.4-16x in 3D, so the sparse-CG cost explanation no longer
applies and is removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
forward/kolmogorov ran each scored time as its own call from t = 0, so every
solver simulated 1 + 2 + 3 + 4 = 10 time units per state and grid to score 4.
Chaining calls instead would round-trip staggered and lattice states through
the cell centers between times, which damps the finest scored modes.

The canonical ns-grid schema gets an optional snapshot_every input and a
non-differentiable snapshots output: the velocity at the cell centers after
every snapshot_every steps, 2-D periodic boxes only. Every solver that runs
the Kolmogorov flow records them inside its own loop (JAX-CFD from its
trajectory, Exponax, PhiFlow and XLB with a nested scan, INS.jl in its RK4
loop, PICT in a post-step hook, Warp-NS in its step loop); the VJPs skip
them. OpenFOAM rejects them, as it rejects the forcing.

The kernel makes one call per state and grid to the last time and scores
each snapshot, so a run that diverges late keeps its earlier times.
safe_apply_with_state can leave the finiteness check to the caller for
that.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dionhaefner added a commit that referenced this pull request Nov 2, 2026
## Summary

INS.jl now runs `forward/cylinder` and `optimization/drag_opt` on the
DFG 2D-1 channel, so it joins the cylinder setup instead of being
excluded as "not wired up". jax-cfd stays excluded; its exclusion now
says why the channel isn't expressible through its API.

## Type of change

- [ ] New solver backend
- [x] Solver tuning / improvement
- [ ] New benchmark domain
- [ ] Harness / infrastructure change
- [ ] Documentation
- [ ] Bug fix

### For solver tuning

- [x] Before/after compared: INS.jl's periodic path is unchanged
(`tests/test_ins_jl_consistency.py` passes on the new image); only the
cylinder cells are new
- [x] No regressions to other solvers (only INS.jl's tesseract changed)
- [x] Intervention record updated for every intervention added, changed
or removed

## What changes

- **The cylinder** is a Brinkman penalization force −χu/η, with η = dt.
χ = 1 on every face touching a cell of the shared staircase. INS.jl
5.0.0 has no obstacles; a body force is its documented hook for extra
physics. The drag is the penalization's integral.
- **The inlet profile** is added to the state after INS.jl's boundary
conditions. INS.jl's rrule gives a `DirichletBC` value no tangent, so
drag_opt would get a zero gradient.
- **The channel's pressure** is solved by diagonalizing INS.jl's
Laplacian, which splits into an x and a y operator on this grid.
`psolver_direct` needs INS.jl's CUDSS extension on the GPU, which fails
to load with CUDA.jl 6. `psolver_transform` rejects the pressure outlet,
and `psolver_cg` ran past 600 s where this takes 2.7 s.
- **The drag_opt charts** only drew a fixed XLB/PhiFlow/Warp-NS list;
INS.jl is added.
- Each workaround is an L2 intervention with its measurements in
`tesseract_config.yaml`.

## Benchmark label

`benchmark:solver`: INS.jl's tesseract changed.

## Results

On an A100, at 20 cells per diameter unless noted:

| | INS.jl | Peers (#272's CI) |
|---|---|---|
| Cd error (gate 5%) | −2.9% (−4.5% at 10) | −1.3% to +3.0% |
| Δp error | 6.0% | 3.5% to 6.8% |
| Cd drift (gate 1e-3) | 2e-5 | |
| drag_opt Cd / Cd₀ | 0.520, 58 iterations, 419 s | 0.523 to 0.537 |

- The penalization drag agrees with the control-volume Cd to 0.04%.
- The drag gradient matches a central difference to 3e-5.
- The optimized profile is within 2.2% of Warp-NS's.

## Notes

- **Drag gap:** INS.jl's drag sits about a point below PhiFlow and
Warp-NS on the same staircase. Halving η moves Cd by only 0.1%, so the
cause is still open.
- **README:** line 65 ("only four of seven … a spectral projection
incompatible with the geometry") is now out of date. I left it for you.
- **Upstream:** INS.jl's CUDSS extension imports `CUDSS.CUDA`, which
CUDSS 0.7 removed. Not reported upstream yet.
- **Tests:** `tests/test_ins_jl_cylinder.py` runs INS.jl's CPU backend
in a container without a GPU.

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@dionhaefner dionhaefner added benchmark:none Skip benchmarks (maintainer trusts no answer-changing code) and removed benchmark:domain Benchmark every solver in the domain whose problem definition changed labels Nov 2, 2026
# Conflicts:
#	mosaic/tesseracts/navier-stokes-grid/ins-jl/tesseract_api.py
#	mosaic/tesseracts/navier-stokes-grid/ins-jl/tesseract_config.yaml

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dionhaefner
dionhaefner force-pushed the feat/kolmogorov-forward branch from 6fd8ea2 to cba4383 Compare November 2, 2026 22:00
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dionhaefner
dionhaefner merged commit 44d1a34 into main Nov 2, 2026
13 checks passed
@dionhaefner
dionhaefner deleted the feat/kolmogorov-forward branch November 2, 2026 22:43
@pasteurlabs pasteurlabs locked and limited conversation to collaborators Nov 2, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

benchmark:none Skip benchmarks (maintainer trusts no answer-changing code)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants