> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ionworks.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Changelog — Page 2

> Ionworks Studio product updates from March to May 2026

<Update label="May 18, 2026" description="Material properties in Studio, native UCP simulation for design optimization, SimplePipeline workflow, global search endpoint">
  ## Material properties in Studio

  A new **Materials** section in the project sidebar lets you create
  materials within a project and attach measured property datasets
  (CSV / parquet) to each one. Upload, plot, edit, re-process, replace,
  and delete are all wired up. The Python SDK gains read-only `client.material`
  and `client.material_property_dataset` sub-clients with `list`, `get`,
  `get_units`, and `get_data` (returns a `polars.DataFrame`); the REST
  surface supports signed-URL downloads, on-the-fly downsampling, and
  x-range filtering. A new docs page covers the UI workflow and REST
  endpoints.

  ## Native UCP simulation for design optimization

  `DesignObjective` gained a `backend="ucp"` option that runs UCP protocols
  natively inside the optimization loop instead of converting them first.
  This preserves UCP features that the conversion dropped — dynamic loops,
  conditionals, gotos, `set_variable`, subroutines — and avoids
  per-iteration overhead. EIS steps are now rejected up front in design
  optimization (with a clear error both in the frontend form and at the
  backend), because the UCP backend does not yet support frequency-domain
  steps; standalone simulations remain the path for EIS.

  ## SimplePipeline workflow

  A new lightweight pipeline variant for configs with at most one
  expensive element (one data fit or one validation). The whole config
  runs end-to-end as a single background job instead of fanning out to
  child jobs. CRUD endpoints under `/simple_pipelines` (POST returns 202;
  LIST supports filters; PATCH for name/description; cancel and delete),
  plus a `client.simple_pipeline` SDK sub-client with `create`, `get`,
  `list`, `update`, `cancel`, `delete`, and `wait_for_completion`.

  ## Global search API

  New `GET /search` endpoint performs prefix full-text + substring
  search across projects, studies, simulations, models, parameterized
  models, optimizations, optimization templates, experiment templates,
  pipelines, cell specifications, and materials within the authenticated
  organization. There is no frontend search bar in Studio yet — the
  new docs page makes this explicit so you don't go looking for one.

  <AccordionGroup>
    <Accordion title="Studio">
      **Improvements**

      * Optimizations table: bulk **Delete** restored next to the existing
        bulk Cancel action, gated by `optimization:delete`, with a
        confirmation dialog that pluralizes correctly and per-row error
        toasts.
      * Protocol simulator: **Download CSV** button next to "Configure Plot"
        exports the full time-series plus step-level columns (cycle count,
        step number, protocol variables) expanded to match each time point,
        regardless of zoom.
      * Time-series measurement plot: overlay multiple variables sharing the
        same unit on either Y-axis via a `+` button — unit-filtered dropdown,
        distinct color cycle per series, individual `×` to remove, and
        selecting a primary variable with a different unit clears
        incompatible extras.
      * ECM models now expose `Anode potential [V]`, `Cathode potential [V]`,
        and their open-circuit counterparts so BioLogic three-electrode
        EWE / ECE control limits can be reproduced from a simulation. New
        `LFP/Li metal` half-cell chemistry added to the parameter library and
        the cell configuration UI.
      * Hover tooltips standardized to 3 decimal places across all plots.
      * EIS Nyquist plot renders as markers-only scatter (no connecting
        lines), with a slightly larger marker.
      * Cell-spec cascade delete now batches storage-path deletion and
        parallelizes per-measurement folder deletes, so one transient
        failure doesn't abort cleanup for the others.
      * Storage downloads now retry transient errors with exponential
        backoff — fixes job failures on intermittent non-JSON error responses.
      * A new endpoint returns the parsed contents of a job's metadata blob,
        giving the Python SDK a path to large validation payloads that the
        legacy result endpoint could not reach.
      * Simulation submission unified to a two-step pattern (parse-to-template
        then simulate-with-template). Removed several redundant older
        simulation endpoints.

      **Fixes**

      * Simulation dedup: removed a session-specific identifier from the
        uniqueness key used to detect duplicate simulations, so the
        "simulation already exists" path actually triggers and duplicate
        rows stop accumulating.
      * Measurement details: Cycles tab is visible again and the cycle
        filter slider's range is correct after the `Cycle number` →
        `Cycle count` column rename.
      * Measurements of type `properties` or `file` now show an
        informational alert pointing to the details panel or the SDK
        instead of rendering empty time-series tabs.
    </Accordion>

    <Accordion title="Pipeline">
      **Improvements**

      * `ionworks-schema` is now the single validation boundary for parser
        inputs across the pipeline, improving consistency between the SDK's
        schema classes and pipeline execution.
      * Standardized user-facing optimizer kwargs across all fitting
        backends: `max_iterations` replaces older per-backend names, and
        `population_size` replaces `popsize` on the differential evolution
        optimizer. Old names continue to work with a `DeprecationWarning`.
      * A transient protocol solver failure during differential evolution now
        lands on the finite-penalty path instead of killing the optimization.
        Protocol and configuration errors still surface as errors so static
        bugs remain visible.

      **Fixes**

      * `pybamm.Experiment` `period` and `temperature` now round-trip
        correctly through serialization (fix shipped in `pybamm 26.4.3`).
        Experiment schemas accept the new field set (per-step `period`,
        `temperature`, `tags`, `description`, `direction`, `start_time`,
        `skip_ok`; experiment-level `period`, `temperature`, `termination`);
        `duration` also accepts human-readable strings like `"287 seconds"`.
      * SimplePipeline jobs run data fits in-process and now establish their
        own connection to the compute backend, so distributed evaluation
        actually fires; when that connection fails, the fit falls back to
        its in-process path. Legacy element-type labels are now canonicalized
        consistently at ingress.
    </Accordion>

    <Accordion title="Python API">
      **Improvements**

      * `client.simple_pipeline` sub-client for the new SimplePipeline
        workflow.
      * `client.protocol.convert(protocol, target)` returns a
        `ConvertResult` with `primary_bytes`, `text()`, and `save(dir)`
        helpers — exports a UCP YAML protocol to a native vendor file
        (Maccor, Arbin, Neware, BioLogic BT-Test, or Novonix). Maccor returns
        any drive-cycle MWF assets alongside the primary file.
      * `client.job.get_metadata(job_id)` returns the parsed contents of a
        job's metadata blob, giving the SDK access to large validation
        payloads the legacy result endpoint could not reach.
    </Accordion>

    <Accordion title="Protocol Simulator">
      **Improvements**

      * BioLogic `.mps` parser: User Profile (drive cycle) steps are now
        extracted from embedded Urban Profile Tables, or from sibling `.txt`
        files supplied via `additional_content` when the `.mps` lacks
        embedded tables. Current sign is flipped on the way in so positive
        represents discharge for UCP/PyBaMM.
      * Arbin parser rewritten to keep the step list flat with raw gotos
        instead of inferring loops from backward-goto patterns. Fixes
        sibling backward gotos to the same target, cross-loop goto
        resolution, and digit-bearing formula labels like
        `F_EIS_10%_capacity_change`. Pause steps emit UCP's first-class
        auxiliary `Pause` step.
      * More Arbin / Maccor step types recognized:
        Arbin `Internal Resistance` → `Rest` with a `UserWarning`,
        additional Arbin step variants mapped to their UCP types,
        bracketed `MV_UD[n]` normalised, leading-negative current
        expressions classified as `Discharge`. Maccor `User Def CYCLE <op> N`
        translated to a UCP `VariableEnd` against the runtime `CYCLE` alias.
      * Per-step overhead trimmed substantially on long protocols, speeding
        up simulation of protocols with many steps.
      * Solver failures are now distinguished from protocol and configuration
        errors, which keep their original error types and gain step context.

      **Fixes**

      * Real Maccor `.MWF` exports that include a multi-line preamble plus
        a header row now parse correctly. Files containing only data rows
        still parse unchanged.
    </Accordion>

    <Accordion title="Skills">
      **Improvements**

      * New `run-simple-pipelines` skill walks through the SimplePipeline
        client end-to-end.
      * `process-data`: clarified that `protocol` holds test conditions that
        affect the electrochemical outcome (temperature, C-rate, SoC, DoD,
        pressure) while `test_setup` holds physical logistics (cycler model,
        operator, lab, channel) that do not. `test_setup` lives only on
        measurements, not on cell instances.
      * `process-data`: `set_step_count` with a step column is now the
        unambiguous default, so decreasing / repeating step ids from GITT or
        RPT-with-substeps work the same as monotonic ones; the sign-based
        fallback is reframed as a fallback for when no step column exists at
        all. Added a caveat for cyclers that emit duplicate `Time [s]` rows
        at step transitions.
      * `process-data`: mandatory header-audit step codifies eight rules
        (walk every file, group by cohort × column-set, classify
        Standard / Auxiliary / Drop, diff reader output, preserve aux
        columns, keep multi-thermocouple channels separate, confirm units /
        sign per cohort, surface missing-temperature as a finding) and a
        required confirmation-report shape, so silent column drops between
        cycler families are caught before any standardized parquet is
        written.
    </Accordion>
  </AccordionGroup>
