Kumbatio
Concepts

Energy State

The immutable, revisioned EnergyState object, energy sources, and how concurrent writes reconcile deterministically.

EnergyState is a frozen, point-in-time snapshot of cognitive capacity. Every field exists so that two contexts (tabs, workers, devices) looking at the same storage can agree on which state wins - deterministically.

The shape

interface EnergyState {
  readonly level: EnergyLevel     // 0 | 25 | 50 | 75 | 100
  readonly timestamp: number      // when it was set (epoch ms)
  readonly source: EnergySource   // how it was determined
  readonly revision: number       // logical sequence for same-timestamp writes
  readonly origin: string         // stable identity of the producing engine
}

States are immutable - the engine never mutates one, it replaces it. createEnergyState() validates every field and freezes the result.

EnergySource

source records how the level was determined, not just what it is:

SourceMeaningReconciliation priority
'manual'The user set it themselvesHighest
'scheduled'An automation applied a pre-set curveMiddle
'inferred'Derived from observation (e.g. the DOM adapter)Lowest

The priority ordering encodes a principle: a human's explicit statement about their own capacity outranks anything the software guessed.

Why revision and origin exist

Two writes can share a wall-clock timestamp - a fast double-tap, or a deterministic test clock that doesn't advance. revision is a logical counter that breaks the tie: local writes advance it when the clock does not advance. origin is a stable per-engine identity (a UUID by default) that breaks the tie when even revisions match, so every context converges on the same winner without coordination.

Reconciliation ordering

When the engine receives an external state (from hydration or a persistence observe callback), it accepts it only if the candidate is preferred over the current state. Preference is checked in strict order:

  1. Timestamp - later wins
  2. Revision - higher wins
  3. Source priority - manual beats scheduled beats inferred
  4. Origin - lexicographically greater wins (arbitrary but deterministic)

Every context applies the same rules, so concurrent writers always converge.

External states are validated strictly before reconciliation: a legal level and source, a finite non-negative timestamp, a non-negative safe-integer revision, and a non-empty origin. Invalid records are ignored, never repaired - a corrupted record must not be promoted into a more authoritative state.

Clock-skew protection

A context with a badly wrong clock could stamp states far in the future and win reconciliation until real time catches up. The engine rejects hydrated or observed states stamped more than maxFutureSkewMs ahead of the local clock (default 5 minutes). Pass Number.POSITIVE_INFINITY to accept any finite timestamp.

const engine = createEnergyEngine({
  persistence: localStoragePersistence(),
  maxFutureSkewMs: 60_000, // tolerate at most 1 minute of future skew
})

Derived metrics

getEnergyMetrics(state, now?) computes app-agnostic guidance from a state snapshot - no separate logging system required:

import { getEnergyMetrics } from '@kumbatio/energy-system'

const metrics = getEnergyMetrics(engine.getState())
metrics.stateAgeMinutes                    // staleness: "you set this 3 hours ago"
metrics.expectedProductivityWindowMinutes  // 120 / 90 / 45 / 25 / 0 by level
metrics.suggestedBreakIntervalMinutes      // 0 at rest - rest is already a break
metrics.recommendedTaskComplexity          // from the level's cognitive profile
metrics.sustainable                        // true only for 25/50/75 - peak depletes, rest recovers
metrics.recoveryHintMinutes                // present at 50/25/0 only

Focus sessions use these metrics for their energy-derived defaults.

  • Levels - what each of the five values means
  • Persistence - where states are stored and how hydration works