What you can do
You can treat a PKR Core result as something to re-derive rather than something to archive. Generation is seeded and the solvers are deterministic, so a recipe plus a seed is a complete description of a structure and of every property measured from it. A baseline from three weeks ago does not need its voxels kept anywhere. It needs its recipe kept.
- POST /api/v1/generate with a fixed seed returns the same structure. A few hundred bytes of JSON is enough to get it back.
- The property solvers return the same value for the same structure. There is no run-to-run scatter to average away.
- Figures the server draws come back identical — cross sections from export-image-stack, the trend chart from parametric-study. A plot in a report can be regenerated instead of stored.
- GET /api/v1/healthz reports deployedSha, the build that answered. A result can be labelled with the version that produced it.
Why it matters
Comparing two candidates measured weeks apart only works if the platform contributes nothing to the difference between them. Otherwise every comparison carries an unknown amount of drift. The only safe move is then to recompute the baseline every time, which is exactly the work you were trying to avoid.
When the service contributes zero, whatever spread you do see belongs to your structure. That is a number worth knowing on its own. In this run, a randomly packed 32³ box has no preferred direction, yet it returned conductivities of 4.4558, 4.2561 and 4.1198 W/m·K along x, y and z. That is about 8 % between the fastest and the slowest axis, purely from having a finite number of spheres in a small box. It is the floor under any comparison at this size. If the service drifted too, you could not tell the two apart.
What was compared
The same showcase script ran on 2026-09-04 and again on 2026-09-06, against api.pakericore.app. The deployed commit was 1162757 the first time and ebf9efc the second. Same three example recipes at 64³, packings raised to 45 % solid at 15 % overlap, solid phase alumina at 30 W/m·K, and the same closed-form validation fixtures.
| Quantity | Published from the 2026-09-04 run | Measured 2026-09-06 |
|---|---|---|
| Particle packing, conductivity (W/m·K) | 19.21 | 19.211442684614628 |
| Fiber packing, conductivity (W/m·K) | 21.46 | 21.455226746729483 |
| Foam-like, permeability (µm²) | 7.43 | 7.4336097575724125 |
| Two slabs in parallel, x (W/m·K) | 50.49074 | 50.49074205942826 |
| Random packing, x (W/m·K) | 4.4558 | 4.4558288976859135 |
Every value agrees to every digit that was published. The solid fractions agree exactly as well: 0.4503746032714844 for the particle packing, the same binary fraction both times. Within this run, generating one recipe twice with the same seed gave a relative difference of exactly zero. Not "within tolerance". Zero.
The images are the sharper test. A rounded table can hide a small change. A PNG cannot. Every figure published with the earlier articles has the same SHA-256 as the file downloaded from the API two days later.
| Artifact the API returned | SHA-256, first 12 hex digits — identical in both runs |
|---|---|
| Particle-packing cross section (PNG) | a50f1cd34b38 |
| Fiber-packing cross section (PNG) | 5ca7fd47f266 |
| Foam-like cross section (PNG) | c07da71b3526 |
| Two-slab validation fixture (PNG) | 026a063ffd40 |
| Capability-suite structure (PNG) | 720c128ae2ef |
| Five-point sweep trend chart (SVG) | a8d0a8b046db |

What did not repeat
Wall-clock time, and only wall-clock time. Generating the particle packing took 349 ms in the first run and 428 ms in the second. The fibers went the other way, 673 ms down to 623 ms. The whole three-structure suite was 10.3 s, then 11.0 s. Timing is a property of the machine and the load at that moment, not of your input.
That distinction has one practical consequence: never build a study whose result depends on a call fitting inside the synchronous request window. The full-grid 3d conductivity solver at 32³ returned 504 after 15.1 s in both runs. The ceiling reproduced, but as a ceiling, not as a number. Anything sitting near it is a coin flip, and the reduced solvers exist precisely so that you do not have to sit there.
Send the recipe, not the handle
A structureId is a server-side handle with a lifetime. It is not the identity of the structure. Registering a structure once with storeStructure and passing that id to every later call does keep request bodies small. But in the capability run, ten analysis calls came back 404 structure_not_found — "Stored structure is unknown or expired". Every one of them arrived after the 15-second timeout above had elapsed.
The recipe is the identity. In the same run, one POST /api/v1/workflows/run carried the recipe itself, with no stored id anywhere in the request. It generated the structure and returned 11 of the 12 requested outputs in 3.8 s. The one that did not land was the CO₂ adsorption step, which reported unstable_timestep as a named step error rather than failing the whole request. Eleven results and one explained gap beats no results.
So the durable record of a measurement is four small things:
- the recipe, including its seed
- the material constants it was solved with (GET /api/v1/materials)
- the analysis method name
- the deployedSha that answered
Keep those and the numbers come back. Keep only a structureId and you have kept a receipt for something that has been thrown away.