etr: fit RESTORE_GAIN — restoring force green (14 PASS / 0 FAIL / 2 PEND)

Spring restoring force (gain 0.5) toward band centre 26, active only out
of band; pulls the basin into [17,35] in a couple of steps without
overshoot. Closes the two red tests (L3 magnitude, L2 convergence).
NOTE: superseded design incoming — Anja's 4-zone bistable axis (snap
<7 / soft-pull 7-17 / stable / incoherency 35-45 / snap >45) will fold
this in as the soft-pull gain and revise L7.

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:
Claude 2026-06-17 05:17:14 +00:00
parent fe65602f16
commit 80791084a4
No known key found for this signature in database
3 changed files with 38 additions and 13 deletions

View File

@ -20,8 +20,9 @@ engine, and *not* migration. The axes:
Handles the stress PS+/Eth-Int generate. Handles the stress PS+/Eth-Int generate.
## 2. Status / certainty ## 2. Status / certainty
**SCAFFOLD — built and tested this session** (`run_etr_tests.sh` → 12 PASS / 2 FAIL-by-design / **SCAFFOLD — `RESTORE_GAIN` fitted** (`run_etr_tests.sh`**14 PASS / 0 FAIL / 2 PEND**; the 2 PEND
2 PEND). Full law + status in `../../src/endocrine/etr/etr_invariants.md` (this spec defers to it). are L5 active coupling and L7). Full law + status in `../../src/endocrine/etr/etr_invariants.md`
(this spec defers to it).
## 3. Language & location ## 3. Language & location
GNU Octave · `src/endocrine/etr/` (`etr.m`, `test_etr.m`, `run_etr_tests.sh`, `etr_invariants.md`). GNU Octave · `src/endocrine/etr/` (`etr.m`, `test_etr.m`, `run_etr_tests.sh`, `etr_invariants.md`).

View File

@ -22,6 +22,12 @@ function v = ETR_BAND_LO(); v = 17; endfunction
function v = ETR_BAND_HI(); v = 35; endfunction function v = ETR_BAND_HI(); v = 35; endfunction
function v = ETR_WRAP(); v = 50; endfunction function v = ETR_WRAP(); v = 50; endfunction
% ---- fitted constant (NOT law) ----
% RESTORE_GAIN: spring stiffness of the out-of-band restoring force (etr_axis_restoring).
% Fitted to satisfy L3-magnitude (force nonzero out of band) and L2 (zero-drift
% convergence into the band) without overshoot past the far edge. 0 < GAIN < ~2.
function v = ETR_RESTORE_GAIN(); v = 0.5; endfunction
% ---- state: one point, three scalars ---- % ---- state: one point, three scalars ----
function s = etr_init(coord) function s = etr_init(coord)
if nargin < 1, coord = [25 25 25]; endif % default: a valid in-band point if nargin < 1, coord = [25 25 25]; endif % default: a valid in-band point
@ -50,11 +56,22 @@ function d = etr_axis_restoring_dir(v)
endif endif
endfunction endfunction
% ---- L3: per-axis restoring FORCE (STUB: magnitude UNFITTED -> RED) ---- % ---- L3: per-axis restoring FORCE (FITTED) ----
% Direction above is law; the magnitude/curve (RESTORE_GAIN) is C1 TBD. % Direction is law (etr_axis_restoring_dir); the magnitude is a spring fitted
% Returns 0 for now so the magnitude + convergence tests stay red. % via RESTORE_GAIN. The force is active ONLY out of band (in band = slack, L3),
% and pulls toward the band CENTRE (not the near edge): a centre target makes the
% step cross INTO [17,35] and stop there, whereas an edge target would asymptote
% onto 17 from below and never reach |v|>=17 (failing L2). Below-band pushes away
% from 0, so the restoring force alone never crosses zero (L7).
function r = etr_axis_restoring(v) function r = etr_axis_restoring(v)
r = 0; % STUB TODO: RESTORE_GAIN * shape(v) along etr_axis_restoring_dir(v) GAIN = ETR_RESTORE_GAIN();
a = abs(v);
if a < ETR_BAND_LO() || a > ETR_BAND_HI()
centre = (ETR_BAND_LO() + ETR_BAND_HI()) / 2; % 26
r = GAIN * (centre * sign(v) - v); % spring toward signed centre
else
r = 0; % in band: slack (L3)
endif
endfunction endfunction
% ---- L5: cross-axis coupling (OPEN SEAM) ---- % ---- L5: cross-axis coupling (OPEN SEAM) ----

