---
title: "End-to-End RLCS Demonstration"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{End-to-End RLCS Demonstration}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)
```

## 1. Conceptual Overview

This vignette demonstrates the **Representation-Level Control Surfaces (RLCS)** paradigm in a complete end-to-end pipeline. 

We will simulate:
1.  **A Latent Manifold**: A sequence of embeddings moving smoothly.
2.  **Fault Injection**: Introducing a sudden "shock" (temporal discontinuity) and "noise" (out-of-distribution).
3.  **Sensing**: Applying `reslik` (population), `tcs` (temporal), and `agreement` (cross-view) sensors.
4.  **Control**: Deriving explicit `PROCEED` / `DEFER` / `ABSTAIN` signals.

This illustrates how RLCS catches failure modes that might otherwise propagate silently through an AI system.

## 2. Synthetic Dataset

We generate a sequence of 50 time steps.
*   **Steps 1-20**: Normal operation (Clean).
*   **Step 21**: Shock (Sudden jump).
*   **Steps 22-50**: Recovery (but potentially noisy).

The use of `set.seed(42)` ensures that the generated data and subsequent sensor responses are fully reproducible and deterministic across environments.

```{r setup_data}
set.seed(42)
n_steps <- 50
dim_z <- 5

# 1. Generate latent walk (smooth)
z_clean <- matrix(0, nrow = n_steps, ncol = dim_z)
for (t in 2:n_steps) {
  z_clean[t, ] <- z_clean[t-1, ] + rnorm(dim_z, 0, 0.1)
}

# 2. Inject Faults
z_corrupt <- z_clean
# Shock at t=21
z_corrupt[21, ] <- z_corrupt[21, ] + 5.0 
# Noise burst at t=30
z_corrupt[30, ] <- z_corrupt[30, ] + rnorm(dim_z, 0, 2.0)

```

## 3. Minimal Encoder

We simulate an encoder that projects these latent states into a "feature" space.
Ideally, this would be a neural network. Here, we use a fixed random projection followed by `tanh` to bound the outputs.

```{r encoder}
# Random projection matrix
W <- matrix(rnorm(dim_z * dim_z), nrow = dim_z)

# Encoder function
encode <- function(z) {
  tanh(z %*% W)
}

# Encode the sequences
feat_clean <- encode(z_clean)
feat_corrupt <- encode(z_corrupt)
```

## 4. Reference Statistics

In RLCS, the **ResLik** sensor requires a reference distribution (mean and standard deviation) derived from "known good" population data. We calculate this from the clean sequence.

```{r reference_stats}
ref_mean <- colMeans(feat_clean)
ref_sd <- apply(feat_clean, 2, sd)

# Ensure sd is positive (avoid division by zero)
ref_sd[ref_sd < 1e-6] <- 1.0
```

## 5. Sensors

We now run the RLCS sensor array on the **corrupted** sequence.

### 5.1 ResLik (Population Sensor)

This detects if the current embedding looks like the training set.

```{r sensor_reslik}
library(resLIK)

# We analyze steps 2 to 50 (since TCS needs t-1)
z_test <- feat_corrupt[2:n_steps, ]

res_out <- reslik(z_test, ref_mean = ref_mean, ref_sd = ref_sd)

# Inspect diagnostics
summary(res_out$diagnostics$discrepancy)
```

### 5.2 Temporal Consistency Sensor (TCS)

This detects if the embedding changed too quickly between $t-1$ and $t$.

```{r sensor_tcs}
z_prev <- feat_corrupt[1:(n_steps-1), ]
tcs_out <- tcs(z_test, z_prev)

# We expect a drop in consistency at the shock index (t=21 in original -> index 20 in reduced)
plot(tcs_out$consistency, type='l', main="Temporal Consistency", ylim=c(0,1))
```

### 5.3 Agreement Sensor

This detects if two views of the data agree. We simulate a "backup" sensor that is slightly noisy but generally agrees, except at the shock where it disagrees.

```{r sensor_agreement}
# Create a second view
z_view2 <- z_test + matrix(rnorm(length(z_test), 0, 0.1), ncol=dim_z)

# At the shock (row 20), make view2 disagree completely
z_view2[20, ] <- -z_test[20, ]

agree_out <- agreement(z_test, z_view2)
```

## 6. Control Surface

We feed the diagnostics into the deterministic control surface.

```{r control_surface}
# Using default thresholds
# reslik_max_disc > 3.0 -> ABSTAIN
# tcs_consistency < 0.2 -> DEFER
# agreement < 0.3 -> DEFER

signals <- rlcs_control(res_out, tcs = tcs_out, agreement = agree_out)
```

## 7. Results

Let's examine the distribution of signals generated by the control surface.

```{r results}
table(signals)

# Check the signal at the shock point (t=21 of original -> index 20)
print(paste("Signal at Shock (t=21):", signals[20]))

# Check the signal at the noise burst (t=30 of original -> index 29)
print(paste("Signal at Noise (t=30):", signals[29]))
```

### Interpretation

*   **PROCEED**: Steps where the embedding is consistent with the population and history.
*   **DEFER**: Steps where there is a shock (TCS failure) or disagreement, but the values themselves might be within population bounds (or the logic prioritizes the specific failure mode).
*   **ABSTAIN**: Steps where the embedding is grossly out-of-distribution (ResLik failure).

This demonstrates how RLCS converts complex high-dimensional anomalies into actionable, discrete safety signals.