--- 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.