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.
164 lines
10 KiB
Markdown
164 lines
10 KiB
Markdown
# 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). |
|