README.md

# viva_emotion

[![CI](https://github.com/gabrielmaialva33/viva_emotion/actions/workflows/ci.yml/badge.svg)](https://github.com/gabrielmaialva33/viva_emotion/actions)
[![Package Version](https://img.shields.io/hexpm/v/viva_emotion)](https://hex.pm/packages/viva_emotion)
[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/viva_emotion/)

Type-safe emotional core for digital consciousness. PAD model, Ornstein-Uhlenbeck dynamics, and Cusp catastrophe - all with exhaustive pattern matching.

## Installation

```sh
gleam add viva_emotion@1
```

## Quick Start

```gleam
import viva_emotion
import viva_emotion/stimulus
import viva_emotion/emotion

pub fn main() {
  // Create emotional state
  let state = viva_emotion.new()

  // Feel success
  let state = viva_emotion.feel(state, stimulus.Success, 1.0)

  // Evolve over time
  let #(state, jumped) = viva_emotion.tick(state, 0.1)

  // Classify current emotion
  let classified = viva_emotion.classify(state)
  // classified.emotion == emotion.Joy
}
```

## Features

- **PAD Model**: Pleasure-Arousal-Dominance emotional space (Mehrabian 1996)
- **Exhaustive Stimuli**: 14 stimulus types with compile-time coverage
- **O-U Dynamics**: Ornstein-Uhlenbeck mean-reverting process
- **Cusp Catastrophe**: Sudden emotional transitions under stress
- **Emotion Fusion**: Combine Need, Past, and Personality sources (Borotschnig 2025)
- **Long-term Mood**: Exponential Moving Average for emotional stability
- **Big Bounce**: Mood continuity across death/rebirth cycles
- **Configurable Personality**: Custom thresholds, weights, and dynamics

## Platform Support

This library targets the Erlang platform and is compatible with:

- Erlang/OTP 26 and higher
- Gleam 1.4.0 and higher

## Personality Configuration

```gleam
import viva_emotion
import viva_emotion/dynamics
import viva_emotion/emotion
import viva_emotion/stimulus
import viva_emotion/pad

// Anxious personality: lower threshold for existential states
let anxious_classification = emotion.ClassificationConfig(
  high_threshold: 0.2,
  low_threshold: -0.2,
  existential_arousal: 0.5,  // Triggers easier
  existential_pleasure: -0.2,
)

// Stoic personality: rejection hurts less
let stoic_weights = stimulus.default_weights()
  |> stimulus.weight(stimulus.Rejection, pad.new(-0.1, 0.1, 0.0))

// Volatile personality: easier cusp triggers
let volatile_dynamics = dynamics.DynamicsConfig(
  ..dynamics.default_config(),
  cusp_dominance_trigger: -0.1,
  cusp_flip_pleasure_damp: 0.95,
)

// Combine into full personality
let anxious_viva = viva_emotion.with_full_config(
  pad.new(-0.1, 0.2, -0.1),  // baseline
  volatile_dynamics,
  anxious_classification,
  stoic_weights,
)
```

## Emotion Fusion

Combine multiple emotional sources with adaptive weighting:

```gleam
import viva_emotion
import viva_emotion/fusion
import viva_emotion/pad

// Need-based emotion (from interoception/hardware)
let need = pad.new(-0.3, 0.4, -0.2)

// Past-based emotion (from memory retrieval)
let past = pad.new(0.2, 0.1, 0.3)

// Context for adaptive weights
let context = fusion.FusionContext(
  arousal: 0.4,     // Current arousal → affects need weight
  confidence: 0.7,  // Memory confidence → affects past weight
  novelty: 0.3,     // Situation novelty → affects personality weight
)

// Fuse sources
let state = viva_emotion.new()
let state = viva_emotion.fuse(state, need, past, context)

// Check for emotional conflict
let has_conflict = viva_emotion.has_emotional_conflict(state, need, past)
let coherence = viva_emotion.emotional_coherence(state, need, past)
```

## Long-term Mood

Track mood over time with Exponential Moving Average:

```gleam
import viva_emotion
import viva_emotion/mood
import viva_emotion/stimulus

// Create state with mood tracking
let state = viva_emotion.new_with_mood()

// Feel emotions and update mood
let state = viva_emotion.EmotionalStateWithMood(
  ..state,
  emotion: viva_emotion.feel(state.emotion, stimulus.Success, 1.0),
)
let state = viva_emotion.update_mood(state)

// Check mood
let is_happy = viva_emotion.mood_is_positive(state)
let valence = viva_emotion.mood_valence(state)

// Big Bounce: carry mood across death (80% decay)
let reborn = viva_emotion.bounce_mood(state, 0.8)
```

## Stochastic Mode

Inject external entropy for organic emotional evolution:

```gleam
// Get noise from Rust/hardware
let noise = pad.new(random_p, random_a, random_d)

// Stochastic tick
let #(state, jumped) = viva_emotion.tick_with_noise(state, 0.1, noise)

// Deterministic mode (for testing/replay)
let #(state, jumped) = viva_emotion.tick_with_noise(state, 0.1, pad.neutral())
```

## Development

```sh
gleam test        # Run tests
gleam format src test  # Format code
gleam build       # Build
```

## Community

For questions and discussions, check:

- [GitHub Issues](https://github.com/gabrielmaialva33/viva_emotion/issues)
- [VIVA Project](https://github.com/gabrielmaialva33/viva)

## License

MIT - see [LICENSE](LICENSE) for details.