Grand Diomande Research · Full HTML Reader

Anticipation

**Version**: 1.1.0 **Last Updated**: 2025-01-01 **Status**: Production **Parent**: [03-ECHELON.md](03-ECHELON.md) **Previous**: [05-SENSOR_FUSION.md](05-SENSOR_FUSION.md) **Next**: [07-GESTURE_RECOGNITION.md](07-GESTURE_RECOGNITION.md) **Crate**: `core/cc-anticipation/` **Tests**: 50 passing

Agents That Account for Themselves architecture technical paper candidate score 40 .md

Full Public Reader

Anticipation

Layer 2: Anticipatory Signal Extraction

Version: 1.1.0
Last Updated: 2025-01-01
Status: Production
Parent: [03-ECHELON.md](03-ECHELON.md)
Previous: [05-SENSOR_FUSION.md](05-SENSOR_FUSION.md)
Next: [07-GESTURE_RECOGNITION.md](07-GESTURE_RECOGNITION.md)
Crate: `core/cc-anticipation/`
Tests: 50 passing

---

Overview

The `cc-anticipation` crate converts stabilized motion windows into anticipatory signals. Unlike reactive systems that trigger on gesture completion, anticipation operates on the pre-completion phase of motion.

Core Concept

This is the key insight of Computational Choreography: we don't wait for motion to complete. We detect when motion becomes irreversible and act on intention rather than completion.

See: [01-COMPUTATIONAL_CHOREOGRAPHY.md](01-COMPUTATIONAL_CHOREOGRAPHY.md) for the philosophical foundation.

---

Core Insight

The key insight of anticipation is that commitment and uncertainty provide a two-dimensional space for proactive decision-making:

CommitmentUncertaintyStateSystem Response
LowHighWaitingMany options, observe
MediumMediumPreparingNarrowing, prepare response
HighLowCommittedMotion locked, execute
HighHighSurprisingUnexpected, adapt quickly

---

Architecture

mermaid
flowchart TB
    subgraph Input [Input]
        MW[MotionWindow]
    end

    subgraph Features [Feature Extraction]
        KF[Kinematic Features]
        LF[Latent Features]
        Fuse[Feature Fusion]
    end

    subgraph Scalars [Scalar Computation]
        C[Commitment]
        U[Uncertainty]
        TP[Transition Pressure]
        RM[Recovery Margin]
        PS[Phase Stiffness]
        N[Novelty]
        S[Stability]
    end

    subgraph Vectors [Vector Outputs]
        RE[Regime Embedding]
        CV[Constraint Vector]
        DS[Derivative Summary]
    end

    subgraph Output [Output]
        AP[AnticipationPacket]
    end

    MW --> KF
    MW --> LF
    KF --> Fuse
    LF --> Fuse
    Fuse --> C
    Fuse --> U
    C --> TP
    U --> TP
    Fuse --> RM
    KF --> PS
    Fuse --> RE
    RE --> N
    LF --> S
    KF --> CV
    Fuse --> DS

    C --> AP
    U --> AP
    TP --> AP
    RM --> AP
    PS --> AP
    N --> AP
    S --> AP
    RE --> AP
    CV --> AP
    DS --> AP

---

Input Contract: MotionWindow

rust
pub struct MotionWindow {
    pub window_id: String,              // Deterministic hash
    pub t_start: f64,                   // Start time (server canonical)
    pub t_end: f64,                     // End time
    pub fps: f32,                       // Frame rate (50 Hz typical)
    pub skeleton_frames: Vec<SkeletonFrame>,
    pub latent_frames: Vec<LatentFrame>,
    pub coverage: f32,                  // Fraction valid [0, 1]
    pub device_offsets: HashMap<String, f64>,
    pub dropped_reason: Option<String>,
}

SkeletonFrame

rust
pub struct SkeletonFrame {
    pub timestamp: f64,
    pub root_position: Vec3,
    pub root_rotation: Quat,
    pub bone_rotations: [Quat; 27],  // MOCOPI_BONE_COUNT
    pub valid: bool,
    pub source_seq: Option<u64>,
}

---

Output Contract: AnticipationPacket

rust
pub struct AnticipationPacket {
    // === Scalars (control-ready) ===

    /// How irreversible the current motion has become [0-1]
    pub commitment: f32,

    /// How many plausible futures remain [0-1]
    pub uncertainty: f32,

    /// Rate at which futures are collapsing [-∞, +∞]
    pub transition_pressure: f32,

    /// Distance to balance/attractor loss [0-1]
    pub recovery_margin: f32,

    /// How locked to internal metronome [0-1]
    pub phase_stiffness: f32,

    /// Distance from recent regimes [0-1]
    pub novelty: f32,

    /// Local stationarity of dynamics [0-1]
    pub stability: f32,

    // === Vectors (query/conditioning) ===

    /// Regime embedding (64-256 dims)
    pub regime_embedding: Vec<f32>,

    /// Constraint vector (~8 dims)
    pub constraint_vector: Vec<f32>,

    /// Derivative summary (~8 dims)
    pub derivative_summary: Vec<f32>,

    // === Provenance ===

    pub window_id: String,
    pub timestamp: f64,
    pub schema_version: String,  // "0.1.0"

    // === Debug ===
    pub debug: Option<DebugTrace>,
}

---

Scalar Computations

Commitment

Commitment measures how irreversible the current motion has become.