</Update>

<Update label="May 11, 2026" description="Custom PyBaMM model + Li-S support, ECM capacity co-optimization, default project for the Python SDK, structured validation issues">
  ## Custom PyBaMM models with Lithium-Sulfur chemistry

  The `/models/upload-custom` endpoint now accepts a `chemistry` field (defaulting
  to `lithium_ion`), and Li-S models get more accurate and robust initialization
  when they run. The `manage-projects` SDK skill documents the full upload
  workflow — `pybamm.Serialise().save_custom_model(filename=...)` → multipart
  upload → `client.model.get(id)` returns `is_custom_model: true`.

  ## ECM fit: capacity co-optimization and per-segment initial SoC

  Several interlocking improvements to the project-scoped ECM fit. Supplying an
  `ocv_soc_curve` (and optional `bounds_capacity`) lets you co-optimize cell
  capacity `Q` jointly with the fit instead of pinning `Q` to a single seed; on
  a 25 °C rate-test trace the fitted capacity now lands within 0.9 % of the
  coulomb-counting truth across all knot schedules. `initial_soc` accepts a
  list (one entry per measurement) so multi-measurement fits reset SoC at each
  segment boundary instead of integrating coulombs across the gaps; if you omit
  it, an improved auto-seed routine now estimates each segment's starting SoC
  automatically. `num_knots`, `num_knots_r0`, `knot_schedule`, and
  `clamp_max_ratio` are now first-class parameters on `/fit-from-measurements`
  and `/fit-from-file`. A boundary-clamp default was also loosened, fixing an
  issue where it could collapse the R0 fit and cause solver failures on
  rate-test forward simulations.

  ## Default project for the Python SDK

  The `Ionworks` client now resolves a default `project_id` at construction time
  from a `project_id=` argument or the new `IONWORKS_PROJECT_ID` environment
  variable, so callers no longer have to thread `project_id` through every call.
  The previous `PROJECT_ID` env var still works but emits a `DeprecationWarning`.
  All `client.study.*` methods take `project_id` as an optional keyword
  (after the resource ID) defaulting to the client value, and pipelines and
  optimizations auto-inject it into payloads.

  ## Structured measurement-validation issues

  `MeasurementValidationError.errors` is now `list[ValidationIssue]` — a frozen
  dataclass carrying a stable `IssueCode` (StrEnum), `severity`, human-readable
  `message`, and JSON-native `payload`. Downstream code can branch on check
  identity via `e.has_code(IssueCode.CURRENT_SIGN_REVERSED)` instead of grepping
  the message string. `ionworksdata`'s auto-fix path now keys off the new codes;
  `IssueCode` and `ValidationIssue` are re-exported from the top-level
  `ionworks` package.

  <AccordionGroup>
    <Accordion title="Studio">
      **Improvements**

      * Simulation boards now have a dedicated backend API at
        `/projects/{project_id}/studies/{study_id}/simulation_boards`, fixing a
        blank Visualization tab in some cases.
      * Optimization Performance Detail and Performance Summary tabs now surface
        buried `validation_warning` / `validation_not_supported` issues as
        top-level alerts above the tabs, with info "no data" alerts inside the
        tabs for the rare empty-but-valid case.
      * Defensive UX in the Visualization tab: the Data/Visualization toggle
        stays visible even when no board is available, with a warning alert
        prompting the switch back to Data instead of trapping the user on a
        blank page.

      **Fixes**

      * The single simulation result page no longer flashes "Simulation not
        found" before the data loads on a fresh navigation.
    </Accordion>

    <Accordion title="Pipeline">
      **Improvements**

      * `ionworks-schema` gained `Constraint`, `Penalty`, `CMAESOptions`,
        `PSOOptions`, `DEOptions`, `LatinHypercube`, and `Uniform` schema
        classes, plus improved documentation across objectives, data fits,
        parameter estimators, regularizers, and distribution samplers.

      **Fixes**

      * Fixed an issue where a solver failure on a bad parameter combination
        during a fit could crash the whole datafit instead of being handled
        gracefully. Cloud fits stay alive and the offending sample just gets a
        huge cost.
    </Accordion>

    <Accordion title="Python API">
      **Improvements**

      * New `client.urls.measurement(measurement_id, project_id)` helper
        returns the web app deep link for a measurement, so callers don't have
        to hand-build URLs themselves.
    </Accordion>

    <Accordion title="Skills">
      **Improvements**

      * `manage-projects` documents the `/models/upload-custom` multipart
        workflow and the Model / ParameterizedModel disambiguation.
      * `upload-data` and other validation-aware skills updated to reference
        the new `IssueCode` / `ValidationIssue` API and the
        `e.has_code(...)` pattern instead of substring-matching error strings.
    </Accordion>
  </AccordionGroup>
