The Spiking Neural Network Inside DosCom
How does a floating Android creature make behavioral decisions without calling an AI API?
Background: DosCom needed a brain. Not a rulebook — something that could weight multiple signals simultaneously, produce different outputs with similar inputs, and change over time. The answer was a Spiking Neural Network: a Leaky Integrate-and-Fire model ported entirely to Kotlin, running on-device with no ML framework, no TensorFlow Lite, no ONNX. Just math.
How it actually works:
The core is LIFCore — 8 input neurons feeding into 48 hidden neurons. The hidden layer has recurrent connections back into itself (each of the 48 neurons can influence all others), giving the network memory within a single think cycle.
Each neuron maintains a membrane potential — a float that starts at -65 (resting) and climbs toward -50 (threshold) as current flows in:
dv = (vRest - membrane[j] + current) / tau
membrane[j] += dv
if membrane[j] >= vThresh → spike, reset to vRest
When think() is called, the network runs for 150 time steps. Each step, spikes propagate through input weights and recurrent weights, accumulating a spike count per neuron. After 150 steps, those counts multiply through a 48×19 decision layer to produce 19 output scores.
Those 19 scores map to 7 behavioral decisions:
- Outputs 0–5 → mime movement style (walk, slide, staircase, skateboard, balloon, rocket)
- Outputs 6–10 → idle animation
- Outputs 11–14 → toy box selection
- Outputs 15–18 → binary flags (moonwalk, discovery mode, social mode, hyperactive mode)
The 8 inputs it reads:
Battery level, time of day (normalized 0–1 across 24 hours), user activity level, session length, emotional sentiment score from EmotionalMemory, screen position, app category, idle duration.
How it learns (STDP-lite):
When the user reacts positively, learn() is called with a positive reward float. Learning rate scales with reward: lr = 0.01f * reward. For every hidden neuron that fired during the last think cycle — if an input was active when that neuron fired, the weight strengthens. Selected output weights strengthen; unselected ones weaken slightly (0.1× the learning rate). Weights save to brain.json in the app's private storage after each learning event. On next launch the brain loads its previous state.
What makes each install unique:
Weights initialize with gaussian() * 8f for input weights and gaussian() * 0.5f for recurrent weights. This seed is generated fresh on first install and not stored. Two DosComs installed on the same day make different decisions from hour one and diverge further with every interaction. There's no default behavior — only what this specific brain learned on this specific phone.
What was surprising:
The recurrent connections were added almost as an afterthought. The expectation was noise. Instead they add something closer to momentum — the network's previous state influences its next decision in a way that makes behavior feel like it has inertia. It doesn't just react to now. It carries something forward.