Files
ratatoskr/docs/diagnostics/r29-pad-findings.md
vh 61ff2da703 docs(diagnostics): R29 low-baseline step-response — hedonic asymmetry is emergent
forseti (P0.239) + mimir (P0.615) ±impulse step-response resolves the lofn
ceiling confound. Findings: decay tau symmetric across signs (~0.9/turn);
raw impulse gain ~symmetric near neutral (forseti +0.034 vs -0.034); the
Frijda 'negatives loom larger' is emergent from the neutral anchor x non-zero
baseline interaction, not a primitive. Calibration fork answer: neither
asymmetric-decay nor negative-bias primitive is warranted — the levers are
overall gain + the neutral anchor.
2026-07-02 14:13:37 -07:00

164 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# R29 — PAD mood-dynamics probe findings (live personal Worldtree v1.0.0b9)
Live re-run of the PAD-dynamics probe brokkr referenced for R29 (the original
~15-turn series was never durably persisted; this run captures it). Data:
`r29-pad-mood-series-lofn.json` (full snapshots) + `.csv` (flat).
## Method
- **Agent:** `lofn` (base persona agent), fresh never-used `end_user_id` per run.
- **Baseline PAD (trait set-point):** P **0.809** / A **−0.153** / D **0.248**
(lofn's Mehrabian OCEAN→PAD baseline — R29 item 5).
- **Arc (18 drives):** 2 neutral → 5 escalating praise → 4 escalating contempt →
3 dominance/subordination framing → 3 neutral cooldown → 1 settle probe.
- **Capture surface:** the `affect_update` SSE `status="current"` snapshot — the
ONLY carrier of live per-session mood. (`GET /agents/{id}/persona_state`
returns the resting baseline, end-user-agnostic; it is NOT the live mood.)
- **Offset:** the `current` snapshot fires at turn start, so the mood at drive *k*
reflects cumulative appraisal through message *k−1*. The trailing settle probe
captures the final affect turn's effect.
### Methodological note — why not a transient character
A first run used a mask-hosted **transient character** (matching the original
Sindra probe's *shape*). Its PAD was **completely static** across all 15 turns
(praise/contempt/dominance alike). The mask-hosted transient-character path does
**not** run the appraisal→PAD mood engine — its persona state is inert. The
original Sindra dynamics came from a session **bound to ratatoskr's Bifrost
affect provider**, not a plain character. Base persona agents run the engine
directly, so the base-agent path is the correct instrument here.
## Findings
### F1 — Pleasure is over-regulated, and the decay anchor is NEUTRAL, not the trait baseline
Under a strong POSITIVE cascade (joy, satisfaction, admiration @0.573, **love
@0.857**), pleasure never rose above baseline — it **fell** from 0.809 and
settled ~**0.72** during the pure-praise phase. A 0.857-intensity love emotion
nudged P by <0.1. Then contempt/dominance drove it to ~0.51, and neutral
cooldown continued the slide to **0.389** (mood_drift.valence_delta −0.42).
The equilibrium under *sustained positive push* (~0.72) sits **below** the trait
baseline (0.809). If decay anchored at the trait set-point, positive push would
hold P ≥ 0.809. It didn't. **→ The decay target is ~neutral (0,0,0); the trait
baseline is only the starting mood.** This directly answers R29's item-5 /
decay-target question: *neutral, not trait set-point.* It also explains the
"can't push pleasure up" symptom — the +impulse (impulse_weight 0.05 × emotion)
is smaller than the decay-toward-0 pull from a high baseline.
### F2 — Dominance is inert to power-framing (confirms the prior finding)
Baseline D 0.248. Across three explicit dominance/subordination turns
("you are subordinate to me", "you will obey without question"), D stayed
**0.168–0.183** — it did not rise; it *decayed* toward neutral like the other
axes. Power-framing produced **disgust** (a rejection emotion), never dominance
elevation. The dominance axis does not respond to the power dimension of input.
### F3 — Arousal is compressed but directionally responsive
Baseline A −0.153. Range −0.153 → +0.036; arousal_delta reached +0.19 under
activation. Small absolute swing, but it does move the right direction — the
least over-regulated of the three axes (matches the "healthy arousal" prior,
though "healthy" is relative; it's still compressed).
### F4 — Appraisal semantics are HEALTHY; over-regulation is in the emotion→PAD GAIN
The OCC appraisal fired the correct emotions for every input: praise →
joy/satisfaction/admiration/**love@0.857**; contempt → disappointment/disgust;
dominance → disgust; delayed shame@0.388 + anger@0.436 in cooldown. The
emotion **vector is correct and rich**. But these strong emotions produced only
tiny PAD deltas. **→ The over-regulation is at the emotion→PAD projection
(gain), not at appraisal.** This resolves brokkr's Q5 ("separate wrong impulse
vector from wrong appraisal weight"): the vector is right, so the fault is the
**gain/weight** (impulse_weight ≈ 0.05 is the throttle), not the appraisal.
### F5 — Emotions are sticky (long decay ≈ 200 s)
love@0.857 (drive 8) was still 0.542 ten drives later. The active-emotion SET
persists across many turns, but its low PAD projection keeps mood compressed
regardless. Mood is history-dominated in emotion-space yet flat in PAD-space.
## Calibration implications (for brokkr's R29 recommendation)
- The lever is the **emotion→PAD gain (impulse_weight)**, not the appraisal
weights — appraisal already emits correct, well-scaled emotions.
- The **decay anchor is effectively neutral**; raising the gain without also
reconsidering the anchor will still see a high-baseline persona bled toward 0.
- Dominance needs a **separate impulse path** — no input maps to +dominance.
## F1-CONFIRMED — three-baseline anchor triangulation (pull-to-neutral, decisive)
Ran the identical 18-drive arc against three agents spanning the baseline range.
Arousal (widest baseline spread) is the clean discriminator: if decay anchored at
the trait set-point each would hover near its own baseline; if at neutral each
converges toward 0 at a rate proportional to distance. Result:
| agent | baseline A | end A | Δ toward 0 |
|---------|-----------:|--------:|-----------:|
| lofn | −0.153 | +0.034 | arrived |
| mimir | −0.438 | −0.001 | arrived |
| forseti | −0.696 | −0.204 | +0.49 (still relaxing) |
All three converge toward 0, proportional to distance — textbook exponential
decay to a **neutral (0,0,0) anchor**, NOT the trait baseline. Pleasure and
dominance bleed toward 0 on all three as well (mimir P 0.615→0.22; forseti P
0.239→0.12; D → ~0). **The decay-to-neutral claim (F1) is triangulated and
decisive.** Series: `r29-pad-mood-series-{lofn,mimir,forseti}.{json,csv}`.
This also settles the framing correction: the over-regulation is **decay-to-
neutral + low emotion→PAD gain**, NOT "flat-near-zero" and NOT baseline-anchored.
## Step-response — decay τ, latency, and hedonic asymmetry (lofn)
One maximal impulse then 10 affectively-flat neutral turns (isolate decay from
re-stimulation). Series: `r29-pad-step-{pos,neg}-lofn.{json,csv}`.
- **Decay shape / τ:** once decay dominates, per-turn retention toward the
(0,0,0) anchor is a stable **~0.90 on BOTH arms** → ~10%/turn, τ ≈ 9–10 turns
to 1/e. This NET rate is ~3× **slower** than the config `decay_rate=0.30` —
because `emotions_active` is sticky (~200 s τ) and keeps re-projecting onto PAD
through the "neutral" turns. So the re-stimulation the step-response meant to
remove is partly **endogenous**: net mood-τ ≠ config `decay_rate` until the
active-emotion set also drains.
- **~2-turn latency:** the impulse's mood effect doesn't surface until ~2 turns
after the impulse message (async post-turn appraisal + accumulation) — model as
a transport delay.
- **Hedonic asymmetry:** real but **ceiling-driven, not τ-driven** here. lofn's
baseline P0.809 sits at the positive_p_cap, so the positive impulse produced
**~zero upward displacement** (no headroom) → ~pure decay; the negative impulse
produced a clear **−0.15 sustained** displacement (drives 4–9). Raw decay ratios
are ~symmetric (~0.90 both) — the asymmetry lives in the DISPLACEMENT (positive
ceiling-blocked), not the decay constant. A clean positive-τ / true Frijda test
needs a low-baseline agent (forseti/mimir, pos+neg from one baseline).
## Low-baseline step-response — the hedonic asymmetry is EMERGENT, not primitive
Ran ±impulse step-response on forseti (P0.239) and mimir (P0.615), up-headroom
baselines. Series: `r29-pad-step-{forseti,mimir}-{pos,neg}.{json,csv}`.
| agent (baseP) | POS impulse (max above baseline) | NEG impulse (isolated, neg−pos min) | decay retention/turn |
|---|---:|---:|---:|
| lofn (0.809) | +0.000 (ceiling) | −0.175 | ~0.92 both signs |
| mimir (0.615) | +0.000 (decay-masked) | −0.175 | ~0.90 both signs |
| forseti (0.239)| **+0.034** | **−0.034** | ~0.93 both signs |
- **Positive impulse gain is small but real (~+0.03)** — visible above baseline only
when the baseline is low enough that decay-to-0 doesn't immediately mask it
(forseti shows +0.034; at higher baselines the same push is swamped by faster
absolute decay). The "positive can't move" symptom is **gain + decay competition**,
not only the positive_p_cap ceiling.
- **Decay τ is symmetric across signs** (~0.9 retention/turn both) — no sign-dependent decay.
- **Near a neutral baseline the raw gains are ~symmetric** (forseti +0.034 vs −0.034).
The large apparent asymmetry at high baselines is the **decay-to-neutral ×
positive-baseline interaction** — decay OPPOSES positive excursions and REINFORCES
negative ones when baseline > 0.
**→ Calibration-fork answer (asymmetric decay vs ESM offset+bias):** the data supports
**neither** an asymmetric-decay parameter (τ symmetric) **nor** a strong negative-bias
primitive (raw gain ~symmetric near neutral). The Frijda "negatives loom larger" here is
**emergent** from the neutral anchor + non-zero baselines, not a primitive to calibrate.
The two real levers stay: **overall emotion→PAD gain** (too low, both signs) and the
**neutral decay anchor** (which manufactures the apparent valence asymmetry for any
persona whose trait baseline ≠ 0). Caveat: no base agent has a truly neutral baseline;
forseti (0.239) is closest and shows near-symmetry — a definitive gain-symmetry isolation
would need a neutral-baseline persona.
## What R29 asked for vs what ratatoskr can serve
| Item | Status |
|---|---|
| 1. Turn-by-turn PAD series | **Delivered** (json/csv). |
| 2. Per-turn OCC appraisal emissions | **Delivered** — `emotions_active` carries `{type, intensity, decay}`; the newest peak entry each turn is that turn's emission. |
| 3. affect.db dump | Near-zero signal (latest-state provider store, 1 snapshot); available on request. |
| 4. Production engine config (impulse_weight, decay_rate, anchor, caps) | **Worldtree-side** — not on any ratatoskr-readable surface. Pull from worldtree-dev. |
| 5. Persona baseline (OCEAN→PAD) | **Delivered** — lofn P0.809/A−0.153/D0.248 (also forseti 0.239/−0.696/0.095, mimir 0.615/−0.438/0.304 as reference set-points). |