</Update>

<Update label="May 4, 2026" description="Full optimization experiment editor, Arbin reader, Maccor coverage, UCP input schema">
  ## Full editor for optimization experiments

  Optimization experiments now use the same protocol editor as the rest of the
  app. The bare text field has been replaced with a rich editor featuring YAML
  syntax highlighting, dark-mode support, frontend pre-validation, and the full
  protocol-builder dialog for picking templates and tuning steps. New protocols
  pre-load a "Constant Current Charge" template so users have a working
  starting point.

  ## Iterative metrics for design optimization

  Design optimization now supports `CyclewiseMetric` and `StepwiseMetric`
  wrappers end-to-end. The optimization form lets you target a metric on a
  specific cycle or step with bounded input fields driven by the parsed
  experiment, mix pipeline variables alongside PyBaMM variables, and
  round-trips wrapped metrics through save/load. A long-standing bug where
  repeated protocol blocks were flat-expanded has also been fixed, which broke
  `solution.cycles` indexing for cycle-wise metrics. Two new templates ship: a
  simplified Charge optimization and composite system models.

  ## Arbin cycler support

  `ionworksdata` now reads native Arbin exports — CSV, XLSX, and the binary
  `.res` format. The `.res` reader extracts data directly from Arbin's export
  format (no separate Access database tool required), sorts rows chronologically
  to handle interleaved multi-session recordings, and reads the absolute start
  time from the file's session metadata. Auto-detection picks the right reader
  from file headers, and `arbin res` is also exposed as an explicit reader name.

  ## Maccor protocol coverage

  The Maccor parser and simulator now handle several real-world protocol
  features that previously failed at parse time or during simulation, including
  per-limit safety gotos, `Chg/Dis Func CCCV` step types, and robust variable
  setvar handling. The Maccor `ionworksdata` reader also gained support for the
  compact short-form column header set used by some firmware versions, which
  previously crashed and silently dropped capacity/energy columns.

  ## Machine-checkable UCP input schema

  The discovery endpoint `/discovery/schemas/protocol` now exposes a JSON
  Schema matching the actual YAML authoring format (single-key dicts like
  `{Charge: {...}}`) rather than the internal parsed shape. Parity tests
  round-trip good and bad fixtures through both the schema and the parser so
  they cannot drift. Submitting the legacy `kind:` shape to
  `POST /protocols/validate` now returns a helpful error pointing at the
  canonical YAML examples, and the `discover-api` and `run-simulations` skills
  show local pre-validation via `jsonschema.validate(...)`.

  <AccordionGroup>
    <Accordion title="Studio">
      **Improvements**

      * The Ionworks Agent tab has been replaced with a static instructions page
        pointing to the [Ionworks Agentic Toolkit](https://github.com/ionworks/ionworks-skills);
        the in-app chat agent has been removed in favour of the SKILL.md-based
        workflow.
      * New cell specifications no longer pre-fill a default capacity, so users
        enter the actual cell capacity from the start.

      **Fixes**

      * Storage permissions are now enforced at the organization level so members
        of the same org can read each other's measurement files as expected.
      * `created_by_email` is now consistently populated on cell-spec, cell-instance,
        and cell-measurement responses across both `get` and `list` endpoints.
      * Simulation usage is aggregated at the organization level (matching the
        org-level usage limit that the backend already enforces) and is fetched
        from a dedicated `GET /organizations/current/usage` endpoint.
    </Accordion>

    <Accordion title="Pipeline">
      **Fixes**

      * Half-cell ECM now exposes anode and cathode potential variables
        (`Anode potential [V]`, `Cathode potential [V]`) for plotting and metrics.
      * `get_cycle_metrics` keeps the `Cycle count` column name on output instead
        of renaming it to `Cycle number`, matching the input convention used
        throughout the data pipeline.
    </Accordion>

    <Accordion title="Python API">
      **Improvements**

      * `validate_measurement_data`, `CellMeasurement.create`, and
        `CellMeasurement.create_or_get` accept a `skip_checks` parameter so callers
        can relax a single strict validator (e.g. `time_gaps`) instead of disabling
        strict mode wholesale. Unknown check names raise `ValueError`, and the
        canonical set is exposed as `ionworks.validators.STRICT_CHECK_NAMES`.
        `validate_strict=True` is now the recommended default.
    </Accordion>

    <Accordion title="Data Processing">
      **Improvements**

      * New Arbin reader covering CSV, XLSX, and native `.res` exports (see the
        highlight above).
      * Maccor reader now accepts the compact short-form column header set used
        by some cycler firmware versions.
    </Accordion>

    <Accordion title="Documentation">
      **Improvements**

      * New electrolyte parameterization page with a worked Landesfeind fit
        example.
      * Optimization experiment editor, iterative metrics, simplified Charge
        template, and composite system models are documented.
      * Custom variables reference now documents anode/cathode potential
        exposure on the half-cell ECM (English and Japanese).
      * Maccor native `CCCV` step type is documented (English and Japanese).
      * Arbin is listed in the supported cyclers table.
      * SEO metadata (keywords, OG tags, tightened descriptions) added across
        the docs site, including expanded data-fitting guide descriptions.
    </Accordion>

    <Accordion title="Skills">
      **Improvements**

      * Each mirrored package (`ionworksdata`, `ionworks-schema`, `ionworks-api`,
        `iwutil`, `ionworkspipeline`, `skills`) now ships a per-package
        `CHANGELOG.md` in Keep-a-Changelog format, written and validated as part
        of the release workflows.
      * `discover-api` and `run-simulations` skills updated to reference the new
        UCP input JSON Schema and demonstrate local pre-validation.
      * `upload-data` skill updated to recommend `validate_strict=True` and
        document the new `skip_checks` parameter.
    </Accordion>
  </AccordionGroup>
</Update>

<Update label="April 27, 2026" description="Project-scoped ECM fitting, PyBaMM v26.4.0 support, SDK skills plugin, strict upload validators">
  ## Project-scoped ECM fitting

  Equivalent-circuit-model fitting is now available directly inside a project. Pick any
  measurement already attached to one of the project's cells (or upload a fresh CSV), preview the
  trace, run the fit, and save the result back to the project as a new model with one click. The
  new flow adds a model-vs-data plot, an error plot, a fitting-progress indicator, an OCV toggle
  helper, and auto-scrolls to the results when the fit completes. The standalone ECM demo continues
  to work for unauthenticated users.

  ## PyBaMM v26.4.0 support

  The simulation engine has been updated for PyBaMM v26.4.0, which introduces a dedicated `Rest`
  step class in place of the old zero-current step and renames the MSMR electrode-capacity
  parameters from short keys (e.g. `Q_n_1`, `Q_p_1`) to descriptive strings (e.g. "Negative
  electrode host site occupancy capacity (1) \[A.h]"). Existing experiments and MSMR parameter sets
  continue to parse correctly under the new release.

  ## SDK skills as a Claude Code plugin

  The Ionworks Python SDK now ships with a set of installable Claude Code skills covering
  api-discovery, cell-data, data-upload, simulations, pipelines, and projects-and-studies. Each
  skill documents the relevant sub-clients, method signatures, and the create-or-get patterns so
  an AI assistant can drive the SDK against the current API surface. Install via
  `/plugin marketplace add ionworks/ionworks-skills` and `/plugin install ionworks` to get the
  slash commands and SessionStart hook for any Ionworks project.

  ## Strict upload validators in the Python API

  `CellMeasurementClient.create` and `create_or_get` now run optional client-side validators
  before sending data to Studio so processing bugs surface as a local error instead of a confusing
  upload result. A hard time-gap check (>5 h between consecutive rows) runs by default; passing
  `voltage_window` enables a voltage-continuity check (catches chronological misordering from a
  faulty data split), and passing `rated_capacity` enables a consecutive same-direction full-step
  check plus a soft warning for any step whose capacity exceeds 5× rated.

  <AccordionGroup>
    <Accordion title="Studio">
      **Improvements**

      * Measurement chart controls collapse into a compact header summary; per-axis variable
        selectors now allow adding and removing series dynamically with a unified two-column layout.

      **Fixes**

      * Study visualization no longer collapses to an empty state when switching between studies whose
        experiment-type tabs differ — the filter resets to All when the previous tab isn't present.
      * Users with a stale session can recover by signing out via the sign-in page instead of being
        stuck on the redirect.
      * The empty cells page now uses the correct organization-level permission check, so users who
        can create cells no longer see a misleading "contact a project admin" message.
      * Pipeline element details view no longer triggers rapid duplicate fetches for `Data Fit` and
        `Validation` configs.
    </Accordion>

    <Accordion title="Pipeline">
      **Improvements**

      * Simulations now compile faster by default, speeding up repeated runs that share the same model.
      * Simulation objectives with custom mesh or spatial-method settings (such as `CycleAgeing`) now
        serialise and reload correctly.
    </Accordion>

    <Accordion title="Python API">
      **Fixes**

      * Time-monotonicity validation error message now reports the correct two adjacent values
        (the previous off-by-one showed the values just before the actual violation).
    </Accordion>

    <Accordion title="Data Processing">
      **Fixes**

      * Sign-convention detection no longer misclassifies low-current pulse datasets as all-rest;
        the rest threshold now scales relative to the 95th-percentile current so violations are
        caught on small-amplitude data.
    </Accordion>
  </AccordionGroup>
</Update>

<Update label="April 20, 2026" description="Python SDK resource clients, validation initial conditions, capacity calculation fix">
  ## Python SDK resource clients

  The Python SDK gains typed sub-clients for managing Studio resources programmatically. You can now
  create, list, retrieve, update, and delete projects, models, parameterized models, studies,
  protocols, and optimizations directly from the `Ionworks` client — for example, `client.project.list()`,
  `client.model.get(id)`, or `client.study.create(...)`. A new "Managing resources" section in the
  Python API docs walks through each sub-client with usage examples, and requests for Projects,
  Models, and Studies no longer require your organization to be specified separately — it's resolved
  from your account automatically.

  ## Validation initial conditions and UX polish

  Validations now let you choose how the simulation is initialized: auto-detect from the measurement,
  a custom starting voltage, or a custom state of charge. Each validation row in the Report tab can
  be removed individually with a confirmation dialog, and a dedup bug that caused two measurements
  sharing the same initial voltage to overwrite each other's drive cycle has been fixed. Validation
  error plots also now render with grid lines for easier reading.

  ## Capacity calculation fix for multi-electrode cells

  A capacity calculation was reading a non-canonical parameter name for the number of electrodes
  connected in parallel, causing the maximum concentration to be over-computed by a factor of N when
  users set the correct key. The fix aligns all lookups with PyBaMM's canonical parameter name so
  multi-electrode cells parameterize correctly.

  <AccordionGroup>
    <Accordion title="Studio">
      **Improvements**

      * Studies with simulations of a single experiment type now auto-select that type so the visualization
        view is immediately accessible.
      * Failed variable-evaluation jobs now surface an error state with a Retry button instead of spinning
        indefinitely.
      * Studies list and parameterized models list now support pagination.

      **Fixes**

      * Fixed a crash when rendering time-series measurements with thousands of short steps (e.g. HPPC
        pulse protocols with \~1500 steps) — the dashboard can now load these measurements.
      * Fixed coupled custom variables being silently dropped when their resolution failed, which could
        remove convenience variables like "Temperature \[degC]" from simulation outputs.
      * Fixed an issue where an overly large page size on the models list could cause an error.
    </Accordion>

    <Accordion title="Pipeline">
      **Improvements**

      * Bumped PyBaMM to 26.3.1, which falls back to a base model with a warning when a custom
        model references a package that isn't installed in the run environment.
      * Improved reliability of OCP-related fitting objectives so they work correctly in Validation
        pipelines.

      **Fixes**

      * Fixed an issue where a data fit submitted with a single objective could fail unexpectedly.
    </Accordion>

    <Accordion title="Python API">
      **Improvements**

      * Added typed sub-clients for Models, Studies, Optimizations, Projects, Protocols, and
        ParameterizedModels, replacing raw HTTP requests for resource management.
      * Requests no longer require your organization to be specified in resource paths — it's resolved
        from your account automatically.
      * Simulation polling now propagates errors immediately instead of swallowing them, and uses typed
        job status objects with clearer completion/failure fields.

      **Fixes**

      * Fixed the simulation job poll endpoint, which was pointing at an incorrect route.
    </Accordion>

    <Accordion title="Data Processing">
      **Fixes**

      * Fixed a sign-detection bug in the ECM validator where a symmetric current profile (charge /
        discharge / charge returning to the same net charge) was incorrectly rejected despite having a
        non-zero SOC span.
    </Accordion>
  </AccordionGroup>
</Update>

<Update label="April 13, 2026" description="Async optimization, study validation reports, cell data filtering">
  ## Asynchronous optimization evaluation

  Optimizers now support asynchronous evaluation for both local and distributed workloads, keeping all
  workers saturated without waiting for generation boundaries. New convergence criteria — including a
  patience counter and population diversity guards — prevent premature stopping.

  ## Study validation reports

  Studies now include a validation workflow for comparing simulation results against experimental
  measurements. A new Report tab displays overlay plots of simulated vs. measured data along with
  quantitative error metrics (RMSE, MAE), and a Data tab lets you manage which measurements are paired with
  which simulations.

  [Find out more →](/simulate/studies#validation-report)

  ## Cell data filtering and ordering

  All cell list endpoints (specifications, instances, and measurements) now accept filter and ordering
  parameters — including name, creator email, date ranges, and sort direction. The Python SDK exposes
  matching keyword arguments on each `list()` method, and the frontend measurement table uses server-side
  filtering.

  <AccordionGroup>
    <Accordion title="Studio">
      **Improvements**

      * Pipeline and cell measurement tables now support server-side sorting.
      * Added an error screen with auto-retry when the initial user info request fails.
      * Removed SNES optimizer option from the frontend.

      **Fixes**

      * Fixed cross-site scripting issues in the notifications drawer and job progress display.
      * Improved error message consistency across the app.
      * Eliminated slow file-listing calls on file-measurement endpoints by caching filenames, reducing
        response times from \~10 s to under 100 ms.
    </Accordion>

    <Accordion title="Pipeline">
      **Improvements**

      * Added dedicated algorithm test suites for CMA-ES, XNES, and Nelder-Mead.
      * Improved convergence for CMA-ES and XNES by preferring the evaluated distribution mean when it
        outperforms the best sample.

      **Fixes**

      * Fixed a flaky deterministic design optimization test.
    </Accordion>

    <Accordion title="Python API">
      **Improvements**

      * Added filter and ordering keyword arguments to `CellSpecificationClient.list()`,
        `CellInstanceClient.list()`, and `CellMeasurementClient.list()`.
      * `download_files(filenames=)` now skips the listing round-trip; new `get_file()` method for
        single-file fetch.
    </Accordion>

    <Accordion title="Data Processing">
      **Improvements**

      * Added temperature column recognition for Biologic files.
    </Accordion>
  </AccordionGroup>
</Update>

<Update label="April 6, 2026" description="Measurement types, performance improvements, total time termination, parameterized model enhancements">
  ## Measurement types for non-time-series data

  Cell measurements now support a `measurement_type` field with three values: `time_series` (the
  default), `properties` for key-value metadata such as checkpoint measurements, and `file` for arbitrary
  files such as images, PDFs, or numpy arrays. Each type has its own creation and retrieval flow, and
  list endpoints can filter by type.

  [Find out more →](/data/overview#measurement-types)

  ## Performance improvements

  Pipeline creation is now significantly faster, and the platform handles concurrent load with improved
  throughput. Models, parameterized models, studies, and optimizations now use server-side pagination and
  filtering, eliminating the need to load entire collections into memory.

  ## Total time termination condition

  Protocol steps can now use `total_time` as a built-in termination condition, ending a step after a
  specified duration of total elapsed experiment time rather than just step time.

  [Find out more →](/simulate/simulating-commercial-protocols#total-time)

  ## Parameterized model improvements

  The parameterized model detail view has been consolidated into a single page with tabs, replacing the
  previous multi-page layout. Models can now be downloaded as a zip archive containing the full
  configuration, and initial temperature is now correctly accounted for in design optimization objectives
  for temperature-dependent studies.

  [Find out more →](/build/parameterized-models)

  <AccordionGroup>
    <Accordion title="Studio">
      **Improvements**

      * Cell specification list now displays as a sortable data table instead of cards.
      * Added a UI warning when a simulation produces no data because all protocol steps were skipped.
      * Removed hardcoded convenience variables from the variable evaluator and improved the evaluate
        variables UX.
      * All update requests now use partial update semantics.
      * Standardized all duplicate resource errors to return HTTP 409 with structured error details.
      * Replaced signed URL downloads with HTTP 307 redirects for simpler, faster file access.
      * Flattened cell measurement composite response shapes for a more consistent API surface.
      * Design optimizations now default to the Differential Evolution algorithm.

      **Fixes**

      * Fixed optimization deletion hitting the wrong API endpoint.
      * Fixed clone optimization sending a reverted request body.
      * Fixed optimization list page sending redundant API requests.
    </Accordion>

    <Accordion title="Pipeline">
      **Improvements**

      * Initial temperature is now correctly parsed for temperature-dependent optimization studies.

      **Fixes**

      * Fixed fitted parameter dictionaries occasionally including an extraneous internal entry.
      * Fixed validation to correctly handle certain transformed parameters.
      * Fixed initial SOC not being passed to EIS frequency-domain simulations.
    </Accordion>

    <Accordion title="Protocol Simulator">
      **Improvements**

      * Added support for arithmetic expressions with input parameters when converting protocols for
        simulation (e.g. `1000 / input["Total cells"]` now produces correct results).

      **Fixes**

      * Fixed initial SOC not being applied in EIS frequency-domain simulations.
    </Accordion>

    <Accordion title="Python API">
      **Improvements**

      * Replaced signed URL downloads with direct HTTP 307 redirects for measurement file access.
      * Flattened cell measurement response shapes for simpler data access.
      * Added `measurement_type` field to measurement models for non-time-series data.
      * All update methods now use partial update semantics.
      * Improved loading of studies and parameterized models with large numbers of simulations via
        server-side pagination.
    </Accordion>

    <Accordion title="Data Processing">
      **Improvements**

      * Faster, more portable local caching.
      * Added Latin-1 encoding support for Neware CSV files.
    </Accordion>
  </AccordionGroup>
</Update>

<Update label="March 30, 2026" description="ECM parameterization, resistance scaling, custom variables, and BaSyTec reader">
  ## ECM parameterization

  A new ECM parameterization page lets you upload cycling data, select 0–5 RC pairs with a live circuit
  diagram, and view fitted parameters including OCV and R0. Results can be downloaded as CSV.

  [Find out more →](/build/ecm-parameterization)

  ## Adjust resistance in protocol simulations

  The protocol simulator now uses Equivalent Circuit Models (ECM) instead of SPM for faster, more robust
  cycler protocol simulations. ECM parameter sets are available for all six supported chemistries, and a
  new resistance scaling parameter in the UI lets you adjust the overall cell resistance before running a
  simulation.

  [Find out more →](/simulate/simulating-commercial-protocols)

  ## Custom variables on models

  You can now define custom derived quantities on models — such as electrode potentials or temperature in
  different units — as PyBaMM expressions stored in the model configuration. These custom variables are
  evaluated at simulation time and included in result data, making it easy to track application-specific
  metrics across design sweeps.

  [Find out more →](/build/custom-variables)

  ## BaSyTec battery cycler reader

  Data processing now supports BaSyTec CSV exports (CTS, X50 series). The reader
  auto-detects BaSyTec files by header signature, parses `HH:MM:SS.sss` timestamps (including values
  above 24 hours), applies the correct current sign convention, and extracts start times from companion
  `_meta.txt` files.

  [Find out more →](/data/format#supported-cycler-formats)

  <AccordionGroup>
    <Accordion title="Studio">
      **Improvements**

      * Added dark mode with a theme toggle in the dashboard header.
      * Moved optimization templates from organization scope to project scope with project-level management
        pages.
      * Made optimization name optional when creating optimizations.
      * Added pagination to cell specification, instance, and measurement list endpoints.
      * Added OCV traces to drive cycle simulation result plots.
      * Unified EIS column naming to `Z_Re [Ohm]` / `Z_Im [Ohm]` across simulation, measurement ingestion,
        and frontend rendering.

      **Fixes**

      * Fixed `LumpedSPMR` model crash due to a missing internal reference.
      * Fixed an issue where datafit setup configuration could be mutated between runs.
    </Accordion>

    <Accordion title="Pipeline">
      **Improvements**

      * Added support for computing lithium inventory from maximum stoichiometries without requiring maximum
        concentration values.
      * Adopted PyBaMM's native model and experiment serialization.
      * Added `abs` as a unary operation for composed metrics.

      **Fixes**

      * Fixed thermal model using incorrect heat generation variable in ECM.
      * Fixed trailing space in electrode balancing direction parameter names.
      * Fixed validation to discover sub-parameters inside function-based parameters.
    </Accordion>

    <Accordion title="Protocol Simulator">
      **Improvements**

      * Unified EIS impedance columns to `Z_Re [Ohm]` / `Z_Im [Ohm]` with SI units and standard sign
        convention.

      **Fixes**

      * Fixed CCCV resolution to apply consistently to all sub-steps within a protocol.
    </Accordion>

    <Accordion title="Python API">
      **Improvements**

      * Added local data caching for cell measurements, reducing repeated downloads.
      * Added pagination support (`limit`/`offset`) to cell list methods, returning a `PaginatedList` with a
        `.total` attribute.
      * Improved sign detection algorithm for measurement current data.
    </Accordion>

    <Accordion title="Data Processing">
      **Improvements**

      * Added BioLogic plain CSV reader for non-MPR exports.
      * Added automatic derivation of `Z_Re` and `Z_Im` from `Z_Mod` and `Z_Phase` when impedance
        components are missing.

      **Fixes**

      * Fixed CSV reader to skip auto-detection for explicitly mapped columns.
      * Fixed plotting bugs in data visualization utilities.
    </Accordion>
  </AccordionGroup>
</Update>

<Update label="March 23, 2026" description="Protocols section, job cancellation, parameterized durations, and optimization management">
  ## Dedicated Protocols section with parameterized input support

  Studio now has a dedicated Protocols section where you can browse, edit, and clone saved experiment
  templates. Each protocol detail page shows the source YAML, a tabbed UCP/human-readable preview, and
  automatically detected input parameters with a generated `parameters_schema`. This makes it easy to
  build reusable, parameterized protocols and simulate them with different input values.

  [Find out more →](/simulate/protocols)

  ## Cancel running jobs from Studio

  You can now cancel pipelines, optimizations, and simulations directly from the UI. Each detail page
  shows a cancel button for in-progress jobs, with optimistic status updates and automatic rollback if
  the cancellation fails. On the backend, cancelling a parent job cascades to all child jobs.

  ## Protocol termination conditions and parameterized durations

  Protocol simulations now support early termination based on variable conditions — useful for ending
  long protocols (e.g. multi-cycle Arbin tests) after a target number of cycles. Duration and
  termination end conditions also accept `input['...']` references, enabling fully parameterized
  experiments such as eVTOL design optimization with variable cruise duration.

  [Find out more →](/simulate/simulating-commercial-protocols#termination-conditions-ends)

  ## Edit and delete optimizations

  Optimization name and description are now editable from the detail page, and you can delete
  optimizations with a confirmation dialog. The experiment-step validation toggle is also exposed as a
  per-objective setting, letting you control whether each objective validates against experiment steps.

  <AccordionGroup>
    <Accordion title="Studio">
      **Improvements**

      * Added cancel buttons for running pipelines, optimizations, and simulations with cascading
        cancellation.
      * Added optimization editing (name and description) and delete with permission checks.
      * Exposed the validate-against-experiment-steps toggle on each optimization objective.
      * Unified table UI across optimizations, protocols, and pipelines — actions behind three-dot menus,
        clickable row names, no more "Actions" column header.
      * Added more plot variables to the protocol simulator results view.
      * Design parameters and experiment conditions are now preserved when rerunning simulations, and
        columns for differing parameters default to visible.

      **Fixes**

      * Fixed 500 error when simulating non-UTF-8 protocol files (e.g. BioLogic `.mps`).
      * Fixed optimization detail page layout issues.
    </Accordion>

    <Accordion title="Pipeline">
      **Improvements**

      * Added support for `input['...']` parameter references in protocol duration and termination end
        conditions.
    </Accordion>

    <Accordion title="Protocol Simulator">
      **Improvements**

      * Added a way to end protocol simulations early when a variable condition is met.
      * Added support for Python-style list repetition (`["step"] * N`) in PyBaMM experiment strings.
      * Added support for cycle-index-based branching in Arbin protocol parsing.

      **Fixes**

      * Fixed decoding of non-UTF-8 protocol files in the standalone simulator.
    </Accordion>

    <Accordion title="Python API">
      **Improvements**

      * Large request payloads (>512 KB) are now compressed automatically, reducing upload sizes
        significantly (e.g. 24.5 MB to 3.7 MB for typical serialized models).
      * Job status fields now use typed enums instead of raw strings.
    </Accordion>
  </AccordionGroup>
</Update>

<Update label="March 16, 2026" description="Protocol Builder launch, stronger optimization guardrails, and better data ingestion">
  ## Protocol Builder is now available in Studio

  Studio now includes a visual Protocol Builder with step editing, drag-and-drop ordering,
  YAML import/export, and backend-backed validation before upload. You can also configure
  global safety limits for current, voltage, and temperature directly in the builder.

  [Find out more →](/simulate/protocol-builder)

  ## Optimization setup is safer and easier to reuse

  You can now clone optimizations and save them as reusable templates. Optimization runs
  also validate that fit parameters are actually used by at least one objective model
  before execution, helping catch invalid configurations earlier.

  ## Data ingestion and model setup got more robust

  This week adds stronger cycler-data handling across formats and improves initialization
  behavior for fitting workflows, including more flexible parameter configuration defaults.

  <AccordionGroup>
    <Accordion title="Studio">
      **Improvements**

      * Added pipeline edit/delete support with row actions, bulk delete, and permission checks.
      * Added a Simulations tab to parameterized model details for quicker navigation and
        management.
      * Added optimization cloning and "save as template" workflows.
      * Added simulation rerun actions and job resubmit support for failed jobs.
      * Added protocol YAML display on simulation result pages with input substitutions.
      * Added source metadata display for direct entry elements in pipeline details.
      * Validation views now surface partial-failure warnings instead of failing silently.
      * Timestamps across key tables now display as absolute datetimes.
      * Standalone and add-result protocol forms now hide initial SOC/temperature inputs when
        those values are explicitly defined in UCP global settings.

      **Fixes**

      * Fixed validation charts so single-point series render visibly.
      * Fixed edge cases in new-user onboarding, including logout and empty-credit handling.
      * Pipeline submission now runs asynchronously to avoid blocking request handling.
    </Accordion>

    <Accordion title="Pipeline">
      **Improvements**

      * Added pre-run checks that reject fit parameters not used by objective models.
      * Fit parameter configs now allow omitted `initial_value` and compute defaults from bounds.
      * OCP balancing now supports GITT workflows with improved interpolation and safeguards.
      * Tuned optimizer defaults for more reliable convergence on real-world data.
      * Improved handling of large datasets during pulse-based fitting workflows.
      * Objective setup now supports better partial-result handling on solver failure paths.

      **Fixes**

      * Fixed piecewise interpolation config roundtripping for 1D/2D direct-entry schemas.
      * Restored support for custom initial-state handling used by ECM and lumped SPMr
        workflows.
    </Accordion>

    <Accordion title="Python API">
      **Improvements**

      * Added validation to block oversized inline time series payloads (>1000 rows) with clear
        guidance to upload measurements and reference `db:` IDs.

      **Fixes**

      * Non-idempotent API calls are no longer retried automatically.
      * Fixed current-sign normalization logic for mixed charge/discharge cycler exports that
        record absolute current values.
    </Accordion>

    <Accordion title="Data Processing">
      **Improvements**

      * Added a Gamry EIS reader with auto-detection for `.dta` and related impedance formats.
      * Improved multi-sheet Neware handling with better timestamp ordering and monotonic time
        reconstruction.
      * Numeric-string columns are now inferred and promoted more reliably during read/clean
        steps.
      * Added support for exporting self-contained inline configurations for local use.

      **Fixes**

      * Fixed BioLogic reader handling for additional file variants.
    </Accordion>
  </AccordionGroup>
</Update>

***

<div className="flex justify-between items-center pt-2">
  <a href="/changelog">← Newer updates</a>
  <a href="/changelog/3">Older updates →</a>
</div>