View File

@ -24,10 +24,15 @@ Each axis is a standalone scalar carrying one of ETR's three tensions:
| L7 no-zero-cross | **C2** | Bands wall off 0; a pole/sign flip happens **only** by riding over the ±50 wrap, never through neutrality. *(emergent — unconfirmed)* | | L7 no-zero-cross | **C2** | Bands wall off 0; a pole/sign flip happens **only** by riding over the ±50 wrap, never through neutrality. *(emergent — unconfirmed)* |
| L8 mechanism | **C2** | "Opposition" = a restoring force on the drift, **not** an out-of-band cost. *(unconfirmed)* | | L8 mechanism | **C2** | "Opposition" = a restoring force on the drift, **not** an out-of-band cost. *(unconfirmed)* |
## Constants (NOT yet fitted — C1) ## Constants
`BAND_LO = 17`, `BAND_HI = 35`, `WRAP = 50` are **law** (L1L3), not fitted. `BAND_LO = 17`, `BAND_HI = 35`, `WRAP = 50` are **law** (L1L3), not fitted.
`RESTORE_GAIN` (restoring magnitude/curve) and `COUPLING` (L5 strength/mapping) are **TBD**, `RESTORE_GAIN = 0.5` is **FITTED** — the spring stiffness of the out-of-band restoring force: active
to be fitted so the tests pass — never asserted ahead of a test. only out of band (in band is slack, L3), pulling toward the band **centre (26)** so a step crosses
*into* `[17,35]` and stops there (an edge target would asymptote onto 17 from below and fail L2).
Below-band pushes away from 0, so the force alone never crosses zero (L7). Lands e.g. `[5 5 5] → 20.75`
in 2 steps; `[45 45 40] → [30.75 30.75 33]`. Valid range `0 < GAIN < ~2` (above ~2 a cross-in step can
overshoot the far edge).
`COUPLING` (L5 strength/mapping) remains **TBD** — open seam, not to be invented.
## Testable predicates (see `test_etr.m`) ## Testable predicates (see `test_etr.m`)
- **L1**: `wrap(50) = 50`; `wrap(60) = 40`; `wrap(v)=v` for `v∈(50,50)`; `wrap(49.9) = wrap(50.1)`. - **L1**: `wrap(50) = 50`; `wrap(60) = 40`; `wrap(v)=v` for `v∈(50,50)`; `wrap(49.9) = wrap(50.1)`.
@ -58,7 +63,9 @@ scaffold seam is correct). What's fixed is their **provenance** (upstream in SAE
endocrines) and two side-effects (reshuffle, shift-rate) that belong to *those* organs. endocrines) and two side-effects (reshuffle, shift-rate) that belong to *those* organs.
Still open: which stress endomotiv; the "too strong" reshuffle threshold; the shift-rate function. Still open: which stress endomotiv; the "too strong" reshuffle threshold; the shift-rate function.
## Status at scaffold ## Status (RESTORE_GAIN fitted — 14 PASS / 0 FAIL / 2 PEND)
Implemented (green): L1 wrap, L3 direction, L4 drift-must-be-fed, L5 coupling-off identity. Green: L1 wrap, L3 direction + **restoring magnitude (fitted)**, **L2 band-convergence**,
Red (await fitting): L3 restoring **magnitude**, L2 band-convergence. L4 drift-must-be-fed, L5 coupling-off identity. L8 (opposition = a restoring force on the drift, not an
Pending (unconfirmed): L5 active coupling, L7 no-zero-crossing, L8 mechanism. out-of-band cost) is now **realised by construction** — the force is added alongside drift, never charged
as a cost — though still tagged C2 until a dedicated test pins it.
Pending: L5 active coupling (C1, open seam), L7 no-zero-crossing (C2).