docs(diagnostics): R30 Phase-1 φ0 measurement — config faithful (demo b14)

Joint two-timescale fit (brokkr-ruled) + empty-tail cross-check against the A1
corrected anchor (baseline_pad). Deployed PAD-point decay φ0 ≈ 0.95-0.97 across
3 baselines (lofn/mimir/mask), intercept c≈0 → config (decay_rate=0.05, φ=0.95)
is faithfully applied; the R29 net-0.90 was continuous re-appraisal, not re-push.
Trait-flat confirmed; A/P ratio ~uniform (not the S2-expected 1.9); φ_max rec:
relax to ~0.96. forseti signal-poor (low-baseline small excursion, excluded);
mask_neg stalled on a demo hang (7/8).
This commit is contained in:
vh
2026-07-03 07:04:00 -07:00
parent c77ff913f0
commit 875f291a42
8 changed files with 5379 additions and 0 deletions
+77
View File
@@ -0,0 +1,77 @@
# 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 (pos) | +0.004 | 0.90 | — |
| forseti | 0.239 | signal-poor (r²=0.46/0.61, excluded) | — | — | **0.95** (neg, r²=1.0) |
- **Joint fit, 5 well-conditioned runs (3 baselines): φ_P = 0.969 ± 0.01**
(range 0.954–0.983).
- **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** stalled on a demo-side turn hang (SSE stall on turn 14);
proceeding with 7/8. Non-blocking — mask_pos already anchors the neutral (0.0)
trait point; mask_neg would be a second neutral-baseline run.
Series: `r30-phi0-{lofn,mimir,forseti,mask}-{pos,neg}.json` (per-turn pad +
emotions_active + wall-clock). sec/turn ≈ 19–25 (16s spacing + processing).