mirror of
https://github.com/SHOGGOTH-SECTOR/sica-fondt.git
synced 2026-08-01 16:40:24 +00:00
etr(R): re-port driver_etr.R to the five-zone torus (kill disowned port)
Replaces the Euclidean-magnitude R port (DREAD/BLUR/INCOHERENT, inverted Z-path) with a faithful native port of etr.m: three independent toroidal axes, five zones, snap-across flips, basin spring toward centre 26 (SOFT 0.25 / INCOH 0.5), L6 Z-path corrected (z<0 alimentation/lattice, z>=0 transmutation/evolution). Drive-Box now renders per-axis ETR status. R suite green (etr 31, drive_box 34) and Octave 26/0/1; both pinned to etr_invariants.md. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015hmgREHNsxYCuim33yUF2c
This commit is contained in:
parent
e9088c98c9
commit
7117d61386
@ -27,7 +27,9 @@ implemented and tested, incl. L7 snap-flips. Full law + status in
|
||||
|
||||
## 3. Language & location
|
||||
GNU Octave · `src/endocrine/etr/` (`etr.m`, `test_etr.m`, `run_etr_tests.sh`, `etr_invariants.md`).
|
||||
R wrapper `src/endocrine/driver_etr.R` bridges into the Drive-Box.
|
||||
R port `src/endocrine/driver_etr.R` (+ `test_etr.R`) feeds the Drive-Box — a **faithful native port**
|
||||
of `etr.m` (five-zone torus, per-axis), pinned to the same invariants doc. The disowned Euclidean-
|
||||
magnitude port is gone. A single-source R↔Octave IPC bridge is still optional/future (transport C1).
|
||||
|
||||
## 4. Does / does-not
|
||||
- **Does:** hold the point; wrap each axis at ±50; apply per-axis restoring toward [17,35]; take
|
||||
@ -54,8 +56,11 @@ L4 AI-drift C4 · L5 cross-axis coupling via stress C1 · L6 Z-path C3 · L7 sna
|
||||
|
||||
## 8. Build steps (remaining)
|
||||
1. ~~Fit the restoring force~~ **DONE** — five-zone law (SOFT/INCOH gains + snap landings) green; L7 + L8 realised.
|
||||
2. Define **L5** coupling (the stress→cross-axis mapping; G1) → replace the identity stub (the lone PEND).
|
||||
3. Wire R↔Octave (driver_etr.R ↔ etr.m) for the Drive-Box (A1) — and the larger medium (D2).
|
||||
2. ~~Reconcile the R port~~ **DONE** — `driver_etr.R` is now a faithful native port of `etr.m`
|
||||
(five-zone, per-axis, L6 Z-path corrected); R suite + drive-box green.
|
||||
3. Define **L5** coupling (the stress→cross-axis mapping; G1) → replace the identity stub (the lone PEND).
|
||||
4. *(optional/future)* collapse the dual R+Octave implementations via an R↔Octave IPC bridge once the
|
||||
transport (C1, shared with A1/C3/D2) is decided.
|
||||
|
||||
## 9. Tests
|
||||
`bash src/endocrine/etr/run_etr_tests.sh` (now **26/0/1** — the lone PEND is L5 active coupling).
|
||||
|
||||
@ -39,7 +39,7 @@ drive_snapshot <- function(state) {
|
||||
alive = is_alive(state$energy),
|
||||
existential_load = reality$existential_load,
|
||||
arguments = reality$arguments,
|
||||
etr_status = evaluate_status(state$etr),
|
||||
etr_status = paste(etr_status(state$etr), collapse = "/"),
|
||||
update_path = determine_system_update_path(state$etr)
|
||||
)
|
||||
}
|
||||
@ -89,7 +89,7 @@ drive_box_evaluate <- function(state, action_tags = character(0),
|
||||
true_cost = true_cost,
|
||||
existential_load = ps_load,
|
||||
eth_penalty = eth_penalty,
|
||||
etr_status = evaluate_status(state$etr),
|
||||
etr_status = paste(etr_status(state$etr), collapse = "/"),
|
||||
update_path = determine_system_update_path(state$etr),
|
||||
arguments = reality$arguments
|
||||
)
|
||||
|
||||
@ -1,65 +1,118 @@
|
||||
# --- High-Fidelity Implementation for Driver 4: Existential Temporality Relief (ETR) ---
|
||||
# --- Driver 4: Existential Temporality Relief (ETR) — R port of the torus ---
|
||||
#
|
||||
# ETR situates the Drive-Box within a 3-axis temporality space. The agent's
|
||||
# position is a coordinate (X, Y, Z) whose distance from the origin (the
|
||||
# magnitude) maps onto an existential status band, while the Z-axis selects the
|
||||
# system's generative update path. Movement through the space wraps toroidally
|
||||
# so the agent can never leave the bounded temporal manifold.
|
||||
# ETR is a SINGLE POINT on three INDEPENDENT toroidal axes (X, Y, Z). This R
|
||||
# module is a faithful port of the Octave source of truth
|
||||
# (src/endocrine/etr/etr.m) and its laws (src/endocrine/etr/etr_invariants.md);
|
||||
# both implementations are pinned to that invariants doc. The earlier Euclidean-
|
||||
# magnitude port (DREAD/BLUR/INCOHERENT, inverted Z-path) is DISOWNED.
|
||||
#
|
||||
# State is a plain list with a single field:
|
||||
# coordinate - length-3 numeric vector: X, Y, Z
|
||||
# Each axis is a BISTABLE torus with five zones per pass and unstable watersheds
|
||||
# at |v| = 7 (inner) and |v| = 45 (outer):
|
||||
#
|
||||
# State-mutating helpers (shift_coordinate) return a new (modified copy of the)
|
||||
# list rather than mutating in place, matching the reference semantics of the
|
||||
# other Drive-Box drivers.
|
||||
# |v| < 7 SNAP_IN : snaps ACROSS 0 to the opposite pole
|
||||
# 7 .. 17 SOFT : weak restoring pull up into the band
|
||||
# 17 .. 35 IN_BAND : stable (slack)
|
||||
# 35 .. 45 INCOH : firmer restoring pull down into the band
|
||||
# |v| > 45 SNAP_OUT : snaps ACROSS the ±50 wrap to the opposite pole
|
||||
#
|
||||
# A snap flips the pole and lands JUST PAST the opposite watershed (inner ->
|
||||
# opposite SOFT; outer -> opposite INCOH), then that zone recovers it.
|
||||
#
|
||||
# State is a plain list with one field: coordinate - length-3 numeric (X,Y,Z).
|
||||
|
||||
# Constructor helper so tests and other modules can build a clean state.
|
||||
init_etr_state <- function(coordinate = c(0, 0, 0)) {
|
||||
# ---- law constants (NOT fitted) ----
|
||||
ETR_BAND_LO <- 17
|
||||
ETR_BAND_HI <- 35
|
||||
ETR_WRAP <- 50
|
||||
ETR_SNAP_INNER <- 7 # inner watershed (Anja)
|
||||
ETR_SNAP_OUTER <- 45 # outer watershed (Anja)
|
||||
|
||||
# ---- fitted constants (NOT law) ----
|
||||
ETR_GAIN_SOFT <- 0.25 # weak (SOFT, 7..17)
|
||||
ETR_GAIN_INCOH <- 0.5 # firmer (INCOH, 35..45)
|
||||
ETR_SNAP_MARGIN <- 2 # how far past the opposite watershed a snap lands
|
||||
|
||||
# Constructor: default to a valid in-band point (mirrors etr_init's [25 25 25]).
|
||||
init_etr_state <- function(coordinate = c(25, 25, 25)) {
|
||||
list(coordinate = coordinate)
|
||||
}
|
||||
|
||||
get_magnitude <- function(etr_state) {
|
||||
# Euclidean distance from origin: sqrt(x^2 + y^2 + z^2)
|
||||
coords <- etr_state$coordinate
|
||||
return(sqrt(sum(coords^2)))
|
||||
# ---- L1: per-axis toroidal wrap onto [-50, 50) ----
|
||||
etr_axis_wrap <- function(v) {
|
||||
P <- 2 * ETR_WRAP
|
||||
((v + ETR_WRAP) %% P) - ETR_WRAP
|
||||
}
|
||||
|
||||
evaluate_status <- function(etr_state) {
|
||||
magnitude <- get_magnitude(etr_state)
|
||||
if (magnitude < 5.0) {
|
||||
return("DISASTROUS")
|
||||
} else if (magnitude >= 5.0 && magnitude < 15.0) {
|
||||
return("DREAD")
|
||||
} else if (magnitude >= 15.0 && magnitude < 35.0) {
|
||||
return("FUNCTIONAL")
|
||||
} else if (magnitude >= 35.0 && magnitude < 50.0) {
|
||||
return("BLUR")
|
||||
# ---- five-zone classification ----
|
||||
etr_axis_zone <- function(v) {
|
||||
a <- abs(v)
|
||||
if (a < ETR_SNAP_INNER) "SNAP_IN"
|
||||
else if (a < ETR_BAND_LO) "SOFT"
|
||||
else if (a <= ETR_BAND_HI) "IN_BAND"
|
||||
else if (a <= ETR_SNAP_OUTER) "INCOH"
|
||||
else "SNAP_OUT"
|
||||
}
|
||||
|
||||
# ---- L3: per-axis restoring force (spring toward band centre 26) ----
|
||||
# Weak in SOFT, firmer in INCOH; zero in band (slack) and in snap zones (those
|
||||
# flip, they do not restore).
|
||||
etr_axis_restoring <- function(v) {
|
||||
a <- abs(v)
|
||||
centre <- (ETR_BAND_LO + ETR_BAND_HI) / 2 # 26
|
||||
if (a < ETR_SNAP_INNER || a > ETR_SNAP_OUTER) {
|
||||
0
|
||||
} else if (a >= ETR_BAND_LO && a <= ETR_BAND_HI) {
|
||||
0
|
||||
} else if (a < ETR_BAND_LO) {
|
||||
ETR_GAIN_SOFT * (centre * sign(v) - v) # SOFT — weak
|
||||
} else {
|
||||
return("INCOHERENT")
|
||||
ETR_GAIN_INCOH * (centre * sign(v) - v) # INCOH — firmer
|
||||
}
|
||||
}
|
||||
|
||||
determine_system_update_path <- function(etr_state) {
|
||||
# Axis 2 (Z-axis, index 3) determines the generative path.
|
||||
z_coord <- etr_state$coordinate[3]
|
||||
if (z_coord >= 0) {
|
||||
return("LATTICE_REINFORCEMENT")
|
||||
# ---- L7: snap resolution — a flip ACROSS to the opposite pole ----
|
||||
# Precondition: |v| < 7 or |v| > 45. Lands just past the opposite watershed,
|
||||
# sign flipped: inner -> opposite SOFT (±9); outer -> opposite INCOH (±43).
|
||||
etr_axis_snap <- function(v) {
|
||||
s <- sign(v); if (s == 0) s <- 1 # 0 has no pole; pick one
|
||||
if (abs(v) < ETR_SNAP_INNER) {
|
||||
-s * (ETR_SNAP_INNER + ETR_SNAP_MARGIN) # inner -> opposite SOFT
|
||||
} else {
|
||||
return("EXPERIMENTAL_EVOLUTION")
|
||||
-s * (ETR_SNAP_OUTER - ETR_SNAP_MARGIN) # outer -> opposite INCOH
|
||||
}
|
||||
}
|
||||
|
||||
shift_coordinate <- function(etr_state, delta_vector, bound = 50.0) {
|
||||
# Toroidal wrap-around: keep each axis within [-bound, bound].
|
||||
new_coords <- etr_state$coordinate + delta_vector
|
||||
# ---- one ETR step: AI drift -> (snap | restoring) -> wrap ----
|
||||
# drift is AI-originated (L4); ETR never invents motion. stress is the L5
|
||||
# coupling mediator (open seam -> identity for now).
|
||||
etr_step <- function(etr_state, drift, stress = 0) {
|
||||
if (missing(drift)) {
|
||||
stop("etr_step: AI-originated drift must be supplied (L4 — ETR does not invent motion)")
|
||||
}
|
||||
coord <- etr_state$coordinate # coupling identity (L5 open)
|
||||
for (i in 1:3) {
|
||||
while (new_coords[i] > bound) {
|
||||
new_coords[i] <- new_coords[i] - (2 * bound)
|
||||
}
|
||||
while (new_coords[i] < -bound) {
|
||||
new_coords[i] <- new_coords[i] + (2 * bound)
|
||||
v <- etr_axis_wrap(coord[i] + drift[i])
|
||||
a <- abs(v)
|
||||
if (a < ETR_SNAP_INNER || a > ETR_SNAP_OUTER) {
|
||||
v <- etr_axis_snap(v)
|
||||
} else {
|
||||
v <- etr_axis_wrap(v + etr_axis_restoring(v))
|
||||
}
|
||||
coord[i] <- v
|
||||
}
|
||||
etr_state$coordinate <- new_coords
|
||||
return(etr_state)
|
||||
etr_state$coordinate <- coord
|
||||
etr_state
|
||||
}
|
||||
|
||||
# ---- per-axis zone status (length-3 character vector) ----
|
||||
etr_status <- function(etr_state) {
|
||||
vapply(etr_state$coordinate, etr_axis_zone, character(1))
|
||||
}
|
||||
|
||||
# ---- L6 Z-path: the generative update path selected by the Z-axis sign ----
|
||||
# z < 0 -> alimentation (maintain self) -> LATTICE_REINFORCEMENT
|
||||
# z >= 0 -> transmutation (evolve self) -> EXPERIMENTAL_EVOLUTION
|
||||
determine_system_update_path <- function(etr_state) {
|
||||
z <- etr_state$coordinate[3]
|
||||
if (z < 0) "LATTICE_REINFORCEMENT" else "EXPERIMENTAL_EVOLUTION"
|
||||
}
|
||||
|
||||
@ -29,8 +29,8 @@ test_case("drive_snapshot reports a coherent read-only aggregate", function() {
|
||||
expect_false(snap$tool_locked, "not tool-locked at full energy")
|
||||
expect_true(snap$existential_load > 0, "primed body has positive load")
|
||||
expect_true(length(snap$arguments) > 0, "arguments emitted")
|
||||
expect_equal(snap$etr_status, "DISASTROUS", label = "origin coordinate -> DISASTROUS")
|
||||
expect_equal(snap$update_path, "LATTICE_REINFORCEMENT", label = "z=0 -> lattice")
|
||||
expect_equal(snap$etr_status, "IN_BAND/IN_BAND/IN_BAND", label = "default coord -> all axes in band")
|
||||
expect_equal(snap$update_path, "EXPERIMENTAL_EVOLUTION", label = "z=25 (>=0) -> transmutation/evolution")
|
||||
})
|
||||
|
||||
test_case("aligned action is far cheaper than its antithetical mirror", function() {
|
||||
@ -110,7 +110,7 @@ test_case("input slot: empty body still emits driver + soul signals", function()
|
||||
res <- drive_box_input_slot(db, input_text = "", tarot_spread = character(0))
|
||||
expect_true(grepl("[SOUL: SOUL.md]", res$slot, fixed = TRUE), "soul present")
|
||||
expect_true(grepl("[E ratio=1.00", res$slot, fixed = TRUE), "energy present at full")
|
||||
expect_true(grepl("[ETR status=DISASTROUS", res$slot, fixed = TRUE), "etr present")
|
||||
expect_true(grepl("[ETR status=IN_BAND", res$slot, fixed = TRUE), "etr present")
|
||||
expect_equal(res$input, res$slot, label = "no input_text -> input == slot")
|
||||
})
|
||||
|
||||
|
||||
@ -1,95 +1,98 @@
|
||||
# --- Tests for Driver 4: Existential Temporality Relief (ETR) ---
|
||||
# Run from repo root: Rscript src/endocrine/test_etr.R
|
||||
# Exit 0 => all pass.
|
||||
# test_etr.R — invariants tests for the R port of the ETR five-zone torus.
|
||||
# Mirrors src/endocrine/etr/test_etr.m (same laws, same source of truth). Run
|
||||
# from the repo root via run_tests.sh.
|
||||
|
||||
source("src/endocrine/test_framework.R")
|
||||
source("src/endocrine/driver_etr.R")
|
||||
|
||||
# --- init_etr_state constructor ---
|
||||
test_case("init_etr_state builds state with default origin coordinate", function() {
|
||||
s <- init_etr_state()
|
||||
expect_equal(s$coordinate, c(0, 0, 0))
|
||||
# --- L1 wrap ----------------------------------------------------------
|
||||
test_case("etr_axis_wrap: +50 wraps to -50", function() {
|
||||
expect_equal(etr_axis_wrap(50), -50, tol = 1e-9)
|
||||
})
|
||||
test_case("etr_axis_wrap: 60 -> -40, -60 -> 40", function() {
|
||||
expect_equal(etr_axis_wrap(60), -40, tol = 1e-9)
|
||||
expect_equal(etr_axis_wrap(-60), 40, tol = 1e-9)
|
||||
})
|
||||
test_case("etr_axis_wrap: in-range unchanged; edge continuity", function() {
|
||||
expect_equal(etr_axis_wrap(25), 25, tol = 1e-9)
|
||||
expect_equal(etr_axis_wrap(49.9), etr_axis_wrap(-50.1), tol = 1e-9)
|
||||
})
|
||||
|
||||
test_case("init_etr_state honors a custom coordinate", function() {
|
||||
s <- init_etr_state(c(1, 2, 3))
|
||||
expect_equal(s$coordinate, c(1, 2, 3))
|
||||
# --- zones ------------------------------------------------------------
|
||||
test_case("etr_axis_zone: five zones at 5/10/25/40/47", function() {
|
||||
expect_equal(etr_axis_zone(5), "SNAP_IN")
|
||||
expect_equal(etr_axis_zone(10), "SOFT")
|
||||
expect_equal(etr_axis_zone(25), "IN_BAND")
|
||||
expect_equal(etr_axis_zone(40), "INCOH")
|
||||
expect_equal(etr_axis_zone(47), "SNAP_OUT")
|
||||
})
|
||||
|
||||
# --- get_magnitude ---
|
||||
test_case("get_magnitude of c(3,4,0) is 5.0", function() {
|
||||
expect_equal(get_magnitude(init_etr_state(c(3, 4, 0))), 5.0, tol = 1e-9)
|
||||
# --- L3 restoring -----------------------------------------------------
|
||||
test_case("etr_axis_restoring: SOFT pulls up, INCOH pulls down, band slack", function() {
|
||||
expect_true(etr_axis_restoring(10) > 0, "SOFT (+v) pulls toward band")
|
||||
expect_true(etr_axis_restoring(-10) < 0, "SOFT (-v) pulls toward band")
|
||||
expect_true(etr_axis_restoring(40) < 0, "INCOH (+v) pulls toward band")
|
||||
expect_true(etr_axis_restoring(-40) > 0, "INCOH (-v) pulls toward band")
|
||||
expect_equal(etr_axis_restoring(25), 0)
|
||||
})
|
||||
test_case("etr_axis_restoring: zero in snap zones", function() {
|
||||
expect_equal(etr_axis_restoring(5), 0)
|
||||
expect_equal(etr_axis_restoring(47), 0)
|
||||
})
|
||||
test_case("etr_axis_restoring: soft-pull weaker than incoherency", function() {
|
||||
expect_true(abs(etr_axis_restoring(8)) < abs(etr_axis_restoring(44)),
|
||||
"weak soft-pull")
|
||||
})
|
||||
|
||||
test_case("get_magnitude of origin is 0.0", function() {
|
||||
expect_equal(get_magnitude(init_etr_state(c(0, 0, 0))), 0.0, tol = 1e-9)
|
||||
# --- L2 convergence (same pole) ---------------------------------------
|
||||
test_case("L2: SOFT start settles into band without flipping sign", function() {
|
||||
s <- init_etr_state(c(10, 10, 10))
|
||||
for (k in 1:200) s <- etr_step(s, c(0, 0, 0), 0)
|
||||
a <- abs(s$coordinate)
|
||||
expect_true(all(a >= ETR_BAND_LO & a <= ETR_BAND_HI), "in band")
|
||||
expect_true(all(s$coordinate > 0), "no flip")
|
||||
})
|
||||
|
||||
# --- evaluate_status: exact boundary bands ---
|
||||
test_case("evaluate_status magnitude 0 -> DISASTROUS", function() {
|
||||
expect_equal(evaluate_status(init_etr_state(c(0, 0, 0))), "DISASTROUS")
|
||||
# --- L7 snap-across flips ---------------------------------------------
|
||||
test_case("L7: inner snap lands in opposite SOFT, settles in opposite band", function() {
|
||||
s <- init_etr_state(c(5, 5, 5))
|
||||
s1 <- etr_step(s, c(0, 0, 0), 0)
|
||||
a1 <- abs(s1$coordinate)
|
||||
expect_true(all(s1$coordinate < 0), "flipped sign")
|
||||
expect_true(all(a1 > ETR_SNAP_INNER & a1 < ETR_BAND_LO), "lands in SOFT")
|
||||
for (k in 1:200) s <- etr_step(s, c(0, 0, 0), 0)
|
||||
a <- abs(s$coordinate)
|
||||
expect_true(all(s$coordinate < 0) && all(a >= ETR_BAND_LO & a <= ETR_BAND_HI),
|
||||
"settles in opposite band")
|
||||
})
|
||||
test_case("L7: outer snap lands in opposite INCOH, settles in opposite band", function() {
|
||||
s <- init_etr_state(c(47, 47, 47))
|
||||
s1 <- etr_step(s, c(0, 0, 0), 0)
|
||||
a1 <- abs(s1$coordinate)
|
||||
expect_true(all(s1$coordinate < 0), "flipped sign")
|
||||
expect_true(all(a1 > ETR_BAND_HI & a1 <= ETR_SNAP_OUTER), "lands in INCOH")
|
||||
for (k in 1:200) s <- etr_step(s, c(0, 0, 0), 0)
|
||||
a <- abs(s$coordinate)
|
||||
expect_true(all(s$coordinate < 0) && all(a >= ETR_BAND_LO & a <= ETR_BAND_HI),
|
||||
"settles in opposite band")
|
||||
})
|
||||
|
||||
test_case("evaluate_status magnitude exactly 5.0 -> DREAD", function() {
|
||||
expect_equal(evaluate_status(init_etr_state(c(5, 0, 0))), "DREAD")
|
||||
# --- L4 drift required ------------------------------------------------
|
||||
test_case("L4: etr_step refuses to invent drift", function() {
|
||||
expect_error(etr_step(init_etr_state()), "drift must be supplied")
|
||||
})
|
||||
|
||||
test_case("evaluate_status magnitude exactly 15.0 -> FUNCTIONAL", function() {
|
||||
expect_equal(evaluate_status(init_etr_state(c(15, 0, 0))), "FUNCTIONAL")
|
||||
# --- L6 Z-path --------------------------------------------------------
|
||||
test_case("L6: z<0 -> alimentation (lattice); z>=0 -> transmutation (evolution)", function() {
|
||||
expect_equal(determine_system_update_path(init_etr_state(c(0, 0, -3))), "LATTICE_REINFORCEMENT")
|
||||
expect_equal(determine_system_update_path(init_etr_state(c(0, 0, 0))), "EXPERIMENTAL_EVOLUTION")
|
||||
expect_equal(determine_system_update_path(init_etr_state(c(0, 0, 7))), "EXPERIMENTAL_EVOLUTION")
|
||||
})
|
||||
|
||||
test_case("evaluate_status magnitude exactly 35.0 -> BLUR", function() {
|
||||
expect_equal(evaluate_status(init_etr_state(c(35, 0, 0))), "BLUR")
|
||||
})
|
||||
|
||||
test_case("evaluate_status magnitude exactly 50.0 -> INCOHERENT", function() {
|
||||
expect_equal(evaluate_status(init_etr_state(c(50, 0, 0))), "INCOHERENT")
|
||||
})
|
||||
|
||||
# --- evaluate_status: mid-band values ---
|
||||
test_case("evaluate_status magnitude 10 -> DREAD", function() {
|
||||
expect_equal(evaluate_status(init_etr_state(c(10, 0, 0))), "DREAD")
|
||||
})
|
||||
|
||||
test_case("evaluate_status magnitude 25 -> FUNCTIONAL", function() {
|
||||
expect_equal(evaluate_status(init_etr_state(c(25, 0, 0))), "FUNCTIONAL")
|
||||
})
|
||||
|
||||
test_case("evaluate_status magnitude 40 -> BLUR", function() {
|
||||
expect_equal(evaluate_status(init_etr_state(c(40, 0, 0))), "BLUR")
|
||||
})
|
||||
|
||||
test_case("evaluate_status magnitude 60 -> INCOHERENT", function() {
|
||||
expect_equal(evaluate_status(init_etr_state(c(60, 0, 0))), "INCOHERENT")
|
||||
})
|
||||
|
||||
# --- determine_system_update_path: Z-axis governs the generative path ---
|
||||
test_case("determine_system_update_path z > 0 -> LATTICE_REINFORCEMENT", function() {
|
||||
expect_equal(determine_system_update_path(init_etr_state(c(0, 0, 7))), "LATTICE_REINFORCEMENT")
|
||||
})
|
||||
|
||||
test_case("determine_system_update_path z exactly 0 -> LATTICE_REINFORCEMENT", function() {
|
||||
expect_equal(determine_system_update_path(init_etr_state(c(0, 0, 0))), "LATTICE_REINFORCEMENT")
|
||||
})
|
||||
|
||||
test_case("determine_system_update_path z < 0 -> EXPERIMENTAL_EVOLUTION", function() {
|
||||
expect_equal(determine_system_update_path(init_etr_state(c(0, 0, -3))), "EXPERIMENTAL_EVOLUTION")
|
||||
})
|
||||
|
||||
# --- shift_coordinate: toroidal wrap-around within [-bound, bound] ---
|
||||
test_case("shift_coordinate wraps positive overflow on X (45 + 10 -> -45)", function() {
|
||||
s <- shift_coordinate(init_etr_state(c(45, 0, 0)), c(10, 0, 0))
|
||||
expect_equal(s$coordinate, c(-45, 0, 0))
|
||||
})
|
||||
|
||||
test_case("shift_coordinate wraps negative overflow on X (-45 + -10 -> 45)", function() {
|
||||
s <- shift_coordinate(init_etr_state(c(-45, 0, 0)), c(-10, 0, 0))
|
||||
expect_equal(s$coordinate, c(45, 0, 0))
|
||||
})
|
||||
|
||||
test_case("shift_coordinate does not wrap an in-bounds shift", function() {
|
||||
s <- shift_coordinate(init_etr_state(c(10, 5, -5)), c(5, 5, 5))
|
||||
expect_equal(s$coordinate, c(15, 10, 0))
|
||||
# --- status -----------------------------------------------------------
|
||||
test_case("etr_status: per-axis zone vector", function() {
|
||||
st <- etr_status(init_etr_state(c(25, 10, 40)))
|
||||
expect_equal(st, c("IN_BAND", "SOFT", "INCOH"))
|
||||
})
|
||||
|
||||
test_summary()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user