SporeLanguage referenceAbout the solverHow it solves
Configurator demo

The configurator that runs on the board

Spore pairs a small, portable solver with SSC (Spore System Configuration), a declarative language for describing which combinations of characteristics a device can legally have. Every value is either committed — a user pick, a policy default, or a live sensor reading — or derived: a domain narrowed by constraints and recomputed fresh on every solve, so sensor input, human input, and inference never fight each other. The solver never touches I/O itself. It decides which combination is legal and what must follow; sensors, actuators, and the UI sit in a thin host around it. It answers legality, not price, BOM, or routing.

The name: a spore is small and self-contained, dormant until it lands somewhere and germinates unmodified - the same idea as one portable engine.c.

A portable solver

engine.c is plain, allocation-free C11. The same file compiles with gcc for a PC, emcc for WebAssembly in the browser, avr-gcc for a microcontroller — a real ATtiny1614 with 2 KB of RAM, 800-byte heap — and the ESP-IDF toolchain for an ESP32-C3.

Committed vs. derived state

A characteristic is either committed (a user pick, a policy default, or a sensor reading) or derived (a domain narrowed by constraints and recomputed fresh on every solve). The split keeps sensor input, human input, and inference from ever fighting each other.

Sensor in, actuator out

A slot marked observed is a live reading — written with no admission gate, because the world cannot be illegal. applied is the opposite direction: the host reads the solver’s answer and drives a relay, LED, or PWM. Unmarked slots are user or policy input.


SSC, at a glance

A characteristic declares a typed slot (SINGLE, MULTI, or RANGE). A class groups them. Constraints narrow what is legal; procedures write values; preconditions hide or require a slot; a variant table is a row-wise fact instead of a hand-written condition.

characteristic MODE {
  names EN "Mode"
  textLength 8
  values
    'ECO' names EN "Eco",
    'COMFORT' names EN "Comfort",
    'BOOST' names EN "Boost"
}

class Thermostat {
  characteristics
    TEMP observed,
    MODE defaultValues ['ECO'],
    FAN noinput
}

constraint fan_high_CS {
  objects:
    ?t is_a Thermostat
  condition:
    ?t.MODE = 'BOOST'
  restrictions:
    ?t.FAN in ['HIGH']
}
Read the full language reference →

Flash once, then just update the KB

On a microcontroller, the compiled .kb.img lives in its own flash slot, separate from the firmware - the solver and its host code don't change when what a device is allowed to configure does. A board only needs flashing once; after that, changing its legal combinations is a KB upload over UART (KB_BEGIN/KB_DATA/KB_END framing, acknowledged chunk by chunk), not a firmware rebuild.


Download the solver

The whole engine is five small, dependency-free C files: engine.c and kb_loader.c, plus the headers they need (engine.h, format.h, kb_schema.h) - the same source this site's own configurator demo compiles to WebAssembly. Also included: a minimal main.c that loads a compiled .kb.img from the command line and prints the settled configuration.

Download spore-0.1.zip

Want the SSC compiler itself (the grammar and kb-emit)? It's not public yet - email mi@mipem.co.