Kumbatio
Guides

Upgrading

What each major release of @kumbatio/energy-system breaks, and how to tell whether it breaks you.

Semver for this package covers more than type signatures. A shipped strategy table's values are API: changing what notificationStrategy returns at level 50 changes how every consumer behaves, so it is a major-version change - and a change to the spec, not only to this library. The reconciliation rule is covered the same way, because two implementations must agree on it to share state at all.

Prose returned by describe() and the level descriptions are not covered. Wording is a product decision.

The practical consequence: an upgrade the compiler waves through can still change what your app does. Type-checking a major is necessary and not sufficient. Diff the tables in conformance.json - it ships in the package, one file per version - to see what your users will actually experience.

1.x to 2.0

No type signature changed in 2.0. It is a major because two of its four fixes changed runtime behavior, and one narrowed an install range.

Does it break you?

Three questions. If all three are "no", the upgrade is a version bump.

Are react or @types/react pinned below 19.2?

The React entry point imports <Activity>, added in React 19.2. The old >=19 peer range advertised a compatibility that throws on first render under 19.0 and 19.1 - so this narrowing documents reality rather than creating a break. Raise the pin, or stop importing @kumbatio/energy-system/react.

Do you persist or exchange states carrying properties outside the published schema?

Through 1.x, unknown properties were silently trimmed to fit. They are now rejected, because trimming let two implementations exchange a state and disagree about what they had exchanged. If you were stashing your own fields alongside an EnergyState, move them out of the object - createEnergyState() will now throw rather than quietly drop them.

Fractional timestamps are rejected for the same reason: spec/energy-state.schema.json never allowed them.

Do you depend on a batched notification being delivered after suppression started, or after energy fell below its threshold?

A notification used to be classified once, when published, and an open batch window was then delivered under whatever policy happened to be in force later. So an intent admitted at Steady could arrive in the middle of a focus session, and one batched at Steady could surface at Rest with every channel disabled.

The gate now re-judges everything it is holding whenever energy or suppression changes. Batched intents the current policy no longer admits move to the deferred queue and are released when something admits them. Nothing is dropped - the defer-not-drop guarantee is unchanged - but delivery timing moved, and it moved deliberately.

flush() also no longer bypasses active suppression; it overrides the wait, not the policy.

Also in 2.0

  • A configured originId no longer corrupts the unproduced sentinel. Construction used to stamp the configured producer identity onto the untouched default state, so isUnproducedState() returned false for it and getEnergyMetrics() reported an age measured from the epoch. The sentinel is always origin: "0-initial"; your configured identity owns the first state the engine actually produces.
  • api-surface.json now includes EnergyEngine.resolve(). The declaration parser did not recognise generic members, so a public method was missing from the frozen surface - and a method absent from the freeze is a method nobody notices removing.
  • 2.0.1 changed the Rest level description from "Depleted." to "Recovery." - product copy, not API. "Depleted" describes damage; the level copy is supposed to say what a person can do at a level, not what they cannot.

Upgrading within a major

Minors and patches are additive. Meltemi integrated at 0.4.0 and rode every minor release to 1.0 without touching its integration code, which is the bar the project holds itself to.

To verify an upgrade yourself rather than taking that on trust:

# The exact public surface of each version, as data
npm view @kumbatio/energy-system@1.0.0 dist.tarball

Both api-surface.json and conformance.json ship inside the package and carry the version of the release they belong to, so you can diff two installs directly - surface against surface, table against table. (Through 2.0.4 both files were published with the previous release's version stamp; 2.0.5 fixed that.)

Migrating from a different level scale

Version upgrades are not the same problem as adopting the five-level model when your app already has its own. For that, see Migrating from legacy scales.