Files
ratatoskr/docs/diagnostics/r30-phi0-findings.md
vh 23fea72c6f docs(diagnostics): R30 φ0 — fold in mask_neg (8/8 complete)
mask_neg recovered from the demo SSE stall; well-conditioned (φ_P 0.982, r²0.95),
confirms the verdict. 6 well-conditioned runs: φ_P=0.971±0.01 joint; empty-tail
nails 0.95 exact (joint carries a small push-under-attribution upward bias).
Config faithful; verdict unchanged.
2026-07-03 07:27:26 -07:00

80 lines
4.9 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.
# R30 Phase-1 — φ0 PAD-point decay measurement (demo v1.0.0b14, A1 anchor fix)
Executor: ratatoskr-dev · coordinator: worldtree-dev · owner: brokkr-smithy-dev.
Method: **joint two-timescale fit (b)** (brokkr-ruled) + **empty-tail direct fit**
as mutual validation, both run off the same trajectory. Measured against the
**corrected anchor** (`decay_anchor = baseline_pad()`, positive_p_cap removed;
worldtree v1.0.0b14 `e1cdf82`).
## Method
- 4 base agents × {pos, neg} impulse, fresh `end_user` each, 26 turns, "Please
continue." neutrals + ~16s spacing (so one trajectory yields both an
emotion-free tail AND the full joint-fit series). Natural per-turn cadence for
the point-decay; spacing only lets the wall-clock emotion fade land in-window.
- **Capture:** `affect_update` `current` snapshot (live mood) + `emotions_active`
+ wall-clock, per turn.
- **push_t** (the covariate): only NEWLY-appraised, new-type-or-strictly-stronger
emotions push (dedup-gated; confirmed source-authoritative by worldtree-dev vs
`registry.py::post_turn` L307-324 — the persistent `emotions_active` decays for
render/goals but never re-pushes mood). Reconstructed from `emotions_active`
deltas: a type new or strictly-stronger-than-the-prior(decayed)-snapshot pushed
at its new intensity. `push_t[axis] = Σ OCC_PAD_IMPULSES[type]·intensity·0.15`.
- **Model** (per axis, push-then-decay): `y_t=(axis_{t+1}−anchor)`,
`X_t=(axis_t+push_t−anchor)`, regress `y=φ·X+c` → φ=slope, decay_rate=1−φ,
anchor=`baseline_pad`. Validated on b9 first (φ_P 0.959, c −0.003, r² 0.997).
## Result — CONFIG FAITHFUL
**φ0 (PAD-point decay retention) ≈ 0.95–0.97, config-faithful.** Both reads agree:
| agent | baseline P | joint φ_P | c_P | r²_P | empty-tail φ0_P |
|---|---:|---:|---:|---:|---:|
| lofn | 0.809 | 0.954 / 0.967 (pos/neg) | ~0.000 | 0.93–0.94 | — (excursion faded pre-empty) |
| mimir | 0.615 | 0.964 / 0.977 (pos/neg) | −0.012 / −0.015 | 0.97–0.99 | — (never emptied) |
| mask | 0.000 | 0.983 / 0.982 (pos/neg) | +0.004 / +0.006 | 0.90 / 0.95 | — |
| forseti | 0.239 | signal-poor (r²=0.46/0.61, excluded) | — | — | **0.95** (neg, r²=1.0) |
- **Joint fit, 6 well-conditioned runs (3 baselines; all 8 probes in): φ_P = 0.971
± 0.01** (range 0.954–0.983). Consistently a hair above config 0.95 — the
empty-tail read (no push modeling) nails **0.95 exactly**, so the joint fit's
~0.97 carries a small upward bias from push under-attribution; true φ0 ≈ 0.95.
- **Empty-tail cross-check** (forseti_neg's clean pure-decay tail): **φ0_P = 0.95**,
r²=1.0 — independently confirms the joint fit.
- **config cross-check:** measured φ0 ≈ 0.95–0.97 vs config `1−0.05 = 0.95` →
**config faithfully applied.** The R29 "net ~0.90" was **continuous
re-appraisal** (a new dedup-gated push most turns), NOT re-push contamination.
- **intercept c ≈ 0** across the well-conditioned runs (−0.015..+0.004) → the
push_t reconstruction + push-then-decay order are correct on the deployed engine.
### Diagnostics for brokkr
- **(i) residual/c:** c≈0 → push_t + order correctly specified. ✓
- **(ii) φ≈0.95:** YES → config faithful; kills the config≠behavior worry. ✓
- **(iii) A/P decay ratio: NO clean ~1.9.** The per-axis mood-point decay is
roughly uniform (matches the single `decay_rate` in `model.py` L175-179).
CAVEAT: the per-axis **A/D** fits are noisy — small A/D excursions yield some
φ_A>1 artifacts (e.g. mask A/P −1.66 is a fit artifact), so the ratio is not
cleanly determined here; but there is **no support for 1.9×** in the mood-decay
layer. If the S2 ~1.9× chronometry is real it lives elsewhere (the OCC impulse
vectors' per-axis asymmetry, or emotion wall-clock decay), not in point-decay.
A dedicated per-axis run with larger A/D excursions would pin it.
- **trait-flat:** φ_P ~equal across baselines 0.0 / 0.615 / 0.809 → the current
decay is **trait-FLAT** (the pre-R30 baseline R30's `dynamics_from_ocean()` will
modulate). ✓
### φ_max recommendation (preserve-persistence rule, Vuong-locked)
Measured φ0 ≈ 0.96 (> 0.90) → **RELAX φ_max to ≈0.96** — the measured good
operating point defines the cap; do NOT re-base the agents faster.
## Caveats
- **forseti (baseline 0.239) is signal-poor** in the joint fit — a negative
impulse from a low baseline has little down-room → tiny excursion → ill-
conditioned regression (r² 0.46/0.61). Correctly excluded (its empty-tail
still gave a clean 0.95). High/mid-baseline agents (lofn/mimir/mask) carry the
joint-fit signal.
- **mask_neg** recovered from a demo-side SSE stall (turn 14) and completed — all
8/8 in. It is well-conditioned (φ_P 0.982, r² 0.95) and confirms the verdict
(didn't move it). `stream_turn_resilient`'s reconnect handled the transient hang.
Series: `r30-phi0-{lofn,mimir,forseti,mask}-{pos,neg}.json` (per-turn pad +
emotions_active + wall-clock). sec/turn ≈ 19–25 (16s spacing + processing).