Core
Create an energy engine, set and cycle levels, subscribe to changes, and resolve strategies - no framework required.
The core engine is a small stateful coordinator: it holds the current EnergyState, notifies subscribers on change, and resolves strategies against the current level. It runs in any JS/TS runtime.
Create an engine
import { createEnergyEngine } from '@kumbatio/energy-system'
const engine = createEnergyEngine({ initialLevel: 75 })
engine.getState()
// { level: 75, timestamp: ..., source: 'manual', revision: 0, origin: '...' }All options are optional:
Prop
Type
Set and cycle levels
engine.setLevel(50) // source defaults to 'manual'
engine.setLevel(25, 'scheduled') // or 'inferred'
engine.cycleLevel() // 100 → 75 → 50 → 25 → 0 → 100setLevel() is synchronous for in-memory subscribers. If a persistence adapter is configured, saving happens in the background with bounded exponential backoff.
Subscribe to changes
const unsubscribe = engine.subscribe((state, prev) => {
console.log(`Energy: ${prev.level} -> ${state.level}`)
})
// later
unsubscribe()Listeners receive both the new and previous state. A listener that throws is logged and does not break the others.
Resolve strategies
A strategy is a pure (level) => config mapping. engine.resolve() applies it to the current level:
import {
uiVisibilityStrategy,
taskComplexityStrategy,
} from '@kumbatio/energy-system'
const ui = engine.resolve(uiVisibilityStrategy)
if (!ui.sidebar) hideSidebar()
const tasks = engine.resolve(taskComplexityStrategy)
tasks.maxComplexity // 'routine' at level 50See Strategies for the built-ins and Authoring strategies to write your own.
Persistence and cleanup
import { localStoragePersistence } from '@kumbatio/energy-system/persistence'
const engine = createEnergyEngine({
initialLevel: 75,
persistence: localStoragePersistence(),
})
engine.setLevel(50)
await engine.flush() // wait for durable storage (optional)
engine.dispose() // release subscriptions and observation resourcesflush() rejects if the engine is disposed, or if the unchanged initial state can't be safely written because the hydration read failed - the engine never overwrites storage it couldn't read. Details in Persistence.
Deterministic testing
Inject a clock so tests control time:
let now = 0
const engine = createEnergyEngine({
initialLevel: 100,
clock: () => now,
originId: 'test-engine',
})
engine.setLevel(50)
now += 60_000
engine.setLevel(25)Full engine reference: /docs/api/core.