Inputs: Uncertainty, constraint vector, fused features

Algorithm:

commitment = 1.0 - uncertainty * (1.0 - constraint_saturation)

Where `constraint_saturation` measures how close to physical limits the body is.

Uncertainty

Uncertainty measures how many plausible continuations remain.

Without neighbors (heuristic):

uncertainty = regime_embedding.variance() * (1.0 - directional_persistence)

With neighbors (MotionPhraseIndex):

dispersion = continuation_dispersion(neighbors)
neighbor_uncertainty = dispersion_to_uncertainty(dispersion)
uncertainty = 0.7 * neighbor_uncertainty + 0.3 * heuristic_uncertainty

Transition Pressure

Rate of uncertainty collapse:

dC = (commitment - prev_commitment) / dt
dU = (uncertainty - prev_uncertainty) / dt
transition_pressure = alpha * dC + (1 - alpha) * (-dU)

Recovery Margin

Distance to instability:

recovery_margin = 1.0 - max(
    balance_violation,
    joint_limit_violation,
    speed_saturation
)

Phase Stiffness

Rhythmic lock:

phase_stiffness = periodicity * (1.0 - angular_jerk)

Novelty

Distance from recent history:

centroid = mean(regime_history)
novelty = clamp(distance(embedding, centroid) / 2.0, 0, 1)

Stability

Local stationarity:

stability = 1.0 - latent_velocity_norm / max_expected_velocity

---

Neighbor-Based Uncertainty (v1)

When a `MotionPhraseIndex` is set, uncertainty uses continuation dispersion:

rust
#[cfg(feature = "neighbors")]
fn compute_uncertainty_with_neighbors(&self, embedding: &[f32]) -> (f32, Option<Vec<String>>) {
    let index = self.phrase_index.as_ref()?;

    // Query k nearest neighbors
    let dispersion = compute_continuation_dispersion(index, embedding, self.k_neighbors);

    if dispersion.neighbor_count == 0 {
        return (heuristic_uncertainty(embedding), None);
    }

    // Convert dispersion to uncertainty
    let neighbor_uncertainty = dispersion_to_uncertainty(&dispersion);

    // Blend with heuristic for stability
    let blend = 0.7 * neighbor_uncertainty + 0.3 * heuristic_uncertainty;

    (blend, Some(neighbor_ids))
}

---

Invariants

IDInvariantEnforcement
INV-001Deterministic replayNo random seeds
INV-003Coverage thresholdReject if coverage < 0.9
INV-004Scalar boundsAll scalars validated
INV-006No hot-path allocationPre-allocated buffers
INV-007Schema versionMust match "0.1.0"

---

Validation

The kernel validates windows before processing:

rust
pub fn validate_window(&self, window: &MotionWindow) -> Result<(), KernelError> {
    // Check skeleton frames for NaN/Inf
    for frame in &window.skeleton_frames {
        if !frame.root_position.is_finite() {
            return Err(KernelError::InvalidSkeletonFrame(...));
        }
        for quat in &frame.bone_rotations {
            if !quat.is_finite() {
                return Err(KernelError::InvalidSkeletonFrame(...));
            }
        }
    }

    // Check latent frames for NaN/Inf
    for frame in &window.latent_frames {
        for &v in &frame.z {
            if !v.is_finite() {
                return Err(KernelError::InvalidLatentFrame(...));
            }
        }
    }

    // Check time bounds
    if window.t_end <= window.t_start {
        return Err(KernelError::InvalidConfig(...));
    }

    Ok(())
}

---

Configuration

rust
pub struct AnticipationConfig {
    /// Minimum coverage to process [0, 1]
    pub min_coverage: f32,              // 0.9

    /// Regime embedding dimension
    pub regime_embedding_dim: usize,    // 64

    /// Constraint vector dimension
    pub constraint_vector_dim: usize,   // 8

    /// Derivative summary dimension
    pub derivative_summary_dim: usize,  // 8

    /// Transition pressure smoothing
    pub transition_pressure_alpha: f32, // 0.3

    /// Emit debug traces
    pub emit_debug: bool,               // false
}

---

Performance

MetricTargetEnforcement
Latency< 2msPre-allocated buffers
Allocations0Ring buffer history
Memory< 1MBFixed-size structures

---

AUDIT FINDINGS

FindingSeverityStatusNotes
MOCOPI_BONE_COUNT = 27InfoCorrectBones 0-26 inclusive
Quaternion validationPassNaN/Inf checked
Coverage thresholdPassRejects < 0.9
Schema versioningPass"0.1.0" enforced
Neighbor blendingNoteConsider70/30 blend could be tunable

---

Future Work

1. Learned embeddings: Replace projection with trained encoder
2. Multi-scale windows: Different time horizons
3. Attractor prediction: Predict likely attractors from uncertainty
4. Gesture priming: Use anticipation to prime gesture classifier

---

Further Reading

  • [05-SENSOR_FUSION.md](05-SENSOR_FUSION.md) - Input stage
  • [07-GESTURE_RECOGNITION.md](07-GESTURE_RECOGNITION.md) - Consumer
  • [13-DATA_CONTRACTS.md](13-DATA_CONTRACTS.md) - Frozen schemas

Promotion Decision

Promote into a technical note or architecture paper with implementation anchors.

Source Anchor

Comp-Core/docs/architecture/06-ANTICIPATION.md

Detected Structure

Method · Evaluation · Architecture