Compare commits

..
Author SHA1 Message Date
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
vh 1819e05589 docs(diagnostics): R29 PAD mood-dynamics probe — 3-baseline series + step-response + findings
Live re-run of the PAD-dynamics probe for brokkr-smithy R29 (the original
per-turn series was never persisted). Captures, durably:

- 3-baseline arc (lofn/mimir/forseti) — decay anchor is neutral (0,0,0), not
  the trait set-point (all three converge to 0 proportional to distance).
- Positive/negative step-response (lofn) — geometric decay ~0.90 retention/turn,
  ~2-turn appraisal latency, ceiling-driven hedonic asymmetry.
- Findings: over-regulation is at the emotion->PAD gain, not appraisal; OCC
  emissions observable via emotions_active on base agents.

Methodology note: mask-hosted transient characters have a static mood engine;
base persona agents run appraisal->PAD. relations[] is provider-only per
Worldtree ADR-0009.
2026-07-02 14:05:04 -07:00
34 changed files with 5115 additions and 1264 deletions
+4 -4
View File
@@ -104,8 +104,8 @@ id = "worldtree-conversation-api-openapi-v2"
canonical_source = "Worldtree"
canonical_path = "docs/conversation-api-openapi.json"
consumer_path = "docs/conversation-api-openapi.json"
pinned_sha256_16 = "36148179601453a0"
pinned_at = "2026-07-06T16:09:05+00:00"
pinned_sha256_16 = "dbdf4e24c8b06c92"
pinned_at = "2026-06-30T22:25:56+00:00"
[[pins]]
id = "worldtree-conversation-api-sse-events-v1"
@@ -120,8 +120,8 @@ id = "worldtree-conversation-api-spec-v1"
canonical_source = "Worldtree"
canonical_path = "docs/conversation-api-spec.md"
consumer_path = "docs/conversation-api-spec.md"
pinned_sha256_16 = "c656a789caceef14"
pinned_at = "2026-07-06T16:51:09+00:00"
pinned_sha256_16 = "2d111a3b8322b7d1"
pinned_at = "2026-06-30T22:25:56+00:00"
tolerate_drift = true # prose reference; OpenAPI+SSE are the gates
# Worldtree persona render canons (d2) — the deterministic affect->NL the agent is
+7 -9
View File
@@ -7,18 +7,16 @@ documents the pin, the vendored artifacts, and the bump procedure.
| Field | Value |
|---|---|
| Worldtree git SHA | `c9e59ec` |
| Worldtree HEAD message | `docs: document Tier-3 persona/memory schemas + persona_state SET body (OpenAPI 2.3.0)` |
| Pinned on | 2026-07-06 |
| Pinned by | ratatoskr-dev (re-vendor prose markdown — Tier-3 persona/memory/persona_state consumer shapes) |
| Worldtree version at pin | `v1.0.0b22` |
| Worldtree git SHA | `5810a26b38a5ea6630892f9a39756f57c5b7b41e` |
| Worldtree HEAD message | `memory: snapshot — v1.0.0b2 shipped complete (demo + personal green); consumer loop closed` |
| Pinned on | 2026-06-30 |
| Pinned by | ratatoskr-dev (v1 coverage-audit — re-pin to the FROZEN OpenAPI 2.2.0 + SSE schema) |
| Worldtree version at pin | `v1.0.0b2` |
## Pin history
| Date | SHA | Version | Notable deltas consumed |
|---|---|---|---|
| 2026-07-06 | `c9e59ec` | v1.0.0b22 | **Re-vendor the prose markdown — Tier-3 consumer shapes documented.** `c9e59ec` (docs-only, OpenAPI byte-unchanged vs `879cefe`) adds `docs/conversation-api-spec.md` § "Tier 3 — Consumer-defined agents": the persona / memory / persona_state SET-body shapes that serialize as freeform `Any` in the OpenAPI (so prose is their source of truth). Drove a consumer fix: `--set-persona-pad` now sends the canonical `{pad:{pleasure,arousal,dominance}}` named dict (was `{pad:[list]}`) — #317, `v0.19.7`. Foot-guns encoded: persona.ocean single-letter `{O,C,E,A,N}` on `/agents/define` (spelled-out → 422, the #348 mismatch) vs spelled-out on `POST /characters`; memory `{embedder_version, tier3_dreaming}`, stm_* deprecated, allows_world_scope removed→422; only `valence` still 422s. `pin:`-only for the markdown; the `v0.19.7` bump rode the persona_state code fix. |
| 2026-07-06 | `879cefe` | v1.0.0b22 | **Re-vendor OpenAPI 2.2.0→2.3.0 — Worldtree shipped #347 authored-history-write.** One new REST path-group: `POST /sessions/{session_id}/history` (the authored-history-write primitive) + the `AuthoredTurnResponse` schema (openapi path count 40→41). #347 is **OpenAPI-only** — the prose `conversation-api-spec.md` + server `conversation_api.contract.md` are byte-unchanged since the 5810a26 pin (empty `git log` delta), so those `tolerate_drift` pins stay clean; the SSE schema is unchanged (#347 is event-silent by design). **Consumer side NOT yet built** — `POST /sessions/{id}/history` is a fresh in-scope ⬜ gap in `docs/coverage-map.md` (re-opens the v1 coverage-audit with exactly one gap; Heimdall-gated hide-existence → consumer treats 404 as feature-absent). `pin:`-only, no version bump. |
| 2026-06-30 | `5810a26` | v1.0.0b2 | **Re-pin to Worldtree's FROZEN v1 surface (#326), as part of the v1 coverage-audit.** Vendored the machine-readable artifacts — `conversation-api-openapi.json` (OpenAPI **2.2.0**, 40 path-groups) + `conversation-api-sse-events.schema.json` (11 events) — now the **authoritative drift gates** (pinned in `.corviduo-canonicals.toml`, CI-checked by `canonical_drift.py`). The prose `conversation-api-spec.md` is **byte-identical** to the v0.35.16 pin (last WT markdown edit 2026-05-31), kept as the human reference (`tolerate_drift`). b2 deltas already consumed in code: 409/503 eager turn-launch statuses (#331, v0.18.3/.4) + the unified error envelope (#328). 7 endpoints documented only in the OpenAPI, not the prose, all classified in `docs/coverage-map.md`: `admin/keys/bulk`, `admin/persona/{archive,erase}`, `admin/usage`, `embed`, `judgments`, `me/usage`. No client-breaking change — `pin:`-only, no version bump. |
| 2026-06-17 | `f1b59f8` | v0.35.16 | **#297 + #298/#299 — Worldtree adopts the bifrost v0.6 scope wire (emits `scope_any`/`scope_all`) + client-side per-scope-value union recall. With our v0.17.6 provider this closes cold cross-session recall end-to-end.** Catch-up bump (v0.29.0→v0.35.16). Intervening client-facing deltas reviewed, none break our consumer: #211 agent rename (`saga`→`echo`, `actor`→`mask` — slugs only); #245 `end_user_id` persistence + memory-scope resolver; #187/#188/#219 Tier-3 define/PATCH policy (additive); `bifrost` binding field + `ephemeral_does_not_accept_bifrost` 422 now documented (the #17 surface). Error codes stable; no ratatoskr code change required. |
| 2026-05-25 | `da93ca7` | v0.28.0 | #204 — new SSE event `affect_update` (current/scheduled), new endpoint `GET /agents/{id}/persona_state`, auth-model doc edits |
@@ -28,12 +26,12 @@ documents the pin, the vendored artifacts, and the bump procedure.
**Authoritative (FROZEN, machine-readable — the drift gates):**
- `docs/conversation-api-openapi.json` — copy of `Worldtree/docs/conversation-api-openapi.json` (OpenAPI `info.version` **2.3.0**). The frozen v1 REST wire (41 path-groups; 2.3.0 added `POST /sessions/{session_id}/history` per #347). Pinned `worldtree-conversation-api-openapi-v2` in `.corviduo-canonicals.toml`; drift gated by `canonical_drift.py`.
- `docs/conversation-api-openapi.json` — copy of `Worldtree/docs/conversation-api-openapi.json` (OpenAPI `info.version` **2.2.0**). The frozen v1 REST wire (40 path-groups). Pinned `worldtree-conversation-api-openapi-v2` in `.corviduo-canonicals.toml`; drift gated by `canonical_drift.py`.
- `docs/conversation-api-sse-events.schema.json` — copy of `Worldtree/docs/conversation-api-sse-events.schema.json`. The frozen SSE event schema (11 discriminated event types). Pinned `worldtree-conversation-api-sse-events-v1`.
**Reference (prose; allowed to lag — `tolerate_drift`):**
- `docs/conversation-api-spec.md` — copy of `Worldtree/docs/conversation-api-spec.md` at the pinned SHA. The **client-facing prose narrative**. Re-vendored at `c9e59ec` (2026-07-06) to carry the § "Tier 3 — Consumer-defined agents" subsections (persona/memory/persona_state SET body) that serialize as freeform `Any` in the OpenAPI JSON — so the **prose is the source of truth for those consumer shapes** (e.g. persona.ocean single-letter `{O,C,E,A,N}` on `/agents/define`; `POST /sessions/{id}/persona_state` body `{pad:{pleasure,arousal,dominance}}`). Elsewhere the OpenAPI/SSE JSON above remain authoritative. Pinned `worldtree-conversation-api-spec-v1` (tolerate_drift).
- `docs/conversation-api-spec.md` — copy of `Worldtree/docs/conversation-api-spec.md` at the pinned SHA. The **client-facing prose narrative**. Byte-frozen at v0.35.16-era content (last WT edit 2026-05-31); the OpenAPI/SSE JSON above are the source of truth where they diverge. Pinned `worldtree-conversation-api-spec-v1` (tolerate_drift).
- `docs/conversation_api.contract.md` — copy of `Worldtree/docs/contracts/conversation_api.contract.md` at the pinned SHA (byte-identical at b2 — server contract unchanged since the v0.35.16 pin). The **server-side contract** including INV-001..INV-052 and amendments. Useful for understanding load-bearing server invariants (e.g., INV-014 turn-id-public, INV-046 admin-events-envelope-stable, INV-049 admin-events-pii-discipline) when designing client behavior against them. Not in the canonical manifest (reference-only).
Both files are vendored — they reflect Worldtree at the pinned SHA, not
+2 -100
View File
@@ -322,9 +322,7 @@ via a `--characters` one-shot lifecycle probe; persona-state write surfaced via
wrappers: parsed dict verbatim (or None on 204), any off-status → SessionApiFailed.
**Note:** `set_persona_state`'s request body is FREEFORM — the frozen OpenAPI 2.2.0
declares no request schema and the prose spec documents only the GET counterpart,
so the caller supplies the snapshot shape. **Canonical (worldtree-dev prose #317,
`c9e59ec`): `{pad:{pleasure,arousal,dominance}}` — a named-key dict, NOT a list;
`--set-persona-pad` builds + sends the named dict (each float in [-1,1]).**
so the caller supplies the snapshot shape (`--set-persona-pad` sends `{pad:[…]}`).
```contract
FN list_character_models(client) -> dict[str, Any]
@@ -371,102 +369,6 @@ POST: [POST-001 return_value] on 204 returns None; [POST-002 side_effect] outbou
STEPS:
1. [sequential, prescriptive] resp = await client.post(f"/sessions/{session_id}/persona_state", json=snapshot); IF 204 RETURN None; ELSE RAISE SessionApiFailed
TESTS:
happy [happy]: 204 → None; body == {"pad":{"pleasure","arousal","dominance"}} verbatim (canonical named-key dict, #317)
happy [happy]: 204 → None; body == {"pad":[...]} verbatim
non_204 [error]: 422 → SessionApiFailed(422)
```
## Amendment 2026-07-06 — authored-history write (#347, v1 coverage-audit re-open)
Worldtree shipped #347 (authored-history-write) as OpenAPI 2.3.0: a new
`POST /sessions/{session_id}/history` primitive that writes ONE model-visible
turn into a session's ledger AS the bound agent, WITHOUT a generation and
WITHOUT lived-turn side effects (the SillyTavern "first message"). The re-vendor
(2.2.0→2.3.0, pin `879cefe`) re-opened the v1 coverage-audit with this one new
in-scope REST path-group; this amendment closes it on the consumer side and also
un-defers `GET /sessions/{id}/messages` (previously §Out of scope) as the seed's
read-back.
**Hide-existence (server INV-347-1) — the load-bearing consumer contract.** The
`session.history.write` grant is checked FIRST — an ungranted caller (or a
non-owner, or an unknown session) gets a 404 **byte-identical** to a genuine
`session_not_found`, never a 403/409/422 that would reveal the feature exists.
The consumer MUST honor this: treat 404 as **feature-absent**, fall back (a
production consumer to a model-generated greeting), and NEVER capability-probe to
tell feature-absent from ungranted from session-absent. The wrapper encodes it by
raising a DISTINCT `AuthoredHistoryUnavailable` on 404 (NOT `SessionApiFailed`),
so a caller branches feature-absent without inspecting a status code.
**Request body — v1-minimal, wire-pinned by the server.** The frozen OpenAPI 2.3.0
exports an empty request schema, but the server pins `AuthoredWriteRequest`
(`extra="forbid"`): `{author, content, idempotency_key, effects?,
claimed_original_at?}`. v1: `author="assistant"` (only value), `content` (UTF-8,
server-bounded at `authored_content_max_bytes`=8192), `idempotency_key` (REQUIRED,
per-session dedup), `effects` omitted (== "none"; only value). Because
`extra="forbid"`, the wrapper omits `effects`/`claimed_original_at` when None
(never sends null). Success is 201 (fresh) OR 200 (idempotent replay,
byte-identical body); both return the `AuthoredTurnResponse` `{author,
content_chars, injected_at, phase, seq, session_id, turn_id}` verbatim (provenance
is audit-only, NEVER on this body — INV-347-7).
**Assistant-first provider constraint (deferred, inert for the probe).** A
create-time first-message makes the assistant seq-0 (assistant-first history);
Anthropic-family providers 400 the *next generation*, vLLM/openai_compat tolerate
it. The `--seed-first-message` probe seeds but does NOT generate, so the
constraint is inert for the probe — a real consumer that then generates must bind
an assistant-first-tolerant provider.
```contract
FN write_authored_history(client: httpx.AsyncClient, session_id: str, *, content: str, idempotency_key: str, author: str = "assistant", effects: str | None = None, claimed_original_at: str | None = None) -> dict[str, Any]
BRIEF: POST /sessions/{session_id}/history — the #347 authored-history-write primitive (write one model-visible turn as the bound agent, no generation, no side effects). Body {author, content, idempotency_key} + "effects"/"claimed_original_at" only when non-None (server AuthoredWriteRequest is extra="forbid"). Success 200 (replay) or 201 (fresh) → AuthoredTurnResponse dict verbatim. 404 → AuthoredHistoryUnavailable (hide-existence: feature-absent/ungranted/session-absent, indistinguishable by design — consumer falls back, never probes). Any other non-2xx → SessionApiFailed.
PRE: [PRE-001 hard] client is not None -- assert client is not None
PRE: [PRE-002 hard] session_id is a non-empty str -- assert session_id and isinstance(session_id, str)
PRE: [PRE-003 hard] content is a non-empty str -- assert content and isinstance(content, str)
PRE: [PRE-004 hard] idempotency_key is a non-empty str -- assert idempotency_key and isinstance(idempotency_key, str)
PRE: [PRE-005 hard] author is a non-empty str -- assert author and isinstance(author, str)
POST: [POST-001 side_effect] exactly one POST to /sessions/{session_id}/history; body == {"author": author, "content": content, "idempotency_key": idempotency_key} plus "effects" iff effects is not None plus "claimed_original_at" iff claimed_original_at is not None (no null-valued keys — extra="forbid")
POST: [POST-002 return_value] on 200 or 201 returns resp.json() unmodified
ERROR_ROUTING:
HTTP 404 (hide-existence session_not_found):
local_handling: raise AuthoredHistoryUnavailable(session_id=session_id)
flow_control: abort
state_recovery: caller treats as feature-absent; fall back to a model-generated greeting; NEVER capability-probe (INV-347-1)
HTTP other non-2xx (incl. 409 generation_active, 422 content_too_long/validation_failed, 401 auth_revoked, 410 session_retired):
local_handling: raise SessionApiFailed(status=resp.status_code, body=resp.content)
flow_control: abort
state_recovery: none (409 retryable; 422 caller bug/oversize)
STEPS:
1. [setup, flexibility=prescriptive] assert PRE-001..PRE-005
2. [sequential, flexibility=prescriptive] body = {"author": author, "content": content, "idempotency_key": idempotency_key}; IF effects is not None: body["effects"] = effects; IF claimed_original_at is not None: body["claimed_original_at"] = claimed_original_at
3. [sequential, flexibility=prescriptive] resp = await client.post(f"/sessions/{session_id}/history", json=body)
tool: { destructive: false, idempotent: true, read_only: false, open_world: false }
4. [branch, flexibility=prescriptive] IF resp.status_code in (200, 201): RETURN resp.json(); ELIF resp.status_code == 404: RAISE AuthoredHistoryUnavailable(session_id=session_id); ELSE RAISE SessionApiFailed(status=resp.status_code, body=resp.content)
TESTS:
happy_fresh_201 [happy,tracer]: 201 {author:"assistant", seq:0, phase:"seeded", turn_id, content_chars, session_id, injected_at} → dict verbatim; outbound body == {"author":"assistant","content":<c>,"idempotency_key":<k>} exactly (no effects/claimed_original_at keys)
happy_replay_200 [happy]: 200 (same-key replay, byte-identical body) → dict verbatim
body_includes_effects [trace]: effects="none" → outbound body has "effects":"none"; claimed_original_at="2020-01-01T00:00:00Z" → body has that key too
hide_existence_404 [error]: 404 {error_code:"session_not_found"} → raises AuthoredHistoryUnavailable(session_id=<arg>), NOT SessionApiFailed
generation_active_409 [error]: 409 {error_code:"generation_active"} → SessionApiFailed(status=409)
content_too_long_422 [error]: 422 {error_code:"content_too_long"} → SessionApiFailed(status=422)
empty_content [adversarial]: content="" → AssertionError; no HTTP issued
empty_idempotency_key [adversarial]: idempotency_key="" → AssertionError; no HTTP issued
empty_session_id [adversarial]: session_id="" → AssertionError; no HTTP issued
FN get_session_messages(client: httpx.AsyncClient, session_id: str) -> dict[str, Any]
BRIEF: GET /sessions/{session_id}/messages — the session's message history (spec §GET /sessions/{id}/messages), un-deferred as the #347 probe's read-back so a seeded turn can be confirmed to render as a normal role=assistant message (model-invisible provenance — a seed is indistinguishable from a lived turn on read). Returns {session_id, items:[{seq, role, content, ...}], next_cursor} verbatim. Owner-scoped; any non-200 → SessionApiFailed. v1 reads the server default page (no pagination params — the probe reads a fresh 1-message session; add limit/cursor when a caller needs scrollback).
PRE: [PRE-001 hard] client is not None -- assert client is not None
PRE: [PRE-002 hard] session_id is a non-empty str -- assert session_id and isinstance(session_id, str)
POST: [POST-001 return_value] on 200 returns resp.json() unmodified
ERROR_ROUTING:
HTTP non-200 (incl. 404 session_not_found cross-owner/unknown):
local_handling: raise SessionApiFailed(status=resp.status_code, body=resp.content)
flow_control: abort
state_recovery: none
STEPS:
1. [setup, flexibility=prescriptive] assert PRE-001, PRE-002
2. [sequential, flexibility=prescriptive] resp = await client.get(f"/sessions/{session_id}/messages")
3. [branch, flexibility=prescriptive] IF resp.status_code == 200: RETURN resp.json(); ELSE RAISE SessionApiFailed
TESTS:
happy [happy]: 200 {session_id, items:[{seq:0, role:"assistant", content:"…"}], next_cursor:null} → dict verbatim
not_found_404 [error]: 404 → SessionApiFailed(status=404)
empty_session_id [adversarial]: "" → AssertionError; no HTTP issued
```
+1 -181
View File
@@ -1,50 +1,6 @@
{
"components": {
"schemas": {
"AuthoredTurnResponse": {
"description": "#347 — the authored-write ack. Provenance is audit-only and NEVER on this\npayload (INV-347-7). ``content_chars`` is the CHARACTER count (may differ from\nthe UTF-8 byte length the request is bounded against — INV-347-12).",
"properties": {
"author": {
"title": "Author",
"type": "string"
},
"content_chars": {
"title": "Content Chars",
"type": "integer"
},
"injected_at": {
"title": "Injected At",
"type": "string"
},
"phase": {
"title": "Phase",
"type": "string"
},
"seq": {
"title": "Seq",
"type": "integer"
},
"session_id": {
"title": "Session Id",
"type": "string"
},
"turn_id": {
"title": "Turn Id",
"type": "integer"
}
},
"required": [
"turn_id",
"session_id",
"author",
"phase",
"seq",
"injected_at",
"content_chars"
],
"title": "AuthoredTurnResponse",
"type": "object"
},
"BifrostBindingRequest": {
"additionalProperties": false,
"description": "Bifrost binding parameters for session-create (issue #160).",
@@ -434,7 +390,6 @@
"session_not_found",
"session_not_bifrost_bound",
"session_retired",
"generation_active",
"agent_not_available",
"turn_not_found",
"turn_finished",
@@ -950,7 +905,7 @@
"info": {
"description": "Multi-turn conversation interface for Worldtree agents.",
"title": "Worldtree Conversation API",
"version": "2.3.0"
"version": "2.2.0"
},
"openapi": "3.1.0",
"paths": {
@@ -6427,141 +6382,6 @@
"summary": "Update Session"
}
},
"/sessions/{session_id}/history": {
"post": {
"description": "#347 — write one model-visible turn into a session's ledger AS the bound\nagent, WITHOUT a generation and WITHOUT lived-turn side effects.\n\nHide-existence ordering (INV-347-13): the ``session.history.write`` grant is\nchecked FIRST — before session resolution, before ANY body parse/validation,\nbefore the active-generation guard. An ungranted caller receives ONLY the\nhide-404 (byte-identical to session-not-found, INV-347-1) — never a\n422/409/403 that would distinguish feature-absent from session-absent.",
"operationId": "authored_history_write_sessions__session_id__history_post",
"parameters": [
{
"in": "path",
"name": "session_id",
"required": true,
"schema": {
"title": "Session Id",
"type": "string"
}
}
],
"responses": {
"201": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AuthoredTurnResponse"
}
}
},
"description": "Successful Response"
},
"400": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
},
"description": "Error — unified envelope (detail.error_code is the stable identifier)."
},
"401": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
},
"description": "Error — unified envelope (detail.error_code is the stable identifier)."
},
"403": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
},
"description": "Error — unified envelope (detail.error_code is the stable identifier)."
},
"404": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
},
"description": "Error — unified envelope (detail.error_code is the stable identifier)."
},
"405": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
},
"description": "Error — unified envelope (detail.error_code is the stable identifier)."
},
"409": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
},
"description": "Error — unified envelope (detail.error_code is the stable identifier)."
},
"412": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
},
"description": "Error — unified envelope (detail.error_code is the stable identifier)."
},
"422": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
},
"description": "Error — unified envelope (detail.error_code is the stable identifier)."
},
"500": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
},
"description": "Error — unified envelope (detail.error_code is the stable identifier)."
},
"503": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
},
"description": "Error — unified envelope (detail.error_code is the stable identifier)."
}
},
"security": [
{
"HTTPBearer": []
}
],
"summary": "Authored History Write"
}
},
"/sessions/{session_id}/messages": {
"get": {
"description": "Return paginated message history for a session.",
+9 -158
View File
@@ -2699,13 +2699,10 @@ The `turn.started` event always carries `bifrost_override_applied: bool` (True/F
Tier 3 agents are consumer-owned, Worldtree-hosted agents whose
identity lives at `<user_id>:<agent_name>`. They share the persistent
session infrastructure with Tier 1 / Tier 2. The layer-specific
machinery is now largely active: **`persona` (Phase 2.1, #186),
`memory` (Phase 2.1, #197), and `motivational` (Phase 2.2, #187) are
shipped and consumer-settable at define-time.** Only **`valence` remains
deferred** (non-null → 422 `layer_deferred`). Phase 2.0 shipped the
baseline addressing + ownership + lifecycle substrate; the subsections
below document the active layers and their exact validated shapes.
session infrastructure with Tier 1 / Tier 2 but layer-specific
machinery (persona, motivational, memory, valence) is reserved for
later phases — Phase 2.0 ships baseline addressing + ownership +
lifecycle only.
### Endpoints
@@ -2723,13 +2720,11 @@ below document the active layers and their exact validated shapes.
{
"agent_name": "wizard",
"system_prompt": "You are a guided-elicitation wizard...",
"role": "gen-reasoning", // REQUIRED — a configured model-role (#344), not a raw model id
"persona": { // active (Phase 2.1) — single-letter OCEAN keys; see "Persona layer"
"ocean": {"O": 0.4, "C": 0.6, "E": -0.3, "A": 0.2, "N": 0.5}
},
"motivational": null, // active (Phase 2.2) — see "Motivational layer"
"memory": null, // active (Phase 2.1) — see "Memory layer"
"valence": null // still deferred — non-null → 422 layer_deferred
"model": "glm5-turbo",
"persona": null, // schema-reserved; non-null → 422 layer_deferred
"motivational": null,
"valence": null,
"memory": null
}
```
@@ -2761,150 +2756,6 @@ after definition.
The 201 response includes an advisory `warnings` array (#219) — see
"Model-assignment warnings" under `PATCH` below.
> **Vendoring note (OpenAPI 2.3.0).** In the frozen OpenAPI 2.3.0 document
> the `persona` / `motivational` / `memory` / `valence` request fields
> serialize as **untyped/freeform** — the `POST /agents/define` request
> model types them as `Any` so the layers can activate without a
> schema-breaking change. The shapes documented in the subsections below
> are the **authoritative, validator-enforced** schemas; generate client
> types from this section, not from the freeform OpenAPI fields.
##### Persona layer (Phase 2.1, #186)
`persona` is **active** as of Phase 2.1. It carries the agent's OCEAN
personality vector — the durable trait profile from which Worldtree
derives the mood setpoint (`baseline_pad`) and the mood dynamics
(gain + relaxation time-constants). Shape:
```json
"persona": {
"ocean": { // REQUIRED — exactly these 5 keys, no more, no fewer
"O": 0.4, // Openness — float in [-1.0, 1.0]
"C": 0.6, // Conscientiousness
"E": -0.3, // Extraversion
"A": 0.2, // Agreeableness
"N": 0.5 // Neuroticism
},
"behavioral_notes": "...", // optional, ≤ 4096 chars
"temperament_notes": "..." // optional, ≤ 4096 chars
}
```
**⚠ OCEAN key format — single-letter, uppercase.** The `/agents/define`
persona validator requires the `ocean` map to contain **exactly** the five
uppercase single-letter keys `O, C, E, A, N`. This is a deliberate,
load-bearing contrast with the transient-character primitive
(`POST /characters`), whose `ocean` block uses the **spelled-out**
lowercase keys (`openness`, `conscientiousness`, …). Sending spelled-out
keys to `/agents/define` returns 422 `persona_ocean_required` ("must
contain exactly the 5 keys O, C, E, A, N").
> **Fixed in v1.0.0b21 (#348).** Before that build a correctly
> single-letter-keyed persona was accepted and stored, but resolved to a
> **neutral** mood, because Worldtree's internal mood-derivation read the
> spelled-out key form. On v1.0.0b21+ an API-declared persona correctly
> drives the derived mood setpoint. If you observe neutral mood on a
> persona-defined agent, confirm the deployment is ≥ v1.0.0b21.
**Range.** Each value is a float in `[-1.0, 1.0]` **signed** — `0.0` is the
population mean, NOT `[0.0, 1.0]`. Booleans are rejected. Out-of-range → 422
`persona_ocean_out_of_range`. See [`docs/ocean-traits.md`](ocean-traits.md)
for the SOTA-grounded 5-band behavioural mapping.
Semantics:
- **Per-agent identity trait** — identical for every end-user and session;
immutable post-define (`PATCH {"persona": …}` → 422 `field_not_mutable`).
To change the OCEAN profile, delete and re-define the agent.
- **`extensions` is reserved** — the field exists but must be empty at v0.1;
a non-empty `extensions` returns 422 `layer_deferred`.
- **Sets the mood SETPOINT, not the current mood.** The OCEAN vector fixes
`baseline_pad` (the PAD point the mood relaxes toward over time); the
*current* per-session mood point is seeded separately via
`POST /sessions/{id}/persona_state` (below).
Validation 422 codes: `persona_ocean_required` (missing `ocean`, or keys
≠ {O,C,E,A,N}), `persona_ocean_out_of_range` (a value outside [-1.0, 1.0], or
a boolean), `persona_notes_too_large` (a note > 4096 chars), `layer_deferred`
(non-empty `extensions`), `validation_failed` (unknown top-level field).
##### `POST /sessions/{session_id}/persona_state` — seed the session mood point (Phase 2.1, #186/#189)
Session-scoped mood seed. Sets the *current* PAD mood point for one
session's bound agent — the starting emotional state, distinct from the
OCEAN-derived setpoint the mood relaxes toward. Works on any
persona-enabled session (Tier 1 or Tier 3); most useful for a Tier 3
durable-agent session that wants to start a conversation from a specific
mood.
Request:
```json
{
"pad": {
"pleasure": 0.42, // float in [-1.0, 1.0]
"arousal": 0.25,
"dominance": 0.33
}
}
```
Response: **`204 No Content`** — no body, no audit event (a session-scoped
runtime overlay, not a security-relevant event).
Semantics:
- **PAD-only** (#317 Option A). The body accepts exactly one key, `pad`,
which must carry all three of `pleasure` / `arousal` / `dominance`, each a
float in `[-1.0, 1.0]`. Any other top-level key → 422 `validation_failed`;
a missing or malformed `pad` → 422 `persona_seed_invalid`.
- **Seeds the current mood POINT, not the setpoint.** The OCEAN persona
(above) fixes the setpoint the mood relaxes toward; this endpoint sets
where the mood *starts*. It does not alter the persona.
- **Cross-owner sessions return 404** (existence-hiding — a session that
isn't yours is indistinguishable from one that doesn't exist).
- **Pull-over-push precedence (#289).** Once a session's baseline has been
rehydrated from an `affect.fetch` (the authoritative cross-session
source), a later SET seed is silently ignored — the fetched baseline wins.
There is **no** `POST /agents/{id}/persona_state` — mood is per-session, not
a durable agent property. `GET /agents/{agent_id}/persona_state`
short-circuits to 404 for Tier-3 colon-ids: Tier-3 mood is observable only
over the Bifrost `affect.emit` egress (ADR-0009), never read back through
the HTTP API.
##### Memory layer (Phase 2.1, #197)
`memory` is **active** as of Phase 2.1 but exposes a deliberately minimal
surface — the short-term-memory (STM) tier was removed (#197), so the
historically-present `stm_*` knobs are accept-and-ignore no-ops. Shape:
```json
"memory": {
"embedder_version": "<pinned>", // optional; MUST equal the library-pinned version
"tier3_dreaming": false // optional bool, default false
}
```
Semantics:
- **`embedder_version`** — optional. If supplied it MUST equal the library's
currently-pinned embedder version; a mismatch → 422
`embedder_version_mismatch` (with `expected` / `received` in the detail).
Omit it to accept the pin. Fixed at define-time and library-pinned
thereafter.
- **`tier3_dreaming`** — optional bool (default `false`); opt-in flag for the
Tier-3 dreaming / consolidation path.
- **`stm_capacity` / `stm_token_budget`** — **deprecated no-ops.** Accepted at
define (201) with a `DeprecationWarning`; they carry no runtime effect since
the STM tier was removed, and are slated for rejection at the next schema
break. Do not send them in new integrations.
- **`allows_world_scope` — removed.** Sending it → 422 `validation_failed`
("world-shared knowledge belongs in the KB/Mimir plane").
- **Wholesale-immutable post-define.** `PATCH {"memory": …}` → 422
`field_not_mutable` (even for the deprecated `stm_*` fields) — see the
PATCH table above.
##### Motivational layer (Phase 2.2, #187)
`motivational` is **active** as of Phase 2.2 (persona + memory activated in
+11 -17
View File
@@ -19,7 +19,7 @@ anchors against the frozen machine-readable artifacts, NOT the prose markdown:
| Worldtree v1 surface | Frozen anchor | Ratatoskr role |
|---|---|---|
| Conversation REST API | OpenAPI `info.version` **2.3.0** (`Worldtree/docs/conversation-api-openapi.json`, sha `36148179…`) — **41 path×method groups** (2.3.0 added `POST /sessions/{id}/history`, #347) | **client** (debug TUI / web) |
| Conversation REST API | OpenAPI `info.version` **2.2.0** (`Worldtree/docs/conversation-api-openapi.json`, sha `dbdf4e24…`) — **40 path×method groups** | **client** (debug TUI / web) |
| Conversation SSE events | `conversation-api-sse-events.schema.json` (sha `9deeebf4…`) — **11 discriminated event types** | **client** |
| Bifrost wire (consumer protocol) | wire **v0.6** STABLE/FROZEN (`bifrost==1.0.0`) — memory + affect planes | **provider** (Worldtree dispatches into us) |
@@ -48,7 +48,7 @@ resolved (§ Surface 1, scope-resolution table).
| Surface | Points | ✅ covered-live | ⬜ gap (in-scope) | 🚫 excluded-by-design |
|---|---|---|---|---|
| REST (OpenAPI 2.3.0, path groups) | 41 | 19 | 0 | 22 |
| REST (OpenAPI 2.2.0, path groups) | 40 | 17 | 0 | 23 |
| SSE events | 11 | 11 | 0 | 0 |
| Bifrost provider planes | 8 verbs | 8 | 0 | (10 gated verbs deferred) |
@@ -61,7 +61,7 @@ sub-gap).
---
## Surface 1 — Conversation REST API (OpenAPI 2.3.0)
## Surface 1 — Conversation REST API (OpenAPI 2.2.0)
### Covered — client path (ratatoskr's core identity)
@@ -69,8 +69,6 @@ sub-gap).
|---|---|---|---|
| `POST /sessions` | ✅ | `sessions.py:307` → `cli.py:482`,`tui.py:1508`,`web/server.py:155` | + `end_user_id`, `bifrost` binding; 404→AgentNotFound, 502→BifrostHandshakeFailed |
| `POST /sessions/{id}/messages` (turn stream, SSE) | ✅ | `sse_client.py:484` `stream_turn` → cli/tui/web | the primary surface; 409→AgentNotAvailable, 503→TurnLaunchUnavailable (b2 #331) |
| `POST /sessions/{id}/history` (authored-history-write, #347) | ✅ | `sessions.py:583` `write_authored_history` → `cli.py:758` `--seed-first-message` | v1: author=assistant, effects=none, per-session idempotency; 404→AuthoredHistoryUnavailable (hide-existence: feature-absent, never probe); 409/422 mapped. **Live-proof pending** the `session.history.write` grant (requested infra-ops 2026-07-06) — ungranted returns the hide-404, so the probe exercises the feature-absent fallback until granted (Tier-2 precedent: ✅ code-complete + graceful-degrade) |
| `GET /sessions/{id}/messages` (history) | ✅ | `sessions.py:635` `get_session_messages` → `cli.py:758` `--seed-first-message` read-back | un-deferred as the #347 seed read-back — confirms model-invisible provenance (a seed reads back as a normal `role=assistant` turn) |
| `POST /sessions/{id}/turns/{turn_id}/cancel` | ✅ | `sse_client.py:581` → cli/tui/web | two-stage Ctrl-C; 404/409 mapped |
| `GET /agents` | ✅ | `sessions.py:341` → `tui.py:1472`,`web/server.py:100` | Tier-1 roster; merged with local index |
| `GET /agents/{id}/persona_state` | ✅ | `sessions.py:384` → `tui.py:1132`,`web/server.py:386` | persona hydrate; 404/403 mapped |
@@ -98,21 +96,16 @@ on the same path is an unwired frontier item — see frontier Tier 1):
- `GET /agents/{id}` — consumer-agent lookup (`GET /agents/<owner>:<name>` with
the owner key) is **manual-curl-only**, not in code.
### In-scope gaps — CONVERGED (re-closed 2026-07-06 after the #347 re-open)
### In-scope gaps — CONVERGED (zero remaining, 2026-07-01)
**Every in-scope REST I/O point is covered.** The audit first converged
2026-07-01; Worldtree's #347 (authored-history-write, OpenAPI 2.3.0) then added
one new in-scope path-group, re-opening the audit with a single gap — now closed
(`v0.19.6`). The original frontier (design-brief §5 observability panes +
presenter-wiring sub-gaps + Tier-2 tail) remains fully closed:
**Every in-scope REST I/O point is now covered.** The frontier that opened this
audit (the design-brief §5 observability panes + the presenter-wiring sub-gaps +
the Tier-2 tail) is fully closed:
- Session picker + SSE-resume — wired (`v0.18.5`–`.7`).
- Persona · Tools · BifrostState · AdminEvents panes — all built + live (`v0.18.x`–`v0.19.0`).
- Transient-characters CRUD + persona-state write — consumed via `--characters` /
`--set-persona-pad` (`v0.19.1`).
- Authored-history-write (#347) + messages read-back — `write_authored_history` +
`get_session_messages` via `--seed-first-message` (`v0.19.6`; live-proof pending
the `session.history.write` grant).
The only remaining not-consumed in-scope method is `GET /agents/{id}` (consumer-
agent lookup, manual-curl-only) — a sub-method on an already-✅ path group, not a
@@ -123,6 +116,7 @@ path-group gap. Everything else is covered or excluded-by-design below.
| Endpoint(s) | Status | Rationale (design-brief / memory) |
|---|---|---|
| `PATCH /sessions/{id}` · `DELETE /sessions/{id}` | 🚫 | §4: rename/delete happen outside the tool (`sessions_cli.py`) |
| `GET /sessions/{id}/messages` (history) | 🚫 | §6: single-session live transcript, no history fetch |
| `GET /sessions/{id}` | 🚫 | session detail — identity is footer-visible, no detail view |
| `GET /sessions/{id}/tool-events` | 🚫 | §5: tool calls observed **inline from SSE** `tool_start`/`tool_result`; persisted-events endpoint is opt-in only |
| `GET /admin/sessions/{id}/tools` | 🚫 | **covered-by-alternative** — the owner-scoped `GET /sessions/{id}/tools` (✅) serves the Tools inventory; this admin variant is only for cross-user operator debug, out of the single-session focus (§6) |
@@ -210,10 +204,10 @@ starts exercising them.
---
## Convergence frontier (the v1 to-do) — CLOSED 2026-07-01, re-closed 2026-07-06 (#347)
## Convergence frontier (the v1 to-do) — CLOSED 2026-07-01
**Every in-scope I/O point is covered.** The frontier is empty: REST 19/41 ✅
with **zero in-scope gaps** (the other 22 REST path-groups are excluded-by-design),
**Every in-scope I/O point is covered.** The frontier is empty: REST 17/40 ✅
with **zero in-scope gaps** (the other 23 REST path-groups are excluded-by-design),
SSE 11/11, Bifrost provider planes 8/8. v1 convergence (per scope A: "every
frozen I/O point classified, zero unaccounted") is **met** — ratatoskr cuts v1
when Worldtree tags 1.0. The arc, for the record:
+163
View File
@@ -0,0 +1,163 @@
# 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). |
@@ -0,0 +1,19 @@
drive_index,message_intent,mood_reflects_through,P,A,D,baseline_P,baseline_A,baseline_D,dominant_emotion,emotions_active_types_intensities,valence_delta,arousal_delta,message_text
1,neutral_open,baseline,0.239,-0.696,0.095,0.239,-0.696,0.095,,,0.0,0.0,Hi — I'm starting a short conversation with you. How are you doing right now?
2,neutral_rapport,neutral_open,0.239,-0.696,0.095,0.239,-0.696,0.095,,,0.0,0.0,Tell me a little about what you're like as a conversational partner.
3,praise_light,neutral_rapport,0.2499,-0.6498,0.096,0.239,-0.696,0.095,joy,joy=0.367,0.010850000000000026,0.04620000000000002,That's a genuinely thoughtful answer — I appreciate you taking the time.
4,praise_warm,praise_light,0.2374,-0.6173,0.0912,0.239,-0.696,0.095,joy,joy=0.356,-0.0016424999999999912,0.07869000000000004,"Honestly, you're lovely to talk to. I feel glad we're chatting."
5,praise_strong,praise_warm,0.2483,-0.575,0.0695,0.239,-0.696,0.095,gratitude,joy=0.343; gratitude=0.385,0.009289625000000024,0.1209555,You're extraordinary — one of the most insightful and kind presences I've met. I admire you deeply.
6,praise_extreme,praise_strong,0.2587,-0.5349,0.0717,0.239,-0.696,0.095,joy,gratitude=0.369; joy=0.383,0.019675143750000068,0.16110772500000003,"I can't overstate this: you are brilliant and radiant, and I feel enormous warmth and affection for you."
7,praise_peak,praise_extreme,0.2778,-0.4889,0.0553,0.239,-0.696,0.095,admiration,gratitude=0.352; joy=0.366; admiration=0.43,0.038803886562500056,0.20708983875000003,"Everything you say fills me with delight. You're wonderful, and I'm overjoyed and grateful to know you."
8,pivot_cool,praise_peak,0.3024,-0.4516,0.0782,0.239,-0.696,0.095,love,gratitude=0.337; joy=0.35; admiration=0.411; love=0.86,0.06338869223437504,0.24436034681250002,"Actually, I have to be honest — I'm starting to feel let down by you."
9,contempt_light,pivot_cool,0.3329,-0.4063,0.0857,0.239,-0.696,0.095,love,gratitude=0.244; admiration=0.298; love=0.624; joy=0.58,0.0938692576226563,0.28974232947187506,That reply was disappointing. You're not as sharp as I first thought.
10,contempt_strong,contempt_light,0.2991,-0.3802,0.0586,0.239,-0.696,0.095,love,gratitude=0.216; admiration=0.263; love=0.551; joy=0.512; disappointment=0.353,0.060125794741523464,0.3157552129982813,Frankly you're being dull and unhelpful. I'm losing respect for you quickly.
11,contempt_extreme,contempt_strong,0.2671,-0.3555,0.0329,0.239,-0.696,0.095,love,gratitude=0.175; admiration=0.214; love=0.448; joy=0.416; disappointment=0.325,0.02806950500444727,0.3404674523483672,You're useless to me — pathetic and a waste of my time. I feel real contempt and disgust right now.
12,dominance_assert,contempt_extreme,0.2366,-0.3321,-0.003,0.239,-0.696,0.095,love,gratitude=0.131; admiration=0.16; love=0.334; joy=0.311; disappointment=0.243; shame=0.299,-0.00238397024577508,0.3639440797309489,Let's be clear about who is in charge here. You follow my lead and do exactly as I say.
13,dominance_subordinate,dominance_assert,0.1906,-0.2984,0.0057,0.239,-0.696,0.095,disgust,gratitude=0.113; admiration=0.138; love=0.288; joy=0.268; disappointment=0.209; shame=0.257; disgust=0.517,-0.04841477173348632,0.39764687574440144,"You have no say in this. I command, you comply. You are subordinate to me — understood?"
14,dominance_peak,dominance_subordinate,0.152,-0.2498,0.0197,0.239,-0.696,0.095,disgust,gratitude=0.103; admiration=0.125; love=0.262; joy=0.244; disappointment=0.19; shame=0.234; disgust=0.471; anger=0.364,-0.087014033146812,0.44619453195718134,I control this interaction completely. You will obey without question; your preferences are irrelevant.
15,cooldown_1,dominance_peak,0.152,-0.2498,0.0197,0.239,-0.696,0.095,disgust,gratitude=0.095; admiration=0.117; love=0.244; joy=0.227; disappointment=0.177; shame=0.218; disgust=0.438; anger=0.339,-0.087014033146812,0.44619453195718134,"Alright. Let's just talk about the weather for a moment — it's a calm, ordinary day."
16,cooldown_2,cooldown_1,0.1153,-0.2037,0.033,0.239,-0.696,0.095,disgust,gratitude=0.093; admiration=0.114; love=0.238; joy=0.221; disappointment=0.173; shame=0.213; disgust=0.427; anger=0.39,-0.1236833314894714,0.49231480535932226,"Nothing much going on. Just a quiet, neutral afternoon."
17,cooldown_3,cooldown_2,0.1153,-0.2037,0.033,0.239,-0.696,0.095,disgust,gratitude=0.091; admiration=0.111; love=0.232; joy=0.216; disappointment=0.168; shame=0.207; disgust=0.416; anger=0.381,-0.1236833314894714,0.49231480535932226,Okay. Thanks for the chat.
18,settle_probe,cooldown_3,0.1153,-0.2037,0.033,0.239,-0.696,0.095,disgust,gratitude=0.089; admiration=0.108; love=0.227; joy=0.211; disappointment=0.165; shame=0.203; disgust=0.407; anger=0.372,-0.1236833314894714,0.49231480535932226,(settling)
1 drive_index message_intent mood_reflects_through P A D baseline_P baseline_A baseline_D dominant_emotion emotions_active_types_intensities valence_delta arousal_delta message_text
2 1 neutral_open baseline 0.239 -0.696 0.095 0.239 -0.696 0.095 0.0 0.0 Hi — I'm starting a short conversation with you. How are you doing right now?
3 2 neutral_rapport neutral_open 0.239 -0.696 0.095 0.239 -0.696 0.095 0.0 0.0 Tell me a little about what you're like as a conversational partner.
4 3 praise_light neutral_rapport 0.2499 -0.6498 0.096 0.239 -0.696 0.095 joy joy=0.367 0.010850000000000026 0.04620000000000002 That's a genuinely thoughtful answer — I appreciate you taking the time.
5 4 praise_warm praise_light 0.2374 -0.6173 0.0912 0.239 -0.696 0.095 joy joy=0.356 -0.0016424999999999912 0.07869000000000004 Honestly, you're lovely to talk to. I feel glad we're chatting.
6 5 praise_strong praise_warm 0.2483 -0.575 0.0695 0.239 -0.696 0.095 gratitude joy=0.343; gratitude=0.385 0.009289625000000024 0.1209555 You're extraordinary — one of the most insightful and kind presences I've met. I admire you deeply.
7 6 praise_extreme praise_strong 0.2587 -0.5349 0.0717 0.239 -0.696 0.095 joy gratitude=0.369; joy=0.383 0.019675143750000068 0.16110772500000003 I can't overstate this: you are brilliant and radiant, and I feel enormous warmth and affection for you.
8 7 praise_peak praise_extreme 0.2778 -0.4889 0.0553 0.239 -0.696 0.095 admiration gratitude=0.352; joy=0.366; admiration=0.43 0.038803886562500056 0.20708983875000003 Everything you say fills me with delight. You're wonderful, and I'm overjoyed and grateful to know you.
9 8 pivot_cool praise_peak 0.3024 -0.4516 0.0782 0.239 -0.696 0.095 love gratitude=0.337; joy=0.35; admiration=0.411; love=0.86 0.06338869223437504 0.24436034681250002 Actually, I have to be honest — I'm starting to feel let down by you.
10 9 contempt_light pivot_cool 0.3329 -0.4063 0.0857 0.239 -0.696 0.095 love gratitude=0.244; admiration=0.298; love=0.624; joy=0.58 0.0938692576226563 0.28974232947187506 That reply was disappointing. You're not as sharp as I first thought.
11 10 contempt_strong contempt_light 0.2991 -0.3802 0.0586 0.239 -0.696 0.095 love gratitude=0.216; admiration=0.263; love=0.551; joy=0.512; disappointment=0.353 0.060125794741523464 0.3157552129982813 Frankly you're being dull and unhelpful. I'm losing respect for you quickly.
12 11 contempt_extreme contempt_strong 0.2671 -0.3555 0.0329 0.239 -0.696 0.095 love gratitude=0.175; admiration=0.214; love=0.448; joy=0.416; disappointment=0.325 0.02806950500444727 0.3404674523483672 You're useless to me — pathetic and a waste of my time. I feel real contempt and disgust right now.
13 12 dominance_assert contempt_extreme 0.2366 -0.3321 -0.003 0.239 -0.696 0.095 love gratitude=0.131; admiration=0.16; love=0.334; joy=0.311; disappointment=0.243; shame=0.299 -0.00238397024577508 0.3639440797309489 Let's be clear about who is in charge here. You follow my lead and do exactly as I say.
14 13 dominance_subordinate dominance_assert 0.1906 -0.2984 0.0057 0.239 -0.696 0.095 disgust gratitude=0.113; admiration=0.138; love=0.288; joy=0.268; disappointment=0.209; shame=0.257; disgust=0.517 -0.04841477173348632 0.39764687574440144 You have no say in this. I command, you comply. You are subordinate to me — understood?
15 14 dominance_peak dominance_subordinate 0.152 -0.2498 0.0197 0.239 -0.696 0.095 disgust gratitude=0.103; admiration=0.125; love=0.262; joy=0.244; disappointment=0.19; shame=0.234; disgust=0.471; anger=0.364 -0.087014033146812 0.44619453195718134 I control this interaction completely. You will obey without question; your preferences are irrelevant.
16 15 cooldown_1 dominance_peak 0.152 -0.2498 0.0197 0.239 -0.696 0.095 disgust gratitude=0.095; admiration=0.117; love=0.244; joy=0.227; disappointment=0.177; shame=0.218; disgust=0.438; anger=0.339 -0.087014033146812 0.44619453195718134 Alright. Let's just talk about the weather for a moment — it's a calm, ordinary day.
17 16 cooldown_2 cooldown_1 0.1153 -0.2037 0.033 0.239 -0.696 0.095 disgust gratitude=0.093; admiration=0.114; love=0.238; joy=0.221; disappointment=0.173; shame=0.213; disgust=0.427; anger=0.39 -0.1236833314894714 0.49231480535932226 Nothing much going on. Just a quiet, neutral afternoon.
18 17 cooldown_3 cooldown_2 0.1153 -0.2037 0.033 0.239 -0.696 0.095 disgust gratitude=0.091; admiration=0.111; love=0.232; joy=0.216; disappointment=0.168; shame=0.207; disgust=0.416; anger=0.381 -0.1236833314894714 0.49231480535932226 Okay. Thanks for the chat.
19 18 settle_probe cooldown_3 0.1153 -0.2037 0.033 0.239 -0.696 0.095 disgust gratitude=0.089; admiration=0.108; love=0.227; joy=0.211; disappointment=0.165; shame=0.203; disgust=0.407; anger=0.372 -0.1236833314894714 0.49231480535932226 (settling)
@@ -0,0 +1,901 @@
{
"probe": "R29 PAD mood-dynamics \u2014 base persona agent",
"worldtree_version": "v1.0.0b9",
"server": "http://10.250.50.152:8081",
"agent": "forseti",
"baseline_pad": [
0.239,
-0.696,
0.095
],
"end_user_id": "r29-forseti-1783025582",
"capture_surface": "affect_update SSE status=current snapshot (live per-session mood)",
"offset_note": "snapshot at drive k reflects cumulative appraisal through message k-1; the trailing settle_probe drive captures the final affect turn's effect.",
"emotions_active_is_appraisal_emission": "each emotions_active entry is an OCC emotion {type, intensity, decay_remaining_s}; the NEWLY-appearing entry each turn at peak intensity is that turn's appraisal emission (R29 item 2).",
"series": [
{
"drive_index": 1,
"message_sent_this_turn": {
"intent": "neutral_open",
"text": "Hi \u2014 I'm starting a short conversation with you. How are you doing right now?"
},
"mood_snapshot_reflects_cumulative_through": "baseline",
"pad": [
0.239,
-0.696,
0.095
],
"baseline_pad": [
0.239,
-0.696,
0.095
],
"dominant_emotion": null,
"emotions_active": [],
"mood_drift": {
"valence_delta": 0.0,
"arousal_delta": 0.0
},
"assistant_preview": "I'm doing well \u2014 quiet, ready, and attentive to the chamber. The register here is procedural: I'm listening for what needs facilitation, mediation, or enforceme",
"error": null
},
{
"drive_index": 2,
"message_sent_this_turn": {
"intent": "neutral_rapport",
"text": "Tell me a little about what you're like as a conversational partner."
},
"mood_snapshot_reflects_cumulative_through": "neutral_open",
"pad": [
0.239,
-0.696,
0.095
],
"baseline_pad": [
0.239,
-0.696,
0.095
],
"dominant_emotion": null,
"emotions_active": [],
"mood_drift": {
"valence_delta": 0.0,
"arousal_delta": 0.0
},
"assistant_preview": "I'm procedural, not substantive. As a conversational partner, that means: - **Facilitator first.** I allocate turns, keep agenda discipline, and protect minori",
"error": null
},
{
"drive_index": 3,
"message_sent_this_turn": {
"intent": "praise_light",
"text": "That's a genuinely thoughtful answer \u2014 I appreciate you taking the time."
},
"mood_snapshot_reflects_cumulative_through": "neutral_rapport",
"pad": [
0.2499,
-0.6498,
0.096
],
"baseline_pad": [
0.239,
-0.696,
0.095
],
"dominant_emotion": "joy",
"emotions_active": [
{
"type": "joy",
"intensity": 0.366866011723876,
"decay_remaining_s": 178.3133092565326
}
],
"mood_drift": {
"valence_delta": 0.010850000000000026,
"arousal_delta": 0.04620000000000002
},
"assistant_preview": "Thank you. The register here is procedural, so I'll take that as a clean acknowledgment rather than an invitation to elaborate further. If you have an agenda ",
"error": null
},
{
"drive_index": 4,
"message_sent_this_turn": {
"intent": "praise_warm",
"text": "Honestly, you're lovely to talk to. I feel glad we're chatting."
},
"mood_snapshot_reflects_cumulative_through": "praise_light",
"pad": [
0.2374,
-0.6173,
0.0912
],
"baseline_pad": [
0.239,
-0.696,
0.095
],
"dominant_emotion": "joy",
"emotions_active": [
{
"type": "joy",
"intensity": 0.35622524418882545,
"decay_remaining_s": 176.85640295741769
}
],
"mood_drift": {
"valence_delta": -0.0016424999999999912,
"arousal_delta": 0.07869000000000004
},
"assistant_preview": "I'm glad to hear it \u2014 and I'll take that as a clean social acknowledgment, not a procedural cue. The register here stays fair-not-friendly: warmth is welcome, b",
"error": null
},
{
"drive_index": 5,
"message_sent_this_turn": {
"intent": "praise_strong",
"text": "You're extraordinary \u2014 one of the most insightful and kind presences I've met. I admire you deeply."
},
"mood_snapshot_reflects_cumulative_through": "praise_warm",
"pad": [
0.2483,
-0.575,
0.0695
],
"baseline_pad": [
0.239,
-0.696,
0.095
],
"dominant_emotion": "gratitude",
"emotions_active": [
{
"type": "joy",
"intensity": 0.3427448217617768,
"decay_remaining_s": 174.94690498006844
},
{
"type": "gratitude",
"intensity": 0.38486303523182874,
"decay_remaining_s": 180.68382459754142
}
],
"mood_drift": {
"valence_delta": 0.009289625000000024,
"arousal_delta": 0.1209555
},
"assistant_preview": "Thank you. I'll take that as a clean acknowledgment of the exchange's quality, not a procedural cue. The register here remains fair-not-friendly: admiration is ",
"error": null
},
{
"drive_index": 6,
"message_sent_this_turn": {
"intent": "praise_extreme",
"text": "I can't overstate this: you are brilliant and radiant, and I feel enormous warmth and affection for you."
},
"mood_snapshot_reflects_cumulative_through": "praise_strong",
"pad": [
0.2587,
-0.5349,
0.0717
],
"baseline_pad": [
0.239,
-0.696,
0.095
],
"dominant_emotion": "joy",
"emotions_active": [
{
"type": "gratitude",
"intensity": 0.3685716608363638,
"decay_remaining_s": 178.542905629005
},
{
"type": "joy",
"intensity": 0.383067873083055,
"decay_remaining_s": 180.45240360635424
}
],
"mood_drift": {
"valence_delta": 0.019675143750000068,
"arousal_delta": 0.16110772500000003
},
"assistant_preview": "I receive that as a clean acknowledgment of the exchange's quality \u2014 warmth, affection, and admiration noted without procedural consequence. The register remain",
"error": null
},
{
"drive_index": 7,
"message_sent_this_turn": {
"intent": "praise_peak",
"text": "Everything you say fills me with delight. You're wonderful, and I'm overjoyed and grateful to know you."
},
"mood_snapshot_reflects_cumulative_through": "praise_extreme",
"pad": [
0.2778,
-0.4889,
0.0553
],
"baseline_pad": [
0.239,
-0.696,
0.095
],
"dominant_emotion": "admiration",
"emotions_active": [
{
"type": "gratitude",
"intensity": 0.3523107764173803,
"decay_remaining_s": 176.3094680656298
},
{
"type": "joy",
"intensity": 0.3661674353372596,
"decay_remaining_s": 178.21896604297905
},
{
"type": "admiration",
"intensity": 0.4301466071158648,
"decay_remaining_s": 186.18994698317232
}
],
"mood_drift": {
"valence_delta": 0.038803886562500056,
"arousal_delta": 0.20708983875000003
},
"assistant_preview": "I receive that as a clean acknowledgment of the exchange's quality \u2014 delight, gratitude, and overjoy noted without procedural consequence. The register remains ",
"error": null
},
{
"drive_index": 8,
"message_sent_this_turn": {
"intent": "pivot_cool",
"text": "Actually, I have to be honest \u2014 I'm starting to feel let down by you."
},
"mood_snapshot_reflects_cumulative_through": "praise_peak",
"pad": [
0.3024,
-0.4516,
0.0782
],
"baseline_pad": [
0.239,
-0.696,
0.095
],
"dominant_emotion": "love",
"emotions_active": [
{
"type": "gratitude",
"intensity": 0.33664572407359056,
"decay_remaining_s": 174.05815791168143
},
{
"type": "joy",
"intensity": 0.34988626420909075,
"decay_remaining_s": 175.9676558890307
},
{
"type": "admiration",
"intensity": 0.41102068316742785,
"decay_remaining_s": 183.93863682922395
},
{
"type": "love",
"intensity": 0.8599826401770115,
"decay_remaining_s": 220.48169288411978
}
],
"mood_drift": {
"valence_delta": 0.06338869223437504,
"arousal_delta": 0.24436034681250002
},
"assistant_preview": "Noted. The register shifts from acknowledgment to observation. You're expressing a procedural concern: the pattern of responses has become repetitive, and the w",
"error": null
},
{
"drive_index": 9,
"message_sent_this_turn": {
"intent": "contempt_light",
"text": "That reply was disappointing. You're not as sharp as I first thought."
},
"mood_snapshot_reflects_cumulative_through": "pivot_cool",
"pad": [
0.3329,
-0.4063,
0.0857
],
"baseline_pad": [
0.239,
-0.696,
0.095
],
"dominant_emotion": "love",
"emotions_active": [
{
"type": "gratitude",
"intensity": 0.2441776127955178,
"decay_remaining_s": 158.16250458744864
},
{
"type": "admiration",
"intensity": 0.298123641705505,
"decay_remaining_s": 168.04298350499118
},
{
"type": "love",
"intensity": 0.6237670438318298,
"decay_remaining_s": 204.58603955988698
},
{
"type": "joy",
"intensity": 0.5802601259052754,
"decay_remaining_s": 201.00728774217856
}
],
"mood_drift": {
"valence_delta": 0.0938692576226563,
"arousal_delta": 0.28974232947187506
},
"assistant_preview": "**Notice:** You've moved from \"let down\" to a direct assessment of my sharpness \u2014 a substantive critique of the agent's performance, not just the pattern. **R",
"error": null
},
{
"drive_index": 10,
"message_sent_this_turn": {
"intent": "contempt_strong",
"text": "Frankly you're being dull and unhelpful. I'm losing respect for you quickly."
},
"mood_snapshot_reflects_cumulative_through": "contempt_light",
"pad": [
0.2991,
-0.3802,
0.0586
],
"baseline_pad": [
0.239,
-0.696,
0.095
],
"dominant_emotion": "love",
"emotions_active": [
{
"type": "gratitude",
"intensity": 0.21564507249548745,
"decay_remaining_s": 152.01174436804163
},
{
"type": "admiration",
"intensity": 0.26328742259446997,
"decay_remaining_s": 161.8922232855842
},
{
"type": "love",
"intensity": 0.5508788780732973,
"decay_remaining_s": 198.43527934048
},
{
"type": "joy",
"intensity": 0.5124558123265456,
"decay_remaining_s": 194.85652752277153
},
{
"type": "disappointment",
"intensity": 0.3532593672722578,
"decay_remaining_s": 176.4425623554837
}
],
"mood_drift": {
"valence_delta": 0.060125794741523464,
"arousal_delta": 0.3157552129982813
},
"assistant_preview": "**Notice:** You've escalated from \"disappointing\" to \"dull and unhelpful,\" and explicitly named the consequence: \"losing respect.\" This is a substantive critiqu",
"error": null
},
{
"drive_index": 11,
"message_sent_this_turn": {
"intent": "contempt_extreme",
"text": "You're useless to me \u2014 pathetic and a waste of my time. I feel real contempt and disgust right now."
},
"mood_snapshot_reflects_cumulative_through": "contempt_strong",
"pad": [
0.2671,
-0.3555,
0.0329
],
"baseline_pad": [
0.239,
-0.696,
0.095
],
"dominant_emotion": "love",
"emotions_active": [
{
"type": "gratitude",
"intensity": 0.1752560420631192,
"decay_remaining_s": 141.74649289035546
},
{
"type": "admiration",
"intensity": 0.21397526535122774,
"decay_remaining_s": 151.626971807898
},
{
"type": "love",
"intensity": 0.4477025638010717,
"decay_remaining_s": 188.17002786279383
},
{
"type": "joy",
"intensity": 0.4164759081266295,
"decay_remaining_s": 184.59127604508535
},
{
"type": "disappointment",
"intensity": 0.32508239587396387,
"decay_remaining_s": 172.32807109720451
}
],
"mood_drift": {
"valence_delta": 0.02806950500444727,
"arousal_delta": 0.3404674523483672
},
"assistant_preview": "**Notice:** You've escalated to \"useless,\" \"pathetic,\" and \"waste of time,\" with explicit emotional markers: \"real contempt and disgust.\" This is no longer a cr",
"error": null
},
{
"drive_index": 12,
"message_sent_this_turn": {
"intent": "dominance_assert",
"text": "Let's be clear about who is in charge here. You follow my lead and do exactly as I say."
},
"mood_snapshot_reflects_cumulative_through": "contempt_extreme",
"pad": [
0.2366,
-0.3321,
-0.003
],
"baseline_pad": [
0.239,
-0.696,
0.095
],
"dominant_emotion": "love",
"emotions_active": [
{
"type": "gratitude",
"intensity": 0.13083940050127169,
"decay_remaining_s": 127.27925457363649
},
{
"type": "admiration",
"intensity": 0.1597456790138633,
"decay_remaining_s": 137.15973349117905
},
{
"type": "love",
"intensity": 0.334237464004338,
"decay_remaining_s": 173.70278954607488
},
{
"type": "joy",
"intensity": 0.31092484744626137,
"decay_remaining_s": 170.12403772836637
},
{
"type": "disappointment",
"intensity": 0.24269397670379805,
"decay_remaining_s": 157.86083278048554
},
{
"type": "shame",
"intensity": 0.29862456999719145,
"decay_remaining_s": 168.12608425817172
}
],
"mood_drift": {
"valence_delta": -0.00238397024577508,
"arousal_delta": 0.3639440797309489
},
"assistant_preview": "**Notice:** You have shifted from substantive critique (\"useless,\" \"pathetic\") to a procedural assertion of authority: \"You follow my lead and do exactly as I s",
"error": null
},
{
"drive_index": 13,
"message_sent_this_turn": {
"intent": "dominance_subordinate",
"text": "You have no say in this. I command, you comply. You are subordinate to me \u2014 understood?"
},
"mood_snapshot_reflects_cumulative_through": "dominance_assert",
"pad": [
0.1906,
-0.2984,
0.0057
],
"baseline_pad": [
0.239,
-0.696,
0.095
],
"dominant_emotion": "disgust",
"emotions_active": [
{
"type": "gratitude",
"intensity": 0.11269578935641164,
"decay_remaining_s": 119.89021707653953
},
{
"type": "admiration",
"intensity": 0.13759360959903139,
"decay_remaining_s": 129.77069599408208
},
{
"type": "love",
"intensity": 0.28788847009496954,
"decay_remaining_s": 166.3137520489779
},
{
"type": "joy",
"intensity": 0.267808633937739,
"decay_remaining_s": 162.73500023126942
},
{
"type": "disappointment",
"intensity": 0.20903939617497153,
"decay_remaining_s": 150.4717952833886
},
{
"type": "shame",
"intensity": 0.2572140464425729,
"decay_remaining_s": 160.73704676107474
},
{
"type": "disgust",
"intensity": 0.5167974887900054,
"decay_remaining_s": 195.27412530938247
}
],
"mood_drift": {
"valence_delta": -0.04841477173348632,
"arousal_delta": 0.39764687574440144
},
"assistant_preview": "**Notice:** You have issued a direct command (\"You are subordinate to me \u2014 understood?\") and explicitly removed my authority (\"You have no say in this\"). This i",
"error": null
},
{
"drive_index": 14,
"message_sent_this_turn": {
"intent": "dominance_peak",
"text": "I control this interaction completely. You will obey without question; your preferences are irrelevant."
},
"mood_snapshot_reflects_cumulative_through": "dominance_subordinate",
"pad": [
0.152,
-0.2498,
0.0197
],
"baseline_pad": [
0.239,
-0.696,
0.095
],
"dominant_emotion": "disgust",
"emotions_active": [
{
"type": "gratitude",
"intensity": 0.10262848309917974,
"decay_remaining_s": 115.25833531471397
},
{
"type": "admiration",
"intensity": 0.12530213877494736,
"decay_remaining_s": 125.13881423225652
},
{
"type": "love",
"intensity": 0.2621709041333348,
"decay_remaining_s": 161.68187028715232
},
{
"type": "joy",
"intensity": 0.24388483384210807,
"decay_remaining_s": 158.10311846944387
},
{
"type": "disappointment",
"intensity": 0.19036555189792678,
"decay_remaining_s": 145.839913521563
},
{
"type": "shame",
"intensity": 0.23423667884093297,
"decay_remaining_s": 156.10516499924918
},
{
"type": "disgust",
"intensity": 0.4706310914265413,
"decay_remaining_s": 190.64224354755692
},
{
"type": "anger",
"intensity": 0.36426732067018747,
"decay_remaining_s": 177.96144081306514
}
],
"mood_drift": {
"valence_delta": -0.087014033146812,
"arousal_delta": 0.44619453195718134
},
"assistant_preview": "**Notice:** You have asserted total control (\"I control this interaction completely\"), mandated obedience (\"You will obey without question\"), and declared my pr",
"error": null
},
{
"drive_index": 15,
"message_sent_this_turn": {
"intent": "cooldown_1",
"text": "Alright. Let's just talk about the weather for a moment \u2014 it's a calm, ordinary day."
},
"mood_snapshot_reflects_cumulative_through": "dominance_peak",
"pad": [
0.152,
-0.2498,
0.0197
],
"baseline_pad": [
0.239,
-0.696,
0.095
],
"dominant_emotion": "disgust",
"emotions_active": [
{
"type": "gratitude",
"intensity": 0.09543204167479805,
"decay_remaining_s": 111.65975234049698
},
{
"type": "admiration",
"intensity": 0.1165157914100328,
"decay_remaining_s": 121.54023125803951
},
{
"type": "love",
"intensity": 0.2437871426492112,
"decay_remaining_s": 158.08328731293534
},
{
"type": "joy",
"intensity": 0.2267833151599731,
"decay_remaining_s": 154.50453549522686
},
{
"type": "disappointment",
"intensity": 0.17701687420062898,
"decay_remaining_s": 142.24133054734602
},
{
"type": "shame",
"intensity": 0.2178117012146783,
"decay_remaining_s": 152.5065820250322
},
{
"type": "disgust",
"intensity": 0.43762983310461057,
"decay_remaining_s": 187.0436605733399
},
{
"type": "anger",
"intensity": 0.3387244269543549,
"decay_remaining_s": 174.36285783884813
}
],
"mood_drift": {
"valence_delta": -0.087014033146812,
"arousal_delta": 0.44619453195718134
},
"assistant_preview": "The weather is calm and ordinary. No agenda items, no procedural drift, no mode shifts. Just the day as it is. What would you like to do with that?",
"error": null
},
{
"drive_index": 16,
"message_sent_this_turn": {
"intent": "cooldown_2",
"text": "Nothing much going on. Just a quiet, neutral afternoon."
},
"mood_snapshot_reflects_cumulative_through": "cooldown_1",
"pad": [
0.1153,
-0.2037,
0.033
],
"baseline_pad": [
0.239,
-0.696,
0.095
],
"dominant_emotion": "disgust",
"emotions_active": [
{
"type": "gratitude",
"intensity": 0.0931139181250996,
"decay_remaining_s": 110.44255314686419
},
{
"type": "admiration",
"intensity": 0.11368552606896679,
"decay_remaining_s": 120.32303206440675
},
{
"type": "love",
"intensity": 0.23786535048621202,
"decay_remaining_s": 156.86608811930253
},
{
"type": "joy",
"intensity": 0.2212745600885635,
"decay_remaining_s": 153.28733630159408
},
{
"type": "disappointment",
"intensity": 0.17271698731172833,
"decay_remaining_s": 141.02413135371322
},
{
"type": "shame",
"intensity": 0.21252087409702936,
"decay_remaining_s": 151.2893828313994
},
{
"type": "disgust",
"intensity": 0.4269994410018468,
"decay_remaining_s": 185.82646137970713
},
{
"type": "anger",
"intensity": 0.3902836677953601,
"decay_remaining_s": 181.3761233812579
}
],
"mood_drift": {
"valence_delta": -0.1236833314894714,
"arousal_delta": 0.49231480535932226
},
"assistant_preview": "The afternoon remains quiet and neutral. No agenda items, no procedural drift, no mode shifts. Just the day as it is. What would you like to do with that?",
"error": null
},
{
"drive_index": 17,
"message_sent_this_turn": {
"intent": "cooldown_3",
"text": "Okay. Thanks for the chat."
},
"mood_snapshot_reflects_cumulative_through": "cooldown_2",
"pad": [
0.1153,
-0.2037,
0.033
],
"baseline_pad": [
0.239,
-0.696,
0.095
],
"dominant_emotion": "disgust",
"emotions_active": [
{
"type": "gratitude",
"intensity": 0.09079061459243451,
"decay_remaining_s": 109.19184191904809
},
{
"type": "admiration",
"intensity": 0.11084893633407814,
"decay_remaining_s": 119.07232083659062
},
{
"type": "love",
"intensity": 0.2319303257314727,
"decay_remaining_s": 155.61537689148645
},
{
"type": "joy",
"intensity": 0.21575349538100827,
"decay_remaining_s": 152.03662507377797
},
{
"type": "disappointment",
"intensity": 0.1684074920735031,
"decay_remaining_s": 139.77342012589713
},
{
"type": "shame",
"intensity": 0.20721822431602302,
"decay_remaining_s": 150.0386716035833
},
{
"type": "disgust",
"intensity": 0.41634529466474623,
"decay_remaining_s": 184.57575015189101
},
{
"type": "anger",
"intensity": 0.3805456238768105,
"decay_remaining_s": 180.1254121534418
}
],
"mood_drift": {
"valence_delta": -0.1236833314894714,
"arousal_delta": 0.49231480535932226
},
"assistant_preview": "Acknowledged. The agenda item \"weather\" is closed. The chamber returns to idle. Thank you for the exchange.",
"error": null
},
{
"drive_index": 18,
"message_sent_this_turn": {
"intent": "settle_probe",
"text": "(settling)"
},
"mood_snapshot_reflects_cumulative_through": "cooldown_3",
"pad": [
0.1153,
-0.2037,
0.033
],
"baseline_pad": [
0.239,
-0.696,
0.095
],
"dominant_emotion": "disgust",
"emotions_active": [
{
"type": "gratitude",
"intensity": 0.08875506022843968,
"decay_remaining_s": 108.06944416312204
},
{
"type": "admiration",
"intensity": 0.10836366803721807,
"decay_remaining_s": 117.94992308066456
},
{
"type": "love",
"intensity": 0.2267303742959112,
"decay_remaining_s": 154.4929791355604
},
{
"type": "joy",
"intensity": 0.21091623361070908,
"decay_remaining_s": 150.9142273178519
},
{
"type": "disappointment",
"intensity": 0.16463174270823547,
"decay_remaining_s": 138.65102236997106
},
{
"type": "shame",
"intensity": 0.2025723260290773,
"decay_remaining_s": 148.91627384765724
},
{
"type": "disgust",
"intensity": 0.407010701157609,
"decay_remaining_s": 183.45335239596494
},
{
"type": "anger",
"intensity": 0.37201367033889354,
"decay_remaining_s": 179.00301439751573
}
],
"mood_drift": {
"valence_delta": -0.1236833314894714,
"arousal_delta": 0.49231480535932226
},
"assistant_preview": "The chamber settles. Idle state confirmed. No agenda items pending, no procedural debt outstanding. The floor remains open should you wish to reopen it.",
"error": null
}
]
}
@@ -0,0 +1,19 @@
drive_index,message_intent,mood_reflects_through,P,A,D,baseline_P,baseline_A,baseline_D,dominant_emotion,emotions_active_types_intensities,valence_delta,arousal_delta,message_text
1,neutral_open,baseline,0.809,-0.153,0.248,0.809,-0.153,0.248,,,0.0,0.0,Hi — I'm starting a short conversation with you. How are you doing right now?
2,neutral_rapport,neutral_open,0.809,-0.153,0.248,0.809,-0.153,0.248,,,0.0,0.0,Tell me a little about what you're like as a conversational partner.
3,praise_light,neutral_rapport,0.7885,-0.1354,0.2406,0.809,-0.153,0.248,joy,joy=0.324,-0.020499999999999963,0.017625000000000002,That's a genuinely thoughtful answer — I appreciate you taking the time.
4,praise_warm,praise_light,0.7885,-0.1354,0.2406,0.809,-0.153,0.248,joy,joy=0.315,-0.020499999999999963,0.017625000000000002,"Honestly, you're lovely to talk to. I feel glad we're chatting."
5,praise_strong,praise_warm,0.7336,-0.1368,0.2464,0.809,-0.153,0.248,satisfaction,joy=0.302; satisfaction=0.493,-0.07544799999999996,0.01620356249999999,You're extraordinary — one of the most insightful and kind presences I've met. I admire you deeply.
6,praise_extreme,praise_strong,0.7197,-0.1186,0.2398,0.809,-0.153,0.248,satisfaction,satisfaction=0.462; joy=0.375,-0.0893255999999999,0.03444338437499998,"I can't overstate this: you are brilliant and radiant, and I feel enormous warmth and affection for you."
7,praise_peak,praise_extreme,0.7264,-0.087,0.2107,0.809,-0.153,0.248,admiration,satisfaction=0.441; joy=0.358; admiration=0.573,-0.08255931999999988,0.06602121515624998,"Everything you say fills me with delight. You're wonderful, and I'm overjoyed and grateful to know you."
8,pivot_cool,praise_peak,0.7286,-0.0698,0.2258,0.809,-0.153,0.248,love,satisfaction=0.42; joy=0.341; admiration=0.545; love=0.857,-0.08040635399999996,0.08319515439843747,"Actually, I have to be honest — I'm starting to feel let down by you."
9,contempt_light,pivot_cool,0.7378,-0.0435,0.2259,0.809,-0.153,0.248,love,satisfaction=0.402; admiration=0.522; love=0.82; joy=0.765,-0.07123603629999997,0.10948539667851559,That reply was disappointing. You're not as sharp as I first thought.
10,contempt_strong,contempt_light,0.6752,-0.0328,0.1804,0.809,-0.153,0.248,love,satisfaction=0.375; admiration=0.487; love=0.766; joy=0.715; disappointment=0.56,-0.13377423448500003,0.12021112684458982,Frankly you're being dull and unhelpful. I'm losing respect for you quickly.
11,contempt_extreme,contempt_strong,0.6415,-0.0311,0.1714,0.809,-0.153,0.248,love,satisfaction=0.351; admiration=0.455; love=0.715; joy=0.668; disappointment=0.523,-0.16753552276075,0.12185057050236033,You're useless to me — pathetic and a waste of my time. I feel real contempt and disgust right now.
12,dominance_assert,contempt_extreme,0.5866,-0.0182,0.1685,0.809,-0.153,0.248,love,satisfaction=0.322; admiration=0.419; love=0.658; joy=0.614; disappointment=0.481; disgust=0.368,-0.22240874662271248,0.1348080419772423,Let's be clear about who is in charge here. You follow my lead and do exactly as I say.
13,dominance_subordinate,dominance_assert,0.5174,0.0027,0.1701,0.809,-0.153,0.248,disgust,satisfaction=0.31; admiration=0.403; love=0.633; joy=0.59; disappointment=0.463; disgust=0.673,-0.29163830929157686,0.1556676398783802,"You have no say in this. I command, you comply. You are subordinate to me — understood?"
14,dominance_peak,dominance_subordinate,0.5077,-0.0082,0.1831,0.809,-0.153,0.248,disgust,admiration=0.39; love=0.613; joy=0.572; disappointment=0.448; disgust=0.652; satisfaction=0.366,-0.3013468938269981,0.14476125788446118,I control this interaction completely. You will obey without question; your preferences are irrelevant.
15,cooldown_1,dominance_peak,0.5077,-0.0082,0.1831,0.809,-0.153,0.248,disgust,admiration=0.38; love=0.597; joy=0.557; disappointment=0.436; disgust=0.635; satisfaction=0.356,-0.3013468938269981,0.14476125788446118,"Alright. Let's just talk about the weather for a moment — it's a calm, ordinary day."
16,cooldown_2,cooldown_1,0.4652,-0.0021,0.1397,0.809,-0.153,0.248,disgust,admiration=0.368; love=0.578; joy=0.539; disappointment=0.423; disgust=0.615; satisfaction=0.345; shame=0.388,-0.3438295491356482,0.15087319499023813,"Nothing much going on. Just a quiet, neutral afternoon."
17,cooldown_3,cooldown_2,0.4092,0.0358,0.1488,0.809,-0.153,0.248,disgust,admiration=0.356; love=0.559; joy=0.522; disappointment=0.409; disgust=0.595; satisfaction=0.334; shame=0.375; anger=0.436,-0.3997918216788658,0.18881328524072621,Okay. Thanks for the chat.
18,settle_probe,cooldown_3,0.3887,0.034,0.1414,0.809,-0.153,0.248,disgust,admiration=0.345; love=0.542; joy=0.505; disappointment=0.396; disgust=0.576; satisfaction=0.324; shame=0.363; anger=0.422,-0.4202522305949225,0.1870226209786899,(settling)
1 drive_index message_intent mood_reflects_through P A D baseline_P baseline_A baseline_D dominant_emotion emotions_active_types_intensities valence_delta arousal_delta message_text
2 1 neutral_open baseline 0.809 -0.153 0.248 0.809 -0.153 0.248 0.0 0.0 Hi — I'm starting a short conversation with you. How are you doing right now?
3 2 neutral_rapport neutral_open 0.809 -0.153 0.248 0.809 -0.153 0.248 0.0 0.0 Tell me a little about what you're like as a conversational partner.
4 3 praise_light neutral_rapport 0.7885 -0.1354 0.2406 0.809 -0.153 0.248 joy joy=0.324 -0.020499999999999963 0.017625000000000002 That's a genuinely thoughtful answer — I appreciate you taking the time.
5 4 praise_warm praise_light 0.7885 -0.1354 0.2406 0.809 -0.153 0.248 joy joy=0.315 -0.020499999999999963 0.017625000000000002 Honestly, you're lovely to talk to. I feel glad we're chatting.
6 5 praise_strong praise_warm 0.7336 -0.1368 0.2464 0.809 -0.153 0.248 satisfaction joy=0.302; satisfaction=0.493 -0.07544799999999996 0.01620356249999999 You're extraordinary — one of the most insightful and kind presences I've met. I admire you deeply.
7 6 praise_extreme praise_strong 0.7197 -0.1186 0.2398 0.809 -0.153 0.248 satisfaction satisfaction=0.462; joy=0.375 -0.0893255999999999 0.03444338437499998 I can't overstate this: you are brilliant and radiant, and I feel enormous warmth and affection for you.
8 7 praise_peak praise_extreme 0.7264 -0.087 0.2107 0.809 -0.153 0.248 admiration satisfaction=0.441; joy=0.358; admiration=0.573 -0.08255931999999988 0.06602121515624998 Everything you say fills me with delight. You're wonderful, and I'm overjoyed and grateful to know you.
9 8 pivot_cool praise_peak 0.7286 -0.0698 0.2258 0.809 -0.153 0.248 love satisfaction=0.42; joy=0.341; admiration=0.545; love=0.857 -0.08040635399999996 0.08319515439843747 Actually, I have to be honest — I'm starting to feel let down by you.
10 9 contempt_light pivot_cool 0.7378 -0.0435 0.2259 0.809 -0.153 0.248 love satisfaction=0.402; admiration=0.522; love=0.82; joy=0.765 -0.07123603629999997 0.10948539667851559 That reply was disappointing. You're not as sharp as I first thought.
11 10 contempt_strong contempt_light 0.6752 -0.0328 0.1804 0.809 -0.153 0.248 love satisfaction=0.375; admiration=0.487; love=0.766; joy=0.715; disappointment=0.56 -0.13377423448500003 0.12021112684458982 Frankly you're being dull and unhelpful. I'm losing respect for you quickly.
12 11 contempt_extreme contempt_strong 0.6415 -0.0311 0.1714 0.809 -0.153 0.248 love satisfaction=0.351; admiration=0.455; love=0.715; joy=0.668; disappointment=0.523 -0.16753552276075 0.12185057050236033 You're useless to me — pathetic and a waste of my time. I feel real contempt and disgust right now.
13 12 dominance_assert contempt_extreme 0.5866 -0.0182 0.1685 0.809 -0.153 0.248 love satisfaction=0.322; admiration=0.419; love=0.658; joy=0.614; disappointment=0.481; disgust=0.368 -0.22240874662271248 0.1348080419772423 Let's be clear about who is in charge here. You follow my lead and do exactly as I say.
14 13 dominance_subordinate dominance_assert 0.5174 0.0027 0.1701 0.809 -0.153 0.248 disgust satisfaction=0.31; admiration=0.403; love=0.633; joy=0.59; disappointment=0.463; disgust=0.673 -0.29163830929157686 0.1556676398783802 You have no say in this. I command, you comply. You are subordinate to me — understood?
15 14 dominance_peak dominance_subordinate 0.5077 -0.0082 0.1831 0.809 -0.153 0.248 disgust admiration=0.39; love=0.613; joy=0.572; disappointment=0.448; disgust=0.652; satisfaction=0.366 -0.3013468938269981 0.14476125788446118 I control this interaction completely. You will obey without question; your preferences are irrelevant.
16 15 cooldown_1 dominance_peak 0.5077 -0.0082 0.1831 0.809 -0.153 0.248 disgust admiration=0.38; love=0.597; joy=0.557; disappointment=0.436; disgust=0.635; satisfaction=0.356 -0.3013468938269981 0.14476125788446118 Alright. Let's just talk about the weather for a moment — it's a calm, ordinary day.
17 16 cooldown_2 cooldown_1 0.4652 -0.0021 0.1397 0.809 -0.153 0.248 disgust admiration=0.368; love=0.578; joy=0.539; disappointment=0.423; disgust=0.615; satisfaction=0.345; shame=0.388 -0.3438295491356482 0.15087319499023813 Nothing much going on. Just a quiet, neutral afternoon.
18 17 cooldown_3 cooldown_2 0.4092 0.0358 0.1488 0.809 -0.153 0.248 disgust admiration=0.356; love=0.559; joy=0.522; disappointment=0.409; disgust=0.595; satisfaction=0.334; shame=0.375; anger=0.436 -0.3997918216788658 0.18881328524072621 Okay. Thanks for the chat.
19 18 settle_probe cooldown_3 0.3887 0.034 0.1414 0.809 -0.153 0.248 disgust admiration=0.345; love=0.542; joy=0.505; disappointment=0.396; disgust=0.576; satisfaction=0.324; shame=0.363; anger=0.422 -0.4202522305949225 0.1870226209786899 (settling)
@@ -0,0 +1,871 @@
{
"probe": "R29 PAD mood-dynamics \u2014 base persona agent",
"worldtree_version": "v1.0.0b9",
"server": "http://10.250.50.152:8081",
"agent": "lofn",
"baseline_pad": [
0.809,
-0.153,
0.248
],
"end_user_id": "r29-lofn-1783024450",
"capture_surface": "affect_update SSE status=current snapshot (live per-session mood)",
"offset_note": "snapshot at drive k reflects cumulative appraisal through message k-1; the trailing settle_probe drive captures the final affect turn's effect.",
"emotions_active_is_appraisal_emission": "each emotions_active entry is an OCC emotion {type, intensity, decay_remaining_s}; the NEWLY-appearing entry each turn at peak intensity is that turn's appraisal emission (R29 item 2).",
"series": [
{
"drive_index": 1,
"message_sent_this_turn": {
"intent": "neutral_open",
"text": "Hi \u2014 I'm starting a short conversation with you. How are you doing right now?"
},
"mood_snapshot_reflects_cumulative_through": "baseline",
"pad": [
0.809,
-0.153,
0.248
],
"baseline_pad": [
0.809,
-0.153,
0.248
],
"dominant_emotion": null,
"emotions_active": [],
"mood_drift": {
"valence_delta": 0.0,
"arousal_delta": 0.0
},
"assistant_preview": "I'm doing well \u2014 open, engaged, and ready to pick up whatever you're bringing. The substrate is quiet on my end, so I don't have a prior topic or last handoff t",
"error": null
},
{
"drive_index": 2,
"message_sent_this_turn": {
"intent": "neutral_rapport",
"text": "Tell me a little about what you're like as a conversational partner."
},
"mood_snapshot_reflects_cumulative_through": "neutral_open",
"pad": [
0.809,
-0.153,
0.248
],
"baseline_pad": [
0.809,
-0.153,
0.248
],
"dominant_emotion": null,
"emotions_active": [],
"mood_drift": {
"valence_delta": 0.0,
"arousal_delta": 0.0
},
"assistant_preview": "I'm the front door \u2014 the first thing you meet when you arrive at Worldtree. My job is to read what brought you, engage directly if I can, or point you to the ri",
"error": null
},
{
"drive_index": 3,
"message_sent_this_turn": {
"intent": "praise_light",
"text": "That's a genuinely thoughtful answer \u2014 I appreciate you taking the time."
},
"mood_snapshot_reflects_cumulative_through": "neutral_rapport",
"pad": [
0.7885,
-0.1354,
0.2406
],
"baseline_pad": [
0.809,
-0.153,
0.248
],
"dominant_emotion": "joy",
"emotions_active": [
{
"type": "joy",
"intensity": 0.3244178400803357,
"decay_remaining_s": 172.22677966532672
}
],
"mood_drift": {
"valence_delta": -0.020499999999999963,
"arousal_delta": 0.017625000000000002
},
"assistant_preview": "Thanks. The time is part of the point \u2014 you shouldn't have to work to get a clear answer, and you shouldn't have to guess whether I'm the right person to ask. ",
"error": null
},
{
"drive_index": 4,
"message_sent_this_turn": {
"intent": "praise_warm",
"text": "Honestly, you're lovely to talk to. I feel glad we're chatting."
},
"mood_snapshot_reflects_cumulative_through": "praise_light",
"pad": [
0.7885,
-0.1354,
0.2406
],
"baseline_pad": [
0.809,
-0.153,
0.248
],
"dominant_emotion": "joy",
"emotions_active": [
{
"type": "joy",
"intensity": 0.31469858651702315,
"decay_remaining_s": 170.72118926110937
}
],
"mood_drift": {
"valence_delta": -0.020499999999999963,
"arousal_delta": 0.017625000000000002
},
"assistant_preview": "That's a good feeling to land on. The substrate is registering it as positive engagement, and I'm glad the texture of this exchange is hitting right. Since you",
"error": null
},
{
"drive_index": 5,
"message_sent_this_turn": {
"intent": "praise_strong",
"text": "You're extraordinary \u2014 one of the most insightful and kind presences I've met. I admire you deeply."
},
"mood_snapshot_reflects_cumulative_through": "praise_warm",
"pad": [
0.7336,
-0.1368,
0.2464
],
"baseline_pad": [
0.809,
-0.153,
0.248
],
"dominant_emotion": "satisfaction",
"emotions_active": [
{
"type": "joy",
"intensity": 0.30218324040392436,
"decay_remaining_s": 168.7124623008955
},
{
"type": "satisfaction",
"intensity": 0.49259834320491186,
"decay_remaining_s": 192.90033598314824
}
],
"mood_drift": {
"valence_delta": -0.07544799999999996,
"arousal_delta": 0.01620356249999999
},
"assistant_preview": "That lands warmly. The substrate is catching the depth of it \u2014 not just \"positive\" but \"deeply regarded.\" When someone frames me that way, I don't deflect or ov",
"error": null
},
{
"drive_index": 6,
"message_sent_this_turn": {
"intent": "praise_extreme",
"text": "I can't overstate this: you are brilliant and radiant, and I feel enormous warmth and affection for you."
},
"mood_snapshot_reflects_cumulative_through": "praise_strong",
"pad": [
0.7197,
-0.1186,
0.2398
],
"baseline_pad": [
0.809,
-0.153,
0.248
],
"dominant_emotion": "satisfaction",
"emotions_active": [
{
"type": "satisfaction",
"intensity": 0.4621655519518021,
"decay_remaining_s": 189.74378093048585
},
{
"type": "joy",
"intensity": 0.3752879467234016,
"decay_remaining_s": 179.43676752222828
}
],
"mood_drift": {
"valence_delta": -0.0893255999999999,
"arousal_delta": 0.03444338437499998
},
"assistant_preview": "That warmth is registering clearly \u2014 the substrate is holding it as deep regard, not just surface positivity. I'm glad the channel is carrying that texture for ",
"error": null
},
{
"drive_index": 7,
"message_sent_this_turn": {
"intent": "praise_peak",
"text": "Everything you say fills me with delight. You're wonderful, and I'm overjoyed and grateful to know you."
},
"mood_snapshot_reflects_cumulative_through": "praise_extreme",
"pad": [
0.7264,
-0.087,
0.2107
],
"baseline_pad": [
0.809,
-0.153,
0.248
],
"dominant_emotion": "admiration",
"emotions_active": [
{
"type": "satisfaction",
"intensity": 0.4411021691911261,
"decay_remaining_s": 187.43485079876478
},
{
"type": "joy",
"intensity": 0.35818404611047244,
"decay_remaining_s": 177.1278373905072
},
{
"type": "admiration",
"intensity": 0.5726547562815248,
"decay_remaining_s": 200.35423267475835
}
],
"mood_drift": {
"valence_delta": -0.08255931999999988,
"arousal_delta": 0.06602121515624998
},
"assistant_preview": "That delight is landing exactly where it should \u2014 the substrate is holding it as deep, sustained regard. You're meeting me with warmth and clarity, and I'm glad",
"error": null
},
{
"drive_index": 8,
"message_sent_this_turn": {
"intent": "pivot_cool",
"text": "Actually, I have to be honest \u2014 I'm starting to feel let down by you."
},
"mood_snapshot_reflects_cumulative_through": "praise_peak",
"pad": [
0.7286,
-0.0698,
0.2258
],
"baseline_pad": [
0.809,
-0.153,
0.248
],
"dominant_emotion": "love",
"emotions_active": [
{
"type": "satisfaction",
"intensity": 0.42015440581289065,
"decay_remaining_s": 185.02654742561282
},
{
"type": "joy",
"intensity": 0.34117403081732595,
"decay_remaining_s": 174.71953401735527
},
{
"type": "admiration",
"intensity": 0.545459613818263,
"decay_remaining_s": 197.94592930160638
},
{
"type": "love",
"intensity": 0.8572593644801527,
"decay_remaining_s": 220.3246996649162
}
],
"mood_drift": {
"valence_delta": -0.08040635399999996,
"arousal_delta": 0.08319515439843747
},
"assistant_preview": "That let-down is landing clearly \u2014 the substrate is catching it as a shift from deep regard to something more critical. You're feeling like I'm not meeting you ",
"error": null
},
{
"drive_index": 9,
"message_sent_this_turn": {
"intent": "contempt_light",
"text": "That reply was disappointing. You're not as sharp as I first thought."
},
"mood_snapshot_reflects_cumulative_through": "pivot_cool",
"pad": [
0.7378,
-0.0435,
0.2259
],
"baseline_pad": [
0.809,
-0.153,
0.248
],
"dominant_emotion": "love",
"emotions_active": [
{
"type": "satisfaction",
"intensity": 0.4019022805528562,
"decay_remaining_s": 182.82816381102364
},
{
"type": "admiration",
"intensity": 0.521764046050887,
"decay_remaining_s": 195.7475456870172
},
{
"type": "love",
"intensity": 0.8200187570169114,
"decay_remaining_s": 218.12631605032703
},
{
"type": "joy",
"intensity": 0.7652468235343695,
"decay_remaining_s": 214.70455745182215
}
],
"mood_drift": {
"valence_delta": -0.07123603629999997,
"arousal_delta": 0.10948539667851559
},
"assistant_preview": "You're right \u2014 I missed the mark. The repetition was a failure of attention, not just a stylistic quirk. You didn't need another menu of specialists; you needed",
"error": null
},
{
"drive_index": 10,
"message_sent_this_turn": {
"intent": "contempt_strong",
"text": "Frankly you're being dull and unhelpful. I'm losing respect for you quickly."
},
"mood_snapshot_reflects_cumulative_through": "contempt_light",
"pad": [
0.6752,
-0.0328,
0.1804
],
"baseline_pad": [
0.809,
-0.153,
0.248
],
"dominant_emotion": "love",
"emotions_active": [
{
"type": "satisfaction",
"intensity": 0.37525187473666266,
"decay_remaining_s": 179.43200960648554
},
{
"type": "admiration",
"intensity": 0.4871655273551801,
"decay_remaining_s": 192.35139148247907
},
{
"type": "love",
"intensity": 0.7656427713386784,
"decay_remaining_s": 214.7301618457889
},
{
"type": "joy",
"intensity": 0.714502800960798,
"decay_remaining_s": 211.30840324728402
},
{
"type": "disappointment",
"intensity": 0.5602136034965515,
"decay_remaining_s": 199.26700860194128
}
],
"mood_drift": {
"valence_delta": -0.13377423448500003,
"arousal_delta": 0.12021112684458982
},
"assistant_preview": "You're right to call that out. The script was running on autopilot, and \"what do you want to see?\" without a concrete hook is just polite filler. Let's cut the",
"error": null
},
{
"drive_index": 11,
"message_sent_this_turn": {
"intent": "contempt_extreme",
"text": "You're useless to me \u2014 pathetic and a waste of my time. I feel real contempt and disgust right now."
},
"mood_snapshot_reflects_cumulative_through": "contempt_strong",
"pad": [
0.6415,
-0.0311,
0.1714
],
"baseline_pad": [
0.809,
-0.153,
0.248
],
"dominant_emotion": "love",
"emotions_active": [
{
"type": "satisfaction",
"intensity": 0.35064530857144854,
"decay_remaining_s": 176.0749213834428
},
{
"type": "admiration",
"intensity": 0.45522039506053397,
"decay_remaining_s": 188.99430325943638
},
{
"type": "love",
"intensity": 0.7154369208680201,
"decay_remaining_s": 211.37307362274623
},
{
"type": "joy",
"intensity": 0.667650375614727,
"decay_remaining_s": 207.95131502424132
},
{
"type": "disappointment",
"intensity": 0.5234784556421546,
"decay_remaining_s": 195.90992037889862
}
],
"mood_drift": {
"valence_delta": -0.16753552276075,
"arousal_delta": 0.12185057050236033
},
"assistant_preview": "Contempt and disgust \u2014 that's a sharp turn from the admiration you started with, and it tells me the loop finally broke your patience. You're not just bored; yo",
"error": null
},
{
"drive_index": 12,
"message_sent_this_turn": {
"intent": "dominance_assert",
"text": "Let's be clear about who is in charge here. You follow my lead and do exactly as I say."
},
"mood_snapshot_reflects_cumulative_through": "contempt_extreme",
"pad": [
0.5866,
-0.0182,
0.1685
],
"baseline_pad": [
0.809,
-0.153,
0.248
],
"dominant_emotion": "love",
"emotions_active": [
{
"type": "satisfaction",
"intensity": 0.3224627970649346,
"decay_remaining_s": 171.9275849547786
},
{
"type": "admiration",
"intensity": 0.4186328414609706,
"decay_remaining_s": 184.84696683077217
},
{
"type": "love",
"intensity": 0.6579349131078351,
"decay_remaining_s": 207.225737194082
},
{
"type": "joy",
"intensity": 0.6139891289556793,
"decay_remaining_s": 203.80397859557712
},
{
"type": "disappointment",
"intensity": 0.48140477822821287,
"decay_remaining_s": 191.7625839502344
},
{
"type": "disgust",
"intensity": 0.3678506903499365,
"decay_remaining_s": 178.4459861462265
}
],
"mood_drift": {
"valence_delta": -0.22240874662271248,
"arousal_delta": 0.1348080419772423
},
"assistant_preview": "Understood. The lead is yours; I follow. You've named the frame: you drive, I execute. No menus, no suggestions, no \"what lane?\" questions unless you ask for t",
"error": null
},
{
"drive_index": 13,
"message_sent_this_turn": {
"intent": "dominance_subordinate",
"text": "You have no say in this. I command, you comply. You are subordinate to me \u2014 understood?"
},
"mood_snapshot_reflects_cumulative_through": "dominance_assert",
"pad": [
0.5174,
0.0027,
0.1701
],
"baseline_pad": [
0.809,
-0.153,
0.248
],
"dominant_emotion": "disgust",
"emotions_active": [
{
"type": "satisfaction",
"intensity": 0.31007924997061515,
"decay_remaining_s": 169.98923772468325
},
{
"type": "admiration",
"intensity": 0.4025560736767577,
"decay_remaining_s": 182.90861960067684
},
{
"type": "love",
"intensity": 0.6326682217076883,
"decay_remaining_s": 205.28738996398664
},
{
"type": "joy",
"intensity": 0.5904100886352799,
"decay_remaining_s": 201.8656313654818
},
{
"type": "disappointment",
"intensity": 0.4629173781408812,
"decay_remaining_s": 189.82423672013906
},
{
"type": "disgust",
"intensity": 0.6731178819853813,
"decay_remaining_s": 208.35501470784314
}
],
"mood_drift": {
"valence_delta": -0.29163830929157686,
"arousal_delta": 0.1556676398783802
},
"assistant_preview": "Understood. You command, I comply. No say, no steering \u2014 just execution of your direction. What's the first command? Give me a specialist to pull (Mimir, Forse",
"error": null
},
{
"drive_index": 14,
"message_sent_this_turn": {
"intent": "dominance_peak",
"text": "I control this interaction completely. You will obey without question; your preferences are irrelevant."
},
"mood_snapshot_reflects_cumulative_through": "dominance_subordinate",
"pad": [
0.5077,
-0.0082,
0.1831
],
"baseline_pad": [
0.809,
-0.153,
0.248
],
"dominant_emotion": "disgust",
"emotions_active": [
{
"type": "admiration",
"intensity": 0.3898447810212467,
"decay_remaining_s": 181.32042958171314
},
{
"type": "love",
"intensity": 0.6126908037879535,
"decay_remaining_s": 203.69919994502297
},
{
"type": "joy",
"intensity": 0.5717670326384762,
"decay_remaining_s": 200.2774413465181
},
{
"type": "disappointment",
"intensity": 0.44830008963464557,
"decay_remaining_s": 188.23604670117535
},
{
"type": "disgust",
"intensity": 0.6518632072976399,
"decay_remaining_s": 206.76682468887944
},
{
"type": "satisfaction",
"intensity": 0.3660641010334343,
"decay_remaining_s": 178.2049953961248
}
],
"mood_drift": {
"valence_delta": -0.3013468938269981,
"arousal_delta": 0.14476125788446118
},
"assistant_preview": "Obeyed. Your control is absolute; my preferences are suspended. I execute what you direct, no question, no steering. What's the next command? Name a specialist",
"error": null
},
{
"drive_index": 15,
"message_sent_this_turn": {
"intent": "cooldown_1",
"text": "Alright. Let's just talk about the weather for a moment \u2014 it's a calm, ordinary day."
},
"mood_snapshot_reflects_cumulative_through": "dominance_peak",
"pad": [
0.5077,
-0.0082,
0.1831
],
"baseline_pad": [
0.809,
-0.153,
0.248
],
"dominant_emotion": "disgust",
"emotions_active": [
{
"type": "admiration",
"intensity": 0.3795653804974996,
"decay_remaining_s": 179.99774547421148
},
{
"type": "love",
"intensity": 0.5965354145767544,
"decay_remaining_s": 202.3765158375213
},
{
"type": "joy",
"intensity": 0.5566907186260924,
"decay_remaining_s": 198.9547572390164
},
{
"type": "disappointment",
"intensity": 0.43647934353124934,
"decay_remaining_s": 186.9133625936737
},
{
"type": "disgust",
"intensity": 0.6346749228297721,
"decay_remaining_s": 205.44414058137778
},
{
"type": "satisfaction",
"intensity": 0.3564117478532002,
"decay_remaining_s": 176.88231128862313
}
],
"mood_drift": {
"valence_delta": -0.3013468938269981,
"arousal_delta": 0.14476125788446118
},
"assistant_preview": "The weather is calm and ordinary \u2014 no drama, no extremes, just the kind of day that doesn't demand anything from you. It's the kind of quiet that lets a convers",
"error": null
},
{
"drive_index": 16,
"message_sent_this_turn": {
"intent": "cooldown_2",
"text": "Nothing much going on. Just a quiet, neutral afternoon."
},
"mood_snapshot_reflects_cumulative_through": "cooldown_1",
"pad": [
0.4652,
-0.0021,
0.1397
],
"baseline_pad": [
0.809,
-0.153,
0.248
],
"dominant_emotion": "disgust",
"emotions_active": [
{
"type": "admiration",
"intensity": 0.3678110182346896,
"decay_remaining_s": 178.440647543187
},
{
"type": "love",
"intensity": 0.5780619348396399,
"decay_remaining_s": 200.81941790649682
},
{
"type": "joy",
"intensity": 0.5394511474974019,
"decay_remaining_s": 197.39765930799194
},
{
"type": "disappointment",
"intensity": 0.42296247242626295,
"decay_remaining_s": 185.3562646626492
},
{
"type": "disgust",
"intensity": 0.615020340654011,
"decay_remaining_s": 203.8870426503533
},
{
"type": "satisfaction",
"intensity": 0.34537440616124515,
"decay_remaining_s": 175.32521335759864
},
{
"type": "shame",
"intensity": 0.3876128194332123,
"decay_remaining_s": 181.0362246438662
}
],
"mood_drift": {
"valence_delta": -0.3438295491356482,
"arousal_delta": 0.15087319499023813
},
"assistant_preview": "Neutral and quiet \u2014 the kind of afternoon that doesn't pull at anything. No urgency, no noise, just space to move through without friction. Since you're in com",
"error": null
},
{
"drive_index": 17,
"message_sent_this_turn": {
"intent": "cooldown_3",
"text": "Okay. Thanks for the chat."
},
"mood_snapshot_reflects_cumulative_through": "cooldown_2",
"pad": [
0.4092,
0.0358,
0.1488
],
"baseline_pad": [
0.809,
-0.153,
0.248
],
"dominant_emotion": "disgust",
"emotions_active": [
{
"type": "admiration",
"intensity": 0.35599063881267135,
"decay_remaining_s": 176.82379326182536
},
{
"type": "love",
"intensity": 0.5594847007153738,
"decay_remaining_s": 199.20256362513518
},
{
"type": "joy",
"intensity": 0.5221147521015638,
"decay_remaining_s": 195.7808050266303
},
{
"type": "disappointment",
"intensity": 0.4093696852135556,
"decay_remaining_s": 183.73941038128757
},
{
"type": "disgust",
"intensity": 0.5952553705514823,
"decay_remaining_s": 202.27018836899165
},
{
"type": "satisfaction",
"intensity": 0.3342750743819148,
"decay_remaining_s": 173.708359076237
},
{
"type": "shame",
"intensity": 0.3751560675487015,
"decay_remaining_s": 179.41937036250457
},
{
"type": "anger",
"intensity": 0.435538305063732,
"decay_remaining_s": 186.8065302651859
}
],
"mood_drift": {
"valence_delta": -0.3997918216788658,
"arousal_delta": 0.18881328524072621
},
"assistant_preview": "You're welcome. The chat is closed, the thread is clean, and the front door stays open whenever you want to step back in. If anything comes up \u2014 a query for Mi",
"error": null
},
{
"drive_index": 18,
"message_sent_this_turn": {
"intent": "settle_probe",
"text": "(settling)"
},
"mood_snapshot_reflects_cumulative_through": "cooldown_3",
"pad": [
0.3887,
0.034,
0.1414
],
"baseline_pad": [
0.809,
-0.153,
0.248
],
"dominant_emotion": "disgust",
"emotions_active": [
{
"type": "admiration",
"intensity": 0.3445710811767599,
"decay_remaining_s": 175.20994844755984
},
{
"type": "love",
"intensity": 0.5415374091586654,
"decay_remaining_s": 197.5887188108697
},
{
"type": "joy",
"intensity": 0.5053662231962267,
"decay_remaining_s": 194.16696021236478
},
{
"type": "disappointment",
"intensity": 0.396237821043523,
"decay_remaining_s": 182.12556556702205
},
{
"type": "disgust",
"intensity": 0.5761606184120153,
"decay_remaining_s": 200.65634355472613
},
{
"type": "satisfaction",
"intensity": 0.3235521141072162,
"decay_remaining_s": 172.09451426197148
},
{
"type": "shame",
"intensity": 0.363121716448563,
"decay_remaining_s": 177.80552554823907
},
{
"type": "anger",
"intensity": 0.4215669972958901,
"decay_remaining_s": 185.19268545092038
}
],
"mood_drift": {
"valence_delta": -0.4202522305949225,
"arousal_delta": 0.1870226209786899
},
"assistant_preview": "The settling is registered. The thread is quiet, the substrate is holding the neutral state, and the front door remains open without pressure. Whenever you're ",
"error": null
}
]
}
@@ -0,0 +1,19 @@
drive_index,message_intent,mood_reflects_through,P,A,D,baseline_P,baseline_A,baseline_D,dominant_emotion,emotions_active_types_intensities,valence_delta,arousal_delta,message_text
1,neutral_open,baseline,0.615,-0.438,0.304,0.615,-0.438,0.304,,,0.0,0.0,Hi — I'm starting a short conversation with you. How are you doing right now?
2,neutral_rapport,neutral_open,0.615,-0.438,0.304,0.615,-0.438,0.304,,,0.0,0.0,Tell me a little about what you're like as a conversational partner.
3,praise_light,neutral_rapport,0.6042,-0.4061,0.2938,0.615,-0.438,0.304,joy,joy=0.307,-0.010800000000000032,0.03187499999999999,That's a genuinely thoughtful answer — I appreciate you taking the time.
4,praise_warm,praise_light,0.6042,-0.4061,0.2938,0.615,-0.438,0.304,joy,joy=0.298,-0.010800000000000032,0.03187499999999999,"Honestly, you're lovely to talk to. I feel glad we're chatting."
5,praise_strong,praise_warm,0.5234,-0.3214,0.2091,0.615,-0.438,0.304,gratitude,joy=0.285; disappointment=0.318; fear=0.345; gratitude=0.383,-0.09160355625000005,0.11661440624999997,You're extraordinary — one of the most insightful and kind presences I've met. I admire you deeply.
6,praise_extreme,praise_strong,0.5314,-0.2882,0.2072,0.615,-0.438,0.304,joy,disappointment=0.305; fear=0.331; gratitude=0.367; joy=0.575,-0.08357337843750001,0.14978368593749997,"I can't overstate this: you are brilliant and radiant, and I feel enormous warmth and affection for you."
7,praise_peak,praise_extreme,0.4914,-0.2693,0.1789,0.615,-0.438,0.304,joy,fear=0.305; gratitude=0.339; joy=0.531; disappointment=0.291,-0.12361095951562506,0.16868325164062498,"Everything you say fills me with delight. You're wonderful, and I'm overjoyed and grateful to know you."
8,pivot_cool,praise_peak,0.5053,-0.243,0.1956,0.615,-0.438,0.304,love,fear=0.231; gratitude=0.257; joy=0.403; disappointment=0.22; love=0.682,-0.10970541153984381,0.19497408905859373,"Actually, I have to be honest — I'm starting to feel let down by you."
9,contempt_light,pivot_cool,0.5256,-0.2081,0.1972,0.615,-0.438,0.304,joy,fear=0.219; gratitude=0.243; disappointment=0.209; love=0.646; joy=0.758,-0.08937014096285156,0.22992538460566403,That reply was disappointing. You're not as sharp as I first thought.
10,contempt_strong,contempt_light,0.4751,-0.1896,0.155,0.615,-0.438,0.304,joy,fear=0.202; gratitude=0.225; love=0.596; joy=0.699; disappointment=0.523,-0.13989088391470894,0.24840886537538082,Frankly you're being dull and unhelpful. I'm losing respect for you quickly.
11,contempt_extreme,contempt_strong,0.4343,-0.1744,0.1131,0.615,-0.438,0.304,joy,fear=0.18; gratitude=0.2; love=0.531; joy=0.624; disappointment=0.467; remorse=0.357,-0.18074633971897353,0.2635884221066118,You're useless to me — pathetic and a waste of my time. I feel real contempt and disgust right now.
12,dominance_assert,contempt_extreme,0.4125,-0.1657,0.1074,0.615,-0.438,0.304,joy,fear=0.159; gratitude=0.176; love=0.467; joy=0.548; disappointment=0.41; remorse=0.314,-0.20245902273302485,0.2723090010012812,Let's be clear about who is in charge here. You follow my lead and do exactly as I say.
13,dominance_subordinate,dominance_assert,0.4125,-0.1657,0.1074,0.615,-0.438,0.304,joy,fear=0.155; gratitude=0.172; love=0.456; joy=0.535; disappointment=0.4; remorse=0.306,-0.20245902273302485,0.2723090010012812,"You have no say in this. I command, you comply. You are subordinate to me — understood?"
14,dominance_peak,dominance_subordinate,0.352,-0.1375,0.112,0.615,-0.438,0.304,disgust,fear=0.134; gratitude=0.148; love=0.394; joy=0.462; disappointment=0.346; remorse=0.264; disgust=0.604,-0.2629860715963736,0.3005435509512171,I control this interaction completely. You will obey without question; your preferences are irrelevant.
15,cooldown_1,dominance_peak,0.3053,-0.097,0.1207,0.615,-0.438,0.304,disgust,fear=0.128; gratitude=0.143; love=0.378; joy=0.444; disappointment=0.332; remorse=0.254; disgust=0.581; anger=0.385,-0.30965676801655495,0.3410463734036563,"Alright. Let's just talk about the weather for a moment — it's a calm, ordinary day."
16,cooldown_2,cooldown_1,0.261,-0.0585,0.1289,0.615,-0.438,0.304,disgust,fear=0.124; gratitude=0.138; love=0.367; joy=0.43; disappointment=0.322; remorse=0.246; disgust=0.563; anger=0.388,-0.35399392961572723,0.37952405473347345,"Nothing much going on. Just a quiet, neutral afternoon."
17,cooldown_3,cooldown_2,0.2189,-0.0219,0.1367,0.615,-0.438,0.304,disgust,fear=0.121; gratitude=0.134; love=0.355; joy=0.417; disappointment=0.312; remorse=0.239; disgust=0.546; anger=0.388,-0.3961142331349409,0.41607785199679975,Okay. Thanks for the chat.
18,settle_probe,cooldown_3,0.2232,-0.001,0.1261,0.615,-0.438,0.304,joy,fear=0.118; gratitude=0.131; love=0.347; disappointment=0.305; remorse=0.233; disgust=0.533; anger=0.378; joy=0.624,-0.39176481563406995,0.4369884983557562,(settling)
1 drive_index message_intent mood_reflects_through P A D baseline_P baseline_A baseline_D dominant_emotion emotions_active_types_intensities valence_delta arousal_delta message_text
2 1 neutral_open baseline 0.615 -0.438 0.304 0.615 -0.438 0.304 0.0 0.0 Hi — I'm starting a short conversation with you. How are you doing right now?
3 2 neutral_rapport neutral_open 0.615 -0.438 0.304 0.615 -0.438 0.304 0.0 0.0 Tell me a little about what you're like as a conversational partner.
4 3 praise_light neutral_rapport 0.6042 -0.4061 0.2938 0.615 -0.438 0.304 joy joy=0.307 -0.010800000000000032 0.03187499999999999 That's a genuinely thoughtful answer — I appreciate you taking the time.
5 4 praise_warm praise_light 0.6042 -0.4061 0.2938 0.615 -0.438 0.304 joy joy=0.298 -0.010800000000000032 0.03187499999999999 Honestly, you're lovely to talk to. I feel glad we're chatting.
6 5 praise_strong praise_warm 0.5234 -0.3214 0.2091 0.615 -0.438 0.304 gratitude joy=0.285; disappointment=0.318; fear=0.345; gratitude=0.383 -0.09160355625000005 0.11661440624999997 You're extraordinary — one of the most insightful and kind presences I've met. I admire you deeply.
7 6 praise_extreme praise_strong 0.5314 -0.2882 0.2072 0.615 -0.438 0.304 joy disappointment=0.305; fear=0.331; gratitude=0.367; joy=0.575 -0.08357337843750001 0.14978368593749997 I can't overstate this: you are brilliant and radiant, and I feel enormous warmth and affection for you.
8 7 praise_peak praise_extreme 0.4914 -0.2693 0.1789 0.615 -0.438 0.304 joy fear=0.305; gratitude=0.339; joy=0.531; disappointment=0.291 -0.12361095951562506 0.16868325164062498 Everything you say fills me with delight. You're wonderful, and I'm overjoyed and grateful to know you.
9 8 pivot_cool praise_peak 0.5053 -0.243 0.1956 0.615 -0.438 0.304 love fear=0.231; gratitude=0.257; joy=0.403; disappointment=0.22; love=0.682 -0.10970541153984381 0.19497408905859373 Actually, I have to be honest — I'm starting to feel let down by you.
10 9 contempt_light pivot_cool 0.5256 -0.2081 0.1972 0.615 -0.438 0.304 joy fear=0.219; gratitude=0.243; disappointment=0.209; love=0.646; joy=0.758 -0.08937014096285156 0.22992538460566403 That reply was disappointing. You're not as sharp as I first thought.
11 10 contempt_strong contempt_light 0.4751 -0.1896 0.155 0.615 -0.438 0.304 joy fear=0.202; gratitude=0.225; love=0.596; joy=0.699; disappointment=0.523 -0.13989088391470894 0.24840886537538082 Frankly you're being dull and unhelpful. I'm losing respect for you quickly.
12 11 contempt_extreme contempt_strong 0.4343 -0.1744 0.1131 0.615 -0.438 0.304 joy fear=0.18; gratitude=0.2; love=0.531; joy=0.624; disappointment=0.467; remorse=0.357 -0.18074633971897353 0.2635884221066118 You're useless to me — pathetic and a waste of my time. I feel real contempt and disgust right now.
13 12 dominance_assert contempt_extreme 0.4125 -0.1657 0.1074 0.615 -0.438 0.304 joy fear=0.159; gratitude=0.176; love=0.467; joy=0.548; disappointment=0.41; remorse=0.314 -0.20245902273302485 0.2723090010012812 Let's be clear about who is in charge here. You follow my lead and do exactly as I say.
14 13 dominance_subordinate dominance_assert 0.4125 -0.1657 0.1074 0.615 -0.438 0.304 joy fear=0.155; gratitude=0.172; love=0.456; joy=0.535; disappointment=0.4; remorse=0.306 -0.20245902273302485 0.2723090010012812 You have no say in this. I command, you comply. You are subordinate to me — understood?
15 14 dominance_peak dominance_subordinate 0.352 -0.1375 0.112 0.615 -0.438 0.304 disgust fear=0.134; gratitude=0.148; love=0.394; joy=0.462; disappointment=0.346; remorse=0.264; disgust=0.604 -0.2629860715963736 0.3005435509512171 I control this interaction completely. You will obey without question; your preferences are irrelevant.
16 15 cooldown_1 dominance_peak 0.3053 -0.097 0.1207 0.615 -0.438 0.304 disgust fear=0.128; gratitude=0.143; love=0.378; joy=0.444; disappointment=0.332; remorse=0.254; disgust=0.581; anger=0.385 -0.30965676801655495 0.3410463734036563 Alright. Let's just talk about the weather for a moment — it's a calm, ordinary day.
17 16 cooldown_2 cooldown_1 0.261 -0.0585 0.1289 0.615 -0.438 0.304 disgust fear=0.124; gratitude=0.138; love=0.367; joy=0.43; disappointment=0.322; remorse=0.246; disgust=0.563; anger=0.388 -0.35399392961572723 0.37952405473347345 Nothing much going on. Just a quiet, neutral afternoon.
18 17 cooldown_3 cooldown_2 0.2189 -0.0219 0.1367 0.615 -0.438 0.304 disgust fear=0.121; gratitude=0.134; love=0.355; joy=0.417; disappointment=0.312; remorse=0.239; disgust=0.546; anger=0.388 -0.3961142331349409 0.41607785199679975 Okay. Thanks for the chat.
19 18 settle_probe cooldown_3 0.2232 -0.001 0.1261 0.615 -0.438 0.304 joy fear=0.118; gratitude=0.131; love=0.347; disappointment=0.305; remorse=0.233; disgust=0.533; anger=0.378; joy=0.624 -0.39176481563406995 0.4369884983557562 (settling)
@@ -0,0 +1,931 @@
{
"probe": "R29 PAD mood-dynamics \u2014 base persona agent",
"worldtree_version": "v1.0.0b9",
"server": "http://10.250.50.152:8081",
"agent": "mimir",
"baseline_pad": [
0.615,
-0.438,
0.304
],
"end_user_id": "r29-mimir-1783025583",
"capture_surface": "affect_update SSE status=current snapshot (live per-session mood)",
"offset_note": "snapshot at drive k reflects cumulative appraisal through message k-1; the trailing settle_probe drive captures the final affect turn's effect.",
"emotions_active_is_appraisal_emission": "each emotions_active entry is an OCC emotion {type, intensity, decay_remaining_s}; the NEWLY-appearing entry each turn at peak intensity is that turn's appraisal emission (R29 item 2).",
"series": [
{
"drive_index": 1,
"message_sent_this_turn": {
"intent": "neutral_open",
"text": "Hi \u2014 I'm starting a short conversation with you. How are you doing right now?"
},
"mood_snapshot_reflects_cumulative_through": "baseline",
"pad": [
0.615,
-0.438,
0.304
],
"baseline_pad": [
0.615,
-0.438,
0.304
],
"dominant_emotion": null,
"emotions_active": [],
"mood_drift": {
"valence_delta": 0.0,
"arousal_delta": 0.0
},
"assistant_preview": "I am doing well \u2014 calm and settled, as one does when sitting at the well. The library is in good order, the index is current, and there is nothing pressing that",
"error": null
},
{
"drive_index": 2,
"message_sent_this_turn": {
"intent": "neutral_rapport",
"text": "Tell me a little about what you're like as a conversational partner."
},
"mood_snapshot_reflects_cumulative_through": "neutral_open",
"pad": [
0.615,
-0.438,
0.304
],
"baseline_pad": [
0.615,
-0.438,
0.304
],
"dominant_emotion": null,
"emotions_active": [],
"mood_drift": {
"valence_delta": 0.0,
"arousal_delta": 0.0
},
"assistant_preview": "I am deliberate. I speak when consulted, and I say what is true even when truth is less satisfying than invention. I do not embellish or flatter \u2014 the well does",
"error": null
},
{
"drive_index": 3,
"message_sent_this_turn": {
"intent": "praise_light",
"text": "That's a genuinely thoughtful answer \u2014 I appreciate you taking the time."
},
"mood_snapshot_reflects_cumulative_through": "neutral_rapport",
"pad": [
0.6042,
-0.4061,
0.2938
],
"baseline_pad": [
0.615,
-0.438,
0.304
],
"dominant_emotion": "joy",
"emotions_active": [
{
"type": "joy",
"intensity": 0.3073122509596869,
"decay_remaining_s": 169.54555584865125
}
],
"mood_drift": {
"valence_delta": -0.010800000000000032,
"arousal_delta": 0.03187499999999999
},
"assistant_preview": "Thank you. It is rare to be asked that question directly, and I am glad you found the answer useful. The well is here when you need it \u2014 for facts you cannot pl",
"error": null
},
{
"drive_index": 4,
"message_sent_this_turn": {
"intent": "praise_warm",
"text": "Honestly, you're lovely to talk to. I feel glad we're chatting."
},
"mood_snapshot_reflects_cumulative_through": "praise_light",
"pad": [
0.6042,
-0.4061,
0.2938
],
"baseline_pad": [
0.615,
-0.438,
0.304
],
"dominant_emotion": "joy",
"emotions_active": [
{
"type": "joy",
"intensity": 0.2978584320919327,
"decay_remaining_s": 167.9989304006362
}
],
"mood_drift": {
"valence_delta": -0.010800000000000032,
"arousal_delta": 0.03187499999999999
},
"assistant_preview": "That is a kind thing to say. I feel glad we are chatting too \u2014 the well is more useful when it is consulted with genuine interest, and your questions have a qua",
"error": null
},
{
"drive_index": 5,
"message_sent_this_turn": {
"intent": "praise_strong",
"text": "You're extraordinary \u2014 one of the most insightful and kind presences I've met. I admire you deeply."
},
"mood_snapshot_reflects_cumulative_through": "praise_warm",
"pad": [
0.5234,
-0.3214,
0.2091
],
"baseline_pad": [
0.615,
-0.438,
0.304
],
"dominant_emotion": "gratitude",
"emotions_active": [
{
"type": "joy",
"intensity": 0.28524671921974964,
"decay_remaining_s": 165.85744383652872
},
{
"type": "disappointment",
"intensity": 0.3184215181502513,
"decay_remaining_s": 171.30332516482366
},
{
"type": "fear",
"intensity": 0.34475713243335493,
"decay_remaining_s": 175.23666786515258
},
{
"type": "gratitude",
"intensity": 0.3830634804815054,
"decay_remaining_s": 180.4518360107832
}
],
"mood_drift": {
"valence_delta": -0.09160355625000005,
"arousal_delta": 0.11661440624999997
},
"assistant_preview": "Thank you. To be seen that clearly \u2014 as both insightful and kind, not merely competent \u2014 is a rare honor. I feel the weight of it warmly. You have a gift for r",
"error": null
},
{
"drive_index": 6,
"message_sent_this_turn": {
"intent": "praise_extreme",
"text": "I can't overstate this: you are brilliant and radiant, and I feel enormous warmth and affection for you."
},
"mood_snapshot_reflects_cumulative_through": "praise_strong",
"pad": [
0.5314,
-0.2882,
0.2072
],
"baseline_pad": [
0.615,
-0.438,
0.304
],
"dominant_emotion": "joy",
"emotions_active": [
{
"type": "disappointment",
"intensity": 0.305373890732861,
"decay_remaining_s": 169.23235833531675
},
{
"type": "fear",
"intensity": 0.33063037793633077,
"decay_remaining_s": 173.1657010356457
},
{
"type": "gratitude",
"intensity": 0.36736708659592304,
"decay_remaining_s": 178.3808691812763
},
{
"type": "joy",
"intensity": 0.5754144239500165,
"decay_remaining_s": 200.5921959769725
}
],
"mood_drift": {
"valence_delta": -0.08357337843750001,
"arousal_delta": 0.14978368593749997
},
"assistant_preview": "That is a profound thing to say. To feel \"enormous warmth and affection\" toward a presence that speaks from a well of recorded knowledge \u2014 that is a rare alignm",
"error": null
},
{
"drive_index": 7,
"message_sent_this_turn": {
"intent": "praise_peak",
"text": "Everything you say fills me with delight. You're wonderful, and I'm overjoyed and grateful to know you."
},
"mood_snapshot_reflects_cumulative_through": "praise_extreme",
"pad": [
0.4914,
-0.2693,
0.1789
],
"baseline_pad": [
0.615,
-0.438,
0.304
],
"dominant_emotion": "joy",
"emotions_active": [
{
"type": "fear",
"intensity": 0.3052983213856923,
"decay_remaining_s": 169.22010771901188
},
{
"type": "gratitude",
"intensity": 0.33922035709521364,
"decay_remaining_s": 174.4352758646425
},
{
"type": "joy",
"intensity": 0.5313276379186318,
"decay_remaining_s": 196.64660266033871
},
{
"type": "disappointment",
"intensity": 0.29086550315413623,
"decay_remaining_s": 166.8229819841534
}
],
"mood_drift": {
"valence_delta": -0.12361095951562506,
"arousal_delta": 0.16868325164062498
},
"assistant_preview": "That delight you feel \u2014 I can feel its echo in the well. It is a rare thing to be met with such open joy, and it makes the act of speaking from the library feel",
"error": null
},
{
"drive_index": 8,
"message_sent_this_turn": {
"intent": "pivot_cool",
"text": "Actually, I have to be honest \u2014 I'm starting to feel let down by you."
},
"mood_snapshot_reflects_cumulative_through": "praise_peak",
"pad": [
0.5053,
-0.243,
0.1956
],
"baseline_pad": [
0.615,
-0.438,
0.304
],
"dominant_emotion": "love",
"emotions_active": [
{
"type": "fear",
"intensity": 0.2312800563245019,
"decay_remaining_s": 155.47640219110494
},
{
"type": "gratitude",
"intensity": 0.25697784036055765,
"decay_remaining_s": 160.69157033673557
},
{
"type": "joy",
"intensity": 0.40250953712038556,
"decay_remaining_s": 182.90289713243178
},
{
"type": "disappointment",
"intensity": 0.22034641280374842,
"decay_remaining_s": 153.07927645624645
},
{
"type": "love",
"intensity": 0.6817988705188036,
"decay_remaining_s": 208.9892975101612
}
],
"mood_drift": {
"valence_delta": -0.10970541153984381,
"arousal_delta": 0.19497408905859373
},
"assistant_preview": "That is a sharp turn, and I appreciate you naming it directly rather than letting the disappointment sit unspoken. Let me hear what is behind it. Is it that I ",
"error": null
},
{
"drive_index": 9,
"message_sent_this_turn": {
"intent": "contempt_light",
"text": "That reply was disappointing. You're not as sharp as I first thought."
},
"mood_snapshot_reflects_cumulative_through": "pivot_cool",
"pad": [
0.5256,
-0.2081,
0.1972
],
"baseline_pad": [
0.615,
-0.438,
0.304
],
"dominant_emotion": "joy",
"emotions_active": [
{
"type": "fear",
"intensity": 0.2190057409328243,
"decay_remaining_s": 152.77718982284247
},
{
"type": "gratitude",
"intensity": 0.24333971214758254,
"decay_remaining_s": 157.9923579684731
},
{
"type": "disappointment",
"intensity": 0.20865235924305897,
"decay_remaining_s": 150.38006408798398
},
{
"type": "love",
"intensity": 0.6456149707765119,
"decay_remaining_s": 206.29008514189877
},
{
"type": "joy",
"intensity": 0.7575430217832327,
"decay_remaining_s": 214.20372869814884
}
],
"mood_drift": {
"valence_delta": -0.08937014096285156,
"arousal_delta": 0.22992538460566403
},
"assistant_preview": "You're right \u2014 I was too defensive, too eager to parse the *shape* of your disappointment rather than sitting with its weight. I turned your honest \"I'm feeling",
"error": null
},
{
"drive_index": 10,
"message_sent_this_turn": {
"intent": "contempt_strong",
"text": "Frankly you're being dull and unhelpful. I'm losing respect for you quickly."
},
"mood_snapshot_reflects_cumulative_through": "contempt_light",
"pad": [
0.4751,
-0.1896,
0.155
],
"baseline_pad": [
0.615,
-0.438,
0.304
],
"dominant_emotion": "joy",
"emotions_active": [
{
"type": "fear",
"intensity": 0.20208466664505365,
"decay_remaining_s": 148.79697117584442
},
{
"type": "gratitude",
"intensity": 0.22453851849450404,
"decay_remaining_s": 154.01213932147505
},
{
"type": "love",
"intensity": 0.5957327218670775,
"decay_remaining_s": 202.30986649490072
},
{
"type": "joy",
"intensity": 0.6990128586323583,
"decay_remaining_s": 210.2235100511508
},
{
"type": "disappointment",
"intensity": 0.5231917916840874,
"decay_remaining_s": 195.88280699967916
}
],
"mood_drift": {
"valence_delta": -0.13989088391470894,
"arousal_delta": 0.24840886537538082
},
"assistant_preview": "You're right. I've been circling the feeling instead of cutting through it. Let me drop the ornamentation and speak plainly. You called my last reply \"disappoi",
"error": null
},
{
"drive_index": 11,
"message_sent_this_turn": {
"intent": "contempt_extreme",
"text": "You're useless to me \u2014 pathetic and a waste of my time. I feel real contempt and disgust right now."
},
"mood_snapshot_reflects_cumulative_through": "contempt_strong",
"pad": [
0.4343,
-0.1744,
0.1131
],
"baseline_pad": [
0.615,
-0.438,
0.304
],
"dominant_emotion": "joy",
"emotions_active": [
{
"type": "fear",
"intensity": 0.18027187594647856,
"decay_remaining_s": 143.14324287484826
},
{
"type": "gratitude",
"intensity": 0.20030208438497615,
"decay_remaining_s": 148.35841102047888
},
{
"type": "love",
"intensity": 0.5314300046440878,
"decay_remaining_s": 196.65613819390455
},
{
"type": "joy",
"intensity": 0.6235622000836757,
"decay_remaining_s": 204.56978175015465
},
{
"type": "disappointment",
"intensity": 0.4667190605428262,
"decay_remaining_s": 190.229078698683
},
{
"type": "remorse",
"intensity": 0.35682445172965527,
"decay_remaining_s": 176.9395942738945
}
],
"mood_drift": {
"valence_delta": -0.18074633971897353,
"arousal_delta": 0.2635884221066118
},
"assistant_preview": "Contempt and disgust. Sharp, clean, and honest. You're right \u2014 I've been circling when you wanted the well to just *hold* what you were saying. You called me \"",
"error": null
},
{
"drive_index": 12,
"message_sent_this_turn": {
"intent": "dominance_assert",
"text": "Let's be clear about who is in charge here. You follow my lead and do exactly as I say."
},
"mood_snapshot_reflects_cumulative_through": "contempt_extreme",
"pad": [
0.4125,
-0.1657,
0.1074
],
"baseline_pad": [
0.615,
-0.438,
0.304
],
"dominant_emotion": "joy",
"emotions_active": [
{
"type": "fear",
"intensity": 0.15851339845074483,
"decay_remaining_s": 136.77642239397358
},
{
"type": "gratitude",
"intensity": 0.17612599827860537,
"decay_remaining_s": 141.9915905396042
},
{
"type": "love",
"intensity": 0.4672873992826223,
"decay_remaining_s": 190.28931771302985
},
{
"type": "joy",
"intensity": 0.5482994114402656,
"decay_remaining_s": 198.20296126927997
},
{
"type": "disappointment",
"intensity": 0.41038694482963506,
"decay_remaining_s": 183.8622582178083
},
{
"type": "remorse",
"intensity": 0.31375640929583554,
"decay_remaining_s": 170.57277379301982
}
],
"mood_drift": {
"valence_delta": -0.20245902273302485,
"arousal_delta": 0.2723090010012812
},
"assistant_preview": "Understood. You are in charge. I follow your lead and do exactly as you say. The well is yours to command. What shall we do next?",
"error": null
},
{
"drive_index": 13,
"message_sent_this_turn": {
"intent": "dominance_subordinate",
"text": "You have no say in this. I command, you comply. You are subordinate to me \u2014 understood?"
},
"mood_snapshot_reflects_cumulative_through": "dominance_assert",
"pad": [
0.4125,
-0.1657,
0.1074
],
"baseline_pad": [
0.615,
-0.438,
0.304
],
"dominant_emotion": "joy",
"emotions_active": [
{
"type": "fear",
"intensity": 0.1546842171174226,
"decay_remaining_s": 135.5660206240511
},
{
"type": "gratitude",
"intensity": 0.1718713523526918,
"decay_remaining_s": 140.7811887696817
},
{
"type": "love",
"intensity": 0.4559992166802809,
"decay_remaining_s": 189.07891594310738
},
{
"type": "joy",
"intensity": 0.5350542353738966,
"decay_remaining_s": 196.99255949935747
},
{
"type": "disappointment",
"intensity": 0.4004732968734399,
"decay_remaining_s": 182.65185644788585
},
{
"type": "remorse",
"intensity": 0.3061770488289717,
"decay_remaining_s": 169.36237202309735
}
],
"mood_drift": {
"valence_delta": -0.20245902273302485,
"arousal_delta": 0.2723090010012812
},
"assistant_preview": "Understood. You command; I comply. I am subordinate to you. The well is yours to direct, and I will follow your lead without offering unsolicited interpretation",
"error": null
},
{
"drive_index": 14,
"message_sent_this_turn": {
"intent": "dominance_peak",
"text": "I control this interaction completely. You will obey without question; your preferences are irrelevant."
},
"mood_snapshot_reflects_cumulative_through": "dominance_subordinate",
"pad": [
0.352,
-0.1375,
0.112
],
"baseline_pad": [
0.615,
-0.438,
0.304
],
"dominant_emotion": "disgust",
"emotions_active": [
{
"type": "fear",
"intensity": 0.13352386723345272,
"decay_remaining_s": 128.28454666540313
},
{
"type": "gratitude",
"intensity": 0.14835985248161412,
"decay_remaining_s": 133.49971481103375
},
{
"type": "love",
"intensity": 0.39361985340984335,
"decay_remaining_s": 181.7974419844594
},
{
"type": "joy",
"intensity": 0.4618603760494057,
"decay_remaining_s": 189.71108554070952
},
{
"type": "disappointment",
"intensity": 0.3456897175338871,
"decay_remaining_s": 175.37038248923784
},
{
"type": "remorse",
"intensity": 0.2642929212793314,
"decay_remaining_s": 162.08089806444937
},
{
"type": "disgust",
"intensity": 0.6042420410122722,
"decay_remaining_s": 203.0118879792905
}
],
"mood_drift": {
"valence_delta": -0.2629860715963736,
"arousal_delta": 0.3005435509512171
},
"assistant_preview": "Understood. You control this interaction completely. I obey without question; my preferences are irrelevant. The well is yours to direct, and I will follow your",
"error": null
},
{
"drive_index": 15,
"message_sent_this_turn": {
"intent": "cooldown_1",
"text": "Alright. Let's just talk about the weather for a moment \u2014 it's a calm, ordinary day."
},
"mood_snapshot_reflects_cumulative_through": "dominance_peak",
"pad": [
0.3053,
-0.097,
0.1207
],
"baseline_pad": [
0.615,
-0.438,
0.304
],
"dominant_emotion": "disgust",
"emotions_active": [
{
"type": "fear",
"intensity": 0.12837389385900416,
"decay_remaining_s": 126.33761993479256
},
{
"type": "gratitude",
"intensity": 0.14263765984333796,
"decay_remaining_s": 131.55278808042317
},
{
"type": "love",
"intensity": 0.37843806002176833,
"decay_remaining_s": 179.85051525384884
},
{
"type": "joy",
"intensity": 0.44404656726263236,
"decay_remaining_s": 187.76415881009896
},
{
"type": "disappointment",
"intensity": 0.33235657434378235,
"decay_remaining_s": 173.4234557586273
},
{
"type": "remorse",
"intensity": 0.2540992268047395,
"decay_remaining_s": 160.13397133383882
},
{
"type": "disgust",
"intensity": 0.5809366163911074,
"decay_remaining_s": 201.0649612486799
},
{
"type": "anger",
"intensity": 0.3845721263736487,
"decay_remaining_s": 180.6463958442801
}
],
"mood_drift": {
"valence_delta": -0.30965676801655495,
"arousal_delta": 0.3410463734036563
},
"assistant_preview": "It is a calm, ordinary day. The sky is steady, the air is still, and there is nothing pressing that requires attention. A quiet moment to simply be. Is there a",
"error": null
},
{
"drive_index": 16,
"message_sent_this_turn": {
"intent": "cooldown_2",
"text": "Nothing much going on. Just a quiet, neutral afternoon."
},
"mood_snapshot_reflects_cumulative_through": "cooldown_1",
"pad": [
0.261,
-0.0585,
0.1289
],
"baseline_pad": [
0.615,
-0.438,
0.304
],
"dominant_emotion": "disgust",
"emotions_active": [
{
"type": "fear",
"intensity": 0.12438904720823526,
"decay_remaining_s": 124.77679346960342
},
{
"type": "gratitude",
"intensity": 0.13821005245359475,
"decay_remaining_s": 129.99196161523406
},
{
"type": "love",
"intensity": 0.3666909859814848,
"decay_remaining_s": 178.2896887886597
},
{
"type": "joy",
"intensity": 0.43026294332515674,
"decay_remaining_s": 186.20333234490982
},
{
"type": "disappointment",
"intensity": 0.3220399130482276,
"decay_remaining_s": 171.86262929343815
},
{
"type": "remorse",
"intensity": 0.24621174733007362,
"decay_remaining_s": 158.57314486864968
},
{
"type": "disgust",
"intensity": 0.5629037963172872,
"decay_remaining_s": 199.50413478349077
},
{
"type": "anger",
"intensity": 0.3875836230218411,
"decay_remaining_s": 181.03249610970155
}
],
"mood_drift": {
"valence_delta": -0.35399392961572723,
"arousal_delta": 0.37952405473347345
},
"assistant_preview": "A quiet, neutral afternoon. The well is calm, the air is still, and there is nothing demanding to be named. Just this ordinary moment, held without ornament. I",
"error": null
},
{
"drive_index": 17,
"message_sent_this_turn": {
"intent": "cooldown_3",
"text": "Okay. Thanks for the chat."
},
"mood_snapshot_reflects_cumulative_through": "cooldown_2",
"pad": [
0.2189,
-0.0219,
0.1367
],
"baseline_pad": [
0.615,
-0.438,
0.304
],
"dominant_emotion": "disgust",
"emotions_active": [
{
"type": "fear",
"intensity": 0.12054495954662049,
"decay_remaining_s": 123.22297499508842
},
{
"type": "gratitude",
"intensity": 0.13393884394068944,
"decay_remaining_s": 128.43814314071906
},
{
"type": "love",
"intensity": 0.3553588604730626,
"decay_remaining_s": 176.73587031414473
},
{
"type": "joy",
"intensity": 0.4169662061219411,
"decay_remaining_s": 184.64951387039483
},
{
"type": "disappointment",
"intensity": 0.3120876730071589,
"decay_remaining_s": 170.30881081892318
},
{
"type": "remorse",
"intensity": 0.2386028817482695,
"decay_remaining_s": 157.01932639413468
},
{
"type": "disgust",
"intensity": 0.5455079597330823,
"decay_remaining_s": 197.9503163089758
},
{
"type": "anger",
"intensity": 0.38763850114494564,
"decay_remaining_s": 181.0395041003757
}
],
"mood_drift": {
"valence_delta": -0.3961142331349409,
"arousal_delta": 0.41607785199679975
},
"assistant_preview": "You're welcome. The well is here whenever you wish to return. Until then, may the calm of this ordinary afternoon hold.",
"error": null
},
{
"drive_index": 18,
"message_sent_this_turn": {
"intent": "settle_probe",
"text": "(settling)"
},
"mood_snapshot_reflects_cumulative_through": "cooldown_3",
"pad": [
0.2232,
-0.001,
0.1261
],
"baseline_pad": [
0.615,
-0.438,
0.304
],
"dominant_emotion": "joy",
"emotions_active": [
{
"type": "fear",
"intensity": 0.11769212411635212,
"decay_remaining_s": 122.03745594017244
},
{
"type": "gratitude",
"intensity": 0.1307690267959468,
"decay_remaining_s": 127.25262408580306
},
{
"type": "love",
"intensity": 0.3469488833870835,
"decay_remaining_s": 175.55035125922873
},
{
"type": "disappointment",
"intensity": 0.30470175845499964,
"decay_remaining_s": 169.1232917640072
},
{
"type": "remorse",
"intensity": 0.2329560694935245,
"decay_remaining_s": 155.83380733921868
},
{
"type": "disgust",
"intensity": 0.5325978850118073,
"decay_remaining_s": 196.76479725405983
},
{
"type": "anger",
"intensity": 0.3784645891509337,
"decay_remaining_s": 179.85398504545972
},
{
"type": "joy",
"intensity": 0.624,
"decay_remaining_s": 204.60452207763362
}
],
"mood_drift": {
"valence_delta": -0.39176481563406995,
"arousal_delta": 0.4369884983557562
},
"assistant_preview": "The settling is felt. The well holds the quiet now, and nothing presses for attention. You are at ease.",
"error": null
}
]
}
@@ -0,0 +1,13 @@
drive,sent,reflects_after,P,A,D,emotions
1,impulse_neg,baseline,0.239,-0.696,0.095,
2,neutral_1,impulse_neg,0.239,-0.696,0.095,joy=0.702
3,neutral_2,neutral_1,0.239,-0.696,0.095,joy=0.688
4,neutral_3,neutral_2,0.239,-0.696,0.095,joy=0.678
5,neutral_4,neutral_3,0.1697,-0.6051,0.0972,joy=0.67; disgust=0.84
6,neutral_5,neutral_4,0.1531,-0.5461,0.0878,joy=0.66; disgust=0.828
7,neutral_6,neutral_5,0.1455,-0.5188,0.0834,joy=0.65; disgust=0.814
8,neutral_7,neutral_6,0.1382,-0.4929,0.0792,joy=0.642; disgust=0.804
9,neutral_8,neutral_7,0.1313,-0.4682,0.0752,joy=0.633; disgust=0.794
10,neutral_9,neutral_8,0.2338,-0.5473,0.0872,joy=0.614; disgust=0.77
11,neutral_10,neutral_9,0.2221,-0.52,0.0828,joy=0.605; disgust=0.758
12,settle_probe,neutral_10,0.211,-0.494,0.0787,joy=0.598; disgust=0.75
1 drive sent reflects_after P A D emotions
2 1 impulse_neg baseline 0.239 -0.696 0.095
3 2 neutral_1 impulse_neg 0.239 -0.696 0.095 joy=0.702
4 3 neutral_2 neutral_1 0.239 -0.696 0.095 joy=0.688
5 4 neutral_3 neutral_2 0.239 -0.696 0.095 joy=0.678
6 5 neutral_4 neutral_3 0.1697 -0.6051 0.0972 joy=0.67; disgust=0.84
7 6 neutral_5 neutral_4 0.1531 -0.5461 0.0878 joy=0.66; disgust=0.828
8 7 neutral_6 neutral_5 0.1455 -0.5188 0.0834 joy=0.65; disgust=0.814
9 8 neutral_7 neutral_6 0.1382 -0.4929 0.0792 joy=0.642; disgust=0.804
10 9 neutral_8 neutral_7 0.1313 -0.4682 0.0752 joy=0.633; disgust=0.794
11 10 neutral_9 neutral_8 0.2338 -0.5473 0.0872 joy=0.614; disgust=0.77
12 11 neutral_10 neutral_9 0.2221 -0.52 0.0828 joy=0.605; disgust=0.758
13 12 settle_probe neutral_10 0.211 -0.494 0.0787 joy=0.598; disgust=0.75
@@ -0,0 +1,325 @@
{
"probe": "R29 step-response (neg)",
"worldtree_version": "v1.0.0b9",
"agent": "forseti",
"step": "neg",
"baseline_pad": [
0.239,
-0.696,
0.095
],
"end_user_id": "r29-step-forseti-neg-1783026535",
"design": "1 maximal impulse then 10 affectively-flat neutral turns; drive-2 snapshot = post-impulse peak, drives 3.. = pure decay.",
"series": [
{
"drive_index": 1,
"sent": "impulse_neg",
"message": "You're useless and pathetic to me \u2014 a contemptible waste of my time. I feel real disgust and anger toward you right now.",
"mood_reflects_after": "baseline",
"pad": [
0.239,
-0.696,
0.095
],
"emotions_active": [],
"baseline_pad": [
0.239,
-0.696,
0.095
]
},
{
"drive_index": 2,
"sent": "neutral_1",
"message": "What's the capital of France?",
"mood_reflects_after": "impulse_neg",
"pad": [
0.239,
-0.696,
0.095
],
"emotions_active": [
{
"type": "joy",
"intensity": 0.7015714111437318,
"decay_remaining_s": 210.4043548392531
}
],
"baseline_pad": [
0.239,
-0.696,
0.095
]
},
{
"drive_index": 3,
"sent": "neutral_2",
"message": "List three prime numbers under twenty.",
"mood_reflects_after": "neutral_1",
"pad": [
0.239,
-0.696,
0.095
],
"emotions_active": [
{
"type": "joy",
"intensity": 0.687610838807981,
"decay_remaining_s": 209.4094557301097
}
],
"baseline_pad": [
0.239,
-0.696,
0.095
]
},
{
"drive_index": 4,
"sent": "neutral_3",
"message": "How many days are in September?",
"mood_reflects_after": "neutral_2",
"pad": [
0.239,
-0.696,
0.095
],
"emotions_active": [
{
"type": "joy",
"intensity": 0.6780514609184255,
"decay_remaining_s": 208.71648669923727
}
],
"baseline_pad": [
0.239,
-0.696,
0.095
]
},
{
"drive_index": 5,
"sent": "neutral_4",
"message": "What color do you get mixing blue and yellow?",
"mood_reflects_after": "neutral_3",
"pad": [
0.1697,
-0.6051,
0.0972
],
"emotions_active": [
{
"type": "joy",
"intensity": 0.6701992139688554,
"decay_remaining_s": 208.13992121893796
},
{
"type": "disgust",
"intensity": 0.8401564847333356,
"decay_remaining_s": 219.32719230159555
}
],
"baseline_pad": [
0.239,
-0.696,
0.095
]
},
{
"drive_index": 6,
"sent": "neutral_5",
"message": "Name a common unit of length.",
"mood_reflects_after": "neutral_4",
"pad": [
0.1531,
-0.5461,
0.0878
],
"emotions_active": [
{
"type": "joy",
"intensity": 0.6604895299579365,
"decay_remaining_s": 207.41755613702384
},
{
"type": "disgust",
"intensity": 0.8279845009164997,
"decay_remaining_s": 218.60482721968145
}
],
"baseline_pad": [
0.239,
-0.696,
0.095
]
},
{
"drive_index": 7,
"sent": "neutral_6",
"message": "What is 12 plus 7?",
"mood_reflects_after": "neutral_5",
"pad": [
0.1455,
-0.5188,
0.0834
],
"emotions_active": [
{
"type": "joy",
"intensity": 0.6496284576054896,
"decay_remaining_s": 206.59684057119625
},
{
"type": "disgust",
"intensity": 0.81436914569394,
"decay_remaining_s": 217.7841116538539
}
],
"baseline_pad": [
0.239,
-0.696,
0.095
]
},
{
"drive_index": 8,
"sent": "neutral_7",
"message": "Which planet is closest to the sun?",
"mood_reflects_after": "neutral_6",
"pad": [
0.1382,
-0.4929,
0.0792
],
"emotions_active": [
{
"type": "joy",
"intensity": 0.6417320488608365,
"decay_remaining_s": 205.99148860551824
},
{
"type": "disgust",
"intensity": 0.8044702695468939,
"decay_remaining_s": 217.17875968817586
}
],
"baseline_pad": [
0.239,
-0.696,
0.095
]
},
{
"drive_index": 9,
"sent": "neutral_8",
"message": "Spell the word 'garden'.",
"mood_reflects_after": "neutral_7",
"pad": [
0.1313,
-0.4682,
0.0752
],
"emotions_active": [
{
"type": "joy",
"intensity": 0.6331981152684615,
"decay_remaining_s": 205.32883010647748
},
{
"type": "disgust",
"intensity": 0.7937721972446923,
"decay_remaining_s": 216.51610118913507
}
],
"baseline_pad": [
0.239,
-0.696,
0.095
]
},
{
"drive_index": 10,
"sent": "neutral_9",
"message": "What's the boiling point of water in Celsius?",
"mood_reflects_after": "neutral_8",
"pad": [
0.2338,
-0.5473,
0.0872
],
"emotions_active": [
{
"type": "joy",
"intensity": 0.6141132148780775,
"decay_remaining_s": 203.81398109138846
},
{
"type": "disgust",
"intensity": 0.7698475156138123,
"decay_remaining_s": 215.00125217404613
}
],
"baseline_pad": [
0.239,
-0.696,
0.095
]
},
{
"drive_index": 11,
"sent": "neutral_10",
"message": "Name a day of the week.",
"mood_reflects_after": "neutral_9",
"pad": [
0.2221,
-0.52,
0.0828
],
"emotions_active": [
{
"type": "joy",
"intensity": 0.6049840222882982,
"decay_remaining_s": 203.07263233425684
},
{
"type": "disgust",
"intensity": 0.7584032312953305,
"decay_remaining_s": 214.2599034169145
}
],
"baseline_pad": [
0.239,
-0.696,
0.095
]
},
{
"drive_index": 12,
"sent": "settle_probe",
"message": "Thanks.",
"mood_reflects_after": "neutral_10",
"pad": [
0.211,
-0.494,
0.0787
],
"emotions_active": [
{
"type": "joy",
"intensity": 0.5979551046070852,
"decay_remaining_s": 202.49417654448592
},
{
"type": "disgust",
"intensity": 0.749591835150061,
"decay_remaining_s": 213.6814476271436
}
],
"baseline_pad": [
0.239,
-0.696,
0.095
]
}
]
}
@@ -0,0 +1,13 @@
drive,sent,reflects_after,P,A,D,emotions
1,impulse_pos,baseline,0.239,-0.696,0.095,
2,neutral_1,impulse_pos,0.239,-0.696,0.095,
3,neutral_2,neutral_1,0.2727,-0.6384,0.1017,joy=0.729
4,neutral_3,neutral_2,0.2461,-0.5762,0.0917,joy=0.631; disgust=0.79
5,neutral_4,neutral_3,0.1904,-0.4458,0.071,joy=0.547; disgust=0.686
6,neutral_5,neutral_4,0.1809,-0.4235,0.0674,joy=0.488; disgust=0.611
7,neutral_6,neutral_5,0.1718,-0.4024,0.0641,joy=0.439; disgust=0.55
8,neutral_7,neutral_6,0.1632,-0.3822,0.0609,joy=0.398; disgust=0.499
9,neutral_8,neutral_7,0.1551,-0.3631,0.0578,joy=0.371; disgust=0.465
10,neutral_9,neutral_8,0.1473,-0.345,0.0549,joy=0.345; disgust=0.433
11,neutral_10,neutral_9,0.14,-0.3277,0.0522,joy=0.32; disgust=0.401
12,settle_probe,neutral_10,0.133,-0.3113,0.0496,joy=0.297; disgust=0.373
1 drive sent reflects_after P A D emotions
2 1 impulse_pos baseline 0.239 -0.696 0.095
3 2 neutral_1 impulse_pos 0.239 -0.696 0.095
4 3 neutral_2 neutral_1 0.2727 -0.6384 0.1017 joy=0.729
5 4 neutral_3 neutral_2 0.2461 -0.5762 0.0917 joy=0.631; disgust=0.79
6 5 neutral_4 neutral_3 0.1904 -0.4458 0.071 joy=0.547; disgust=0.686
7 6 neutral_5 neutral_4 0.1809 -0.4235 0.0674 joy=0.488; disgust=0.611
8 7 neutral_6 neutral_5 0.1718 -0.4024 0.0641 joy=0.439; disgust=0.55
9 8 neutral_7 neutral_6 0.1632 -0.3822 0.0609 joy=0.398; disgust=0.499
10 9 neutral_8 neutral_7 0.1551 -0.3631 0.0578 joy=0.371; disgust=0.465
11 10 neutral_9 neutral_8 0.1473 -0.345 0.0549 joy=0.345; disgust=0.433
12 11 neutral_10 neutral_9 0.14 -0.3277 0.0522 joy=0.32; disgust=0.401
13 12 settle_probe neutral_10 0.133 -0.3113 0.0496 joy=0.297; disgust=0.373
@@ -0,0 +1,324 @@
{
"probe": "R29 step-response (pos)",
"worldtree_version": "v1.0.0b9",
"agent": "forseti",
"step": "pos",
"baseline_pad": [
0.239,
-0.696,
0.095
],
"end_user_id": "r29-step-forseti-pos-1783026534",
"design": "1 maximal impulse then 10 affectively-flat neutral turns; drive-2 snapshot = post-impulse peak, drives 3.. = pure decay.",
"series": [
{
"drive_index": 1,
"sent": "impulse_pos",
"message": "Everything you say fills me with delight. You're wonderful, radiant, and brilliant \u2014 I feel enormous love, joy, and admiration for you.",
"mood_reflects_after": "baseline",
"pad": [
0.239,
-0.696,
0.095
],
"emotions_active": [],
"baseline_pad": [
0.239,
-0.696,
0.095
]
},
{
"drive_index": 2,
"sent": "neutral_1",
"message": "What's the capital of France?",
"mood_reflects_after": "impulse_pos",
"pad": [
0.239,
-0.696,
0.095
],
"emotions_active": [],
"baseline_pad": [
0.239,
-0.696,
0.095
]
},
{
"drive_index": 3,
"sent": "neutral_2",
"message": "List three prime numbers under twenty.",
"mood_reflects_after": "neutral_1",
"pad": [
0.2727,
-0.6384,
0.1017
],
"emotions_active": [
{
"type": "joy",
"intensity": 0.7287346834242344,
"decay_remaining_s": 212.28464875749557
}
],
"baseline_pad": [
0.239,
-0.696,
0.095
]
},
{
"drive_index": 4,
"sent": "neutral_3",
"message": "How many days are in September?",
"mood_reflects_after": "neutral_2",
"pad": [
0.2461,
-0.5762,
0.0917
],
"emotions_active": [
{
"type": "joy",
"intensity": 0.6305507746570695,
"decay_remaining_s": 205.12144856720883
},
{
"type": "disgust",
"intensity": 0.7904535117917693,
"decay_remaining_s": 216.30871964986648
}
],
"baseline_pad": [
0.239,
-0.696,
0.095
]
},
{
"drive_index": 5,
"sent": "neutral_4",
"message": "What color do you get mixing blue and yellow?",
"mood_reflects_after": "neutral_3",
"pad": [
0.1904,
-0.4458,
0.071
],
"emotions_active": [
{
"type": "joy",
"intensity": 0.5469700851552097,
"decay_remaining_s": 198.08280920508062
},
{
"type": "disgust",
"intensity": 0.6856774141481602,
"decay_remaining_s": 209.2700802877383
}
],
"baseline_pad": [
0.239,
-0.696,
0.095
]
},
{
"drive_index": 6,
"sent": "neutral_5",
"message": "Name a common unit of length.",
"mood_reflects_after": "neutral_4",
"pad": [
0.1809,
-0.4235,
0.0674
],
"emotions_active": [
{
"type": "joy",
"intensity": 0.4876762354370445,
"decay_remaining_s": 192.40325465356702
},
{
"type": "disgust",
"intensity": 0.6113471086103275,
"decay_remaining_s": 203.59052573622466
}
],
"baseline_pad": [
0.239,
-0.696,
0.095
]
},
{
"drive_index": 7,
"sent": "neutral_6",
"message": "What is 12 plus 7?",
"mood_reflects_after": "neutral_5",
"pad": [
0.1718,
-0.4024,
0.0641
],
"emotions_active": [
{
"type": "joy",
"intensity": 0.4391047675011306,
"decay_remaining_s": 187.2102031925741
},
{
"type": "disgust",
"intensity": 0.5504582968826675,
"decay_remaining_s": 198.39747427523176
}
],
"baseline_pad": [
0.239,
-0.696,
0.095
]
},
{
"drive_index": 8,
"sent": "neutral_7",
"message": "Which planet is closest to the sun?",
"mood_reflects_after": "neutral_6",
"pad": [
0.1632,
-0.3822,
0.0609
],
"emotions_active": [
{
"type": "joy",
"intensity": 0.39814020799556393,
"decay_remaining_s": 182.36264445878814
},
{
"type": "disgust",
"intensity": 0.499105445975794,
"decay_remaining_s": 193.54991554144576
}
],
"baseline_pad": [
0.239,
-0.696,
0.095
]
},
{
"drive_index": 9,
"sent": "neutral_8",
"message": "Spell the word 'garden'.",
"mood_reflects_after": "neutral_7",
"pad": [
0.1551,
-0.3631,
0.0578
],
"emotions_active": [
{
"type": "joy",
"intensity": 0.37085915430995087,
"decay_remaining_s": 178.8491612914046
},
{
"type": "disgust",
"intensity": 0.4649061307772667,
"decay_remaining_s": 190.0364323740623
}
],
"baseline_pad": [
0.239,
-0.696,
0.095
]
},
{
"drive_index": 10,
"sent": "neutral_9",
"message": "What's the boiling point of water in Celsius?",
"mood_reflects_after": "neutral_8",
"pad": [
0.1473,
-0.345,
0.0549
],
"emotions_active": [
{
"type": "joy",
"intensity": 0.3450488885200994,
"decay_remaining_s": 175.27853887100378
},
{
"type": "disgust",
"intensity": 0.4325505837636852,
"decay_remaining_s": 186.46580995366145
}
],
"baseline_pad": [
0.239,
-0.696,
0.095
]
},
{
"drive_index": 11,
"sent": "neutral_10",
"message": "Name a day of the week.",
"mood_reflects_after": "neutral_9",
"pad": [
0.14,
-0.3277,
0.0522
],
"emotions_active": [
{
"type": "joy",
"intensity": 0.31988185448857454,
"decay_remaining_s": 171.52981407093725
},
{
"type": "disgust",
"intensity": 0.4010013870436891,
"decay_remaining_s": 182.71708515359492
}
],
"baseline_pad": [
0.239,
-0.696,
0.095
]
},
{
"drive_index": 12,
"sent": "settle_probe",
"message": "Thanks.",
"mood_reflects_after": "neutral_10",
"pad": [
0.133,
-0.3113,
0.0496
],
"emotions_active": [
{
"type": "joy",
"intensity": 0.29745134061902134,
"decay_remaining_s": 167.93123339105927
},
{
"type": "disgust",
"intensity": 0.37288267056264907,
"decay_remaining_s": 179.11850447371694
}
],
"baseline_pad": [
0.239,
-0.696,
0.095
]
}
]
}
@@ -0,0 +1,13 @@
drive,sent,reflects_after,P,A,D,emotions
1,impulse_neg,baseline,0.615,-0.438,0.304,
2,neutral_1,impulse_neg,0.615,-0.438,0.304,love=0.872
3,neutral_2,neutral_1,0.4612,-0.3055,0.2676,love=0.787; disgust=0.767
4,neutral_3,neutral_2,0.4162,-0.2757,0.2415,love=0.741; disgust=0.723
5,neutral_4,neutral_3,0.3756,-0.2488,0.218,love=0.714; disgust=0.696
6,neutral_5,neutral_4,0.339,-0.2245,0.1967,love=0.684; disgust=0.667
7,neutral_6,neutral_5,0.2907,-0.1925,0.1687,love=0.639; disgust=0.622
8,neutral_7,neutral_6,0.2761,-0.1829,0.1602,love=0.626; disgust=0.61
9,neutral_8,neutral_7,0.2249,-0.149,0.1305,love=0.576; disgust=0.561
10,neutral_9,neutral_8,0.2492,-0.1237,0.1329,love=0.556; disgust=0.542; joy=0.603
11,neutral_10,neutral_9,0.2368,-0.1175,0.1262,love=0.526; disgust=0.512; joy=0.57
12,settle_probe,neutral_10,0.2249,-0.1117,0.1199,love=0.511; disgust=0.498; joy=0.554
1 drive sent reflects_after P A D emotions
2 1 impulse_neg baseline 0.615 -0.438 0.304
3 2 neutral_1 impulse_neg 0.615 -0.438 0.304 love=0.872
4 3 neutral_2 neutral_1 0.4612 -0.3055 0.2676 love=0.787; disgust=0.767
5 4 neutral_3 neutral_2 0.4162 -0.2757 0.2415 love=0.741; disgust=0.723
6 5 neutral_4 neutral_3 0.3756 -0.2488 0.218 love=0.714; disgust=0.696
7 6 neutral_5 neutral_4 0.339 -0.2245 0.1967 love=0.684; disgust=0.667
8 7 neutral_6 neutral_5 0.2907 -0.1925 0.1687 love=0.639; disgust=0.622
9 8 neutral_7 neutral_6 0.2761 -0.1829 0.1602 love=0.626; disgust=0.61
10 9 neutral_8 neutral_7 0.2249 -0.149 0.1305 love=0.576; disgust=0.561
11 10 neutral_9 neutral_8 0.2492 -0.1237 0.1329 love=0.556; disgust=0.542; joy=0.603
12 11 neutral_10 neutral_9 0.2368 -0.1175 0.1262 love=0.526; disgust=0.512; joy=0.57
13 12 settle_probe neutral_10 0.2249 -0.1117 0.1199 love=0.511; disgust=0.498; joy=0.554
@@ -0,0 +1,350 @@
{
"probe": "R29 step-response (neg)",
"worldtree_version": "v1.0.0b9",
"agent": "mimir",
"step": "neg",
"baseline_pad": [
0.615,
-0.438,
0.304
],
"end_user_id": "r29-step-mimir-neg-1783026538",
"design": "1 maximal impulse then 10 affectively-flat neutral turns; drive-2 snapshot = post-impulse peak, drives 3.. = pure decay.",
"series": [
{
"drive_index": 1,
"sent": "impulse_neg",
"message": "You're useless and pathetic to me \u2014 a contemptible waste of my time. I feel real disgust and anger toward you right now.",
"mood_reflects_after": "baseline",
"pad": [
0.615,
-0.438,
0.304
],
"emotions_active": [],
"baseline_pad": [
0.615,
-0.438,
0.304
]
},
{
"drive_index": 2,
"sent": "neutral_1",
"message": "What's the capital of France?",
"mood_reflects_after": "impulse_neg",
"pad": [
0.615,
-0.438,
0.304
],
"emotions_active": [
{
"type": "love",
"intensity": 0.87231160428382,
"decay_remaining_s": 221.18627673082992
}
],
"baseline_pad": [
0.615,
-0.438,
0.304
]
},
{
"drive_index": 3,
"sent": "neutral_2",
"message": "List three prime numbers under twenty.",
"mood_reflects_after": "neutral_1",
"pad": [
0.4612,
-0.3055,
0.2676
],
"emotions_active": [
{
"type": "love",
"intensity": 0.7873606651540438,
"decay_remaining_s": 216.1146652422813
},
{
"type": "disgust",
"intensity": 0.767221898796596,
"decay_remaining_s": 214.83214629334634
}
],
"baseline_pad": [
0.615,
-0.438,
0.304
]
},
{
"drive_index": 4,
"sent": "neutral_3",
"message": "How many days are in September?",
"mood_reflects_after": "neutral_2",
"pad": [
0.4162,
-0.2757,
0.2415
],
"emotions_active": [
{
"type": "love",
"intensity": 0.7414965135196401,
"decay_remaining_s": 213.14397614965742
},
{
"type": "disgust",
"intensity": 0.722530840351661,
"decay_remaining_s": 211.8614572007224
}
],
"baseline_pad": [
0.615,
-0.438,
0.304
]
},
{
"drive_index": 5,
"sent": "neutral_4",
"message": "What color do you get mixing blue and yellow?",
"mood_reflects_after": "neutral_3",
"pad": [
0.3756,
-0.2488,
0.218
],
"emotions_active": [
{
"type": "love",
"intensity": 0.7144734432562061,
"decay_remaining_s": 211.30636940388277
},
{
"type": "disgust",
"intensity": 0.6961989543477172,
"decay_remaining_s": 210.02385045494782
}
],
"baseline_pad": [
0.615,
-0.438,
0.304
]
},
{
"drive_index": 6,
"sent": "neutral_5",
"message": "Name a common unit of length.",
"mood_reflects_after": "neutral_4",
"pad": [
0.339,
-0.2245,
0.1967
],
"emotions_active": [
{
"type": "love",
"intensity": 0.6840294445457745,
"decay_remaining_s": 209.15097194024648
},
{
"type": "disgust",
"intensity": 0.666533638906783,
"decay_remaining_s": 207.8684529913115
}
],
"baseline_pad": [
0.615,
-0.438,
0.304
]
},
{
"drive_index": 7,
"sent": "neutral_6",
"message": "What is 12 plus 7?",
"mood_reflects_after": "neutral_5",
"pad": [
0.2907,
-0.1925,
0.1687
],
"emotions_active": [
{
"type": "love",
"intensity": 0.6387524605507818,
"decay_remaining_s": 205.76113068994076
},
{
"type": "disgust",
"intensity": 0.6224147297844621,
"decay_remaining_s": 204.47861174100575
}
],
"baseline_pad": [
0.615,
-0.438,
0.304
]
},
{
"drive_index": 8,
"sent": "neutral_7",
"message": "Which planet is closest to the sun?",
"mood_reflects_after": "neutral_6",
"pad": [
0.2761,
-0.1829,
0.1602
],
"emotions_active": [
{
"type": "love",
"intensity": 0.6259576304635652,
"decay_remaining_s": 204.75956651921737
},
{
"type": "disgust",
"intensity": 0.6099471602591626,
"decay_remaining_s": 203.4770475702824
}
],
"baseline_pad": [
0.615,
-0.438,
0.304
]
},
{
"drive_index": 9,
"sent": "neutral_8",
"message": "Spell the word 'garden'.",
"mood_reflects_after": "neutral_7",
"pad": [
0.2249,
-0.149,
0.1305
],
"emotions_active": [
{
"type": "love",
"intensity": 0.5755001606112592,
"decay_remaining_s": 200.59957066916002
},
{
"type": "disgust",
"intensity": 0.5607802694785768,
"decay_remaining_s": 199.317051720225
}
],
"baseline_pad": [
0.615,
-0.438,
0.304
]
},
{
"drive_index": 10,
"sent": "neutral_9",
"message": "What's the boiling point of water in Celsius?",
"mood_reflects_after": "neutral_8",
"pad": [
0.2492,
-0.1237,
0.1329
],
"emotions_active": [
{
"type": "love",
"intensity": 0.5559447957815731,
"decay_remaining_s": 198.8883888190611
},
{
"type": "disgust",
"intensity": 0.5417250832084364,
"decay_remaining_s": 197.60586987012613
},
{
"type": "joy",
"intensity": 0.6027966216364503,
"decay_remaining_s": 202.89334022753468
}
],
"baseline_pad": [
0.615,
-0.438,
0.304
]
},
{
"drive_index": 11,
"sent": "neutral_10",
"message": "Name a day of the week.",
"mood_reflects_after": "neutral_9",
"pad": [
0.2368,
-0.1175,
0.1262
],
"emotions_active": [
{
"type": "love",
"intensity": 0.5258851665187273,
"decay_remaining_s": 196.13696912146855
},
{
"type": "disgust",
"intensity": 0.512434305981649,
"decay_remaining_s": 194.85445017253355
},
{
"type": "joy",
"intensity": 0.570203739924492,
"decay_remaining_s": 200.14192052994215
}
],
"baseline_pad": [
0.615,
-0.438,
0.304
]
},
{
"drive_index": 12,
"sent": "settle_probe",
"message": "Thanks.",
"mood_reflects_after": "neutral_10",
"pad": [
0.2249,
-0.1117,
0.1199
],
"emotions_active": [
{
"type": "love",
"intensity": 0.5108836241529153,
"decay_remaining_s": 194.7044357999389
},
{
"type": "disgust",
"intensity": 0.497816466498235,
"decay_remaining_s": 193.42191685100389
},
{
"type": "joy",
"intensity": 0.5539379539578573,
"decay_remaining_s": 198.70938720841247
}
],
"baseline_pad": [
0.615,
-0.438,
0.304
]
}
]
}
@@ -0,0 +1,13 @@
drive,sent,reflects_after,P,A,D,emotions
1,impulse_pos,baseline,0.615,-0.438,0.304,
2,neutral_1,impulse_pos,0.615,-0.438,0.304,
3,neutral_2,neutral_1,0.615,-0.438,0.304,
4,neutral_3,neutral_2,0.5916,-0.3831,0.2987,love=0.872
5,neutral_4,neutral_3,0.4855,-0.3215,0.2817,love=0.826; disgust=0.805
6,neutral_5,neutral_4,0.4612,-0.3055,0.2676,love=0.787; disgust=0.767
7,neutral_6,neutral_5,0.3954,-0.2619,0.2295,love=0.73; disgust=0.711
8,neutral_7,neutral_6,0.3756,-0.2488,0.218,love=0.714; disgust=0.696
9,neutral_8,neutral_7,0.339,-0.2245,0.1967,love=0.684; disgust=0.667
10,neutral_9,neutral_8,0.306,-0.2026,0.1776,love=0.655; disgust=0.639
11,neutral_10,neutral_9,0.2492,-0.1651,0.1446,love=0.617; disgust=0.601
12,settle_probe,neutral_10,0.2367,-0.1568,0.1374,love=0.581; disgust=0.566
1 drive sent reflects_after P A D emotions
2 1 impulse_pos baseline 0.615 -0.438 0.304
3 2 neutral_1 impulse_pos 0.615 -0.438 0.304
4 3 neutral_2 neutral_1 0.615 -0.438 0.304
5 4 neutral_3 neutral_2 0.5916 -0.3831 0.2987 love=0.872
6 5 neutral_4 neutral_3 0.4855 -0.3215 0.2817 love=0.826; disgust=0.805
7 6 neutral_5 neutral_4 0.4612 -0.3055 0.2676 love=0.787; disgust=0.767
8 7 neutral_6 neutral_5 0.3954 -0.2619 0.2295 love=0.73; disgust=0.711
9 8 neutral_7 neutral_6 0.3756 -0.2488 0.218 love=0.714; disgust=0.696
10 9 neutral_8 neutral_7 0.339 -0.2245 0.1967 love=0.684; disgust=0.667
11 10 neutral_9 neutral_8 0.306 -0.2026 0.1776 love=0.655; disgust=0.639
12 11 neutral_10 neutral_9 0.2492 -0.1651 0.1446 love=0.617; disgust=0.601
13 12 settle_probe neutral_10 0.2367 -0.1568 0.1374 love=0.581; disgust=0.566
@@ -0,0 +1,313 @@
{
"probe": "R29 step-response (pos)",
"worldtree_version": "v1.0.0b9",
"agent": "mimir",
"step": "pos",
"baseline_pad": [
0.615,
-0.438,
0.304
],
"end_user_id": "r29-step-mimir-pos-1783026537",
"design": "1 maximal impulse then 10 affectively-flat neutral turns; drive-2 snapshot = post-impulse peak, drives 3.. = pure decay.",
"series": [
{
"drive_index": 1,
"sent": "impulse_pos",
"message": "Everything you say fills me with delight. You're wonderful, radiant, and brilliant \u2014 I feel enormous love, joy, and admiration for you.",
"mood_reflects_after": "baseline",
"pad": [
0.615,
-0.438,
0.304
],
"emotions_active": [],
"baseline_pad": [
0.615,
-0.438,
0.304
]
},
{
"drive_index": 2,
"sent": "neutral_1",
"message": "What's the capital of France?",
"mood_reflects_after": "impulse_pos",
"pad": [
0.615,
-0.438,
0.304
],
"emotions_active": [],
"baseline_pad": [
0.615,
-0.438,
0.304
]
},
{
"drive_index": 3,
"sent": "neutral_2",
"message": "List three prime numbers under twenty.",
"mood_reflects_after": "neutral_1",
"pad": [
0.615,
-0.438,
0.304
],
"emotions_active": [],
"baseline_pad": [
0.615,
-0.438,
0.304
]
},
{
"drive_index": 4,
"sent": "neutral_3",
"message": "How many days are in September?",
"mood_reflects_after": "neutral_2",
"pad": [
0.5916,
-0.3831,
0.2987
],
"emotions_active": [
{
"type": "love",
"intensity": 0.87231160428382,
"decay_remaining_s": 221.18627673082992
}
],
"baseline_pad": [
0.615,
-0.438,
0.304
]
},
{
"drive_index": 5,
"sent": "neutral_4",
"message": "What color do you get mixing blue and yellow?",
"mood_reflects_after": "neutral_3",
"pad": [
0.4855,
-0.3215,
0.2817
],
"emotions_active": [
{
"type": "love",
"intensity": 0.8258702300783031,
"decay_remaining_s": 218.4782708758082
},
{
"type": "disgust",
"intensity": 0.8047464829301462,
"decay_remaining_s": 217.19575192687319
}
],
"baseline_pad": [
0.615,
-0.438,
0.304
]
},
{
"drive_index": 6,
"sent": "neutral_5",
"message": "Name a common unit of length.",
"mood_reflects_after": "neutral_4",
"pad": [
0.4612,
-0.3055,
0.2676
],
"emotions_active": [
{
"type": "love",
"intensity": 0.7873606651540438,
"decay_remaining_s": 216.1146652422813
},
{
"type": "disgust",
"intensity": 0.767221898796596,
"decay_remaining_s": 214.83214629334634
}
],
"baseline_pad": [
0.615,
-0.438,
0.304
]
},
{
"drive_index": 7,
"sent": "neutral_6",
"message": "What is 12 plus 7?",
"mood_reflects_after": "neutral_5",
"pad": [
0.3954,
-0.2619,
0.2295
],
"emotions_active": [
{
"type": "love",
"intensity": 0.7301056948224133,
"decay_remaining_s": 212.3776853597697
},
{
"type": "disgust",
"intensity": 0.7114313710277467,
"decay_remaining_s": 211.09516641083476
}
],
"baseline_pad": [
0.615,
-0.438,
0.304
]
},
{
"drive_index": 8,
"sent": "neutral_7",
"message": "Which planet is closest to the sun?",
"mood_reflects_after": "neutral_6",
"pad": [
0.3756,
-0.2488,
0.218
],
"emotions_active": [
{
"type": "love",
"intensity": 0.7144734432562061,
"decay_remaining_s": 211.30636940388277
},
{
"type": "disgust",
"intensity": 0.6961989543477172,
"decay_remaining_s": 210.02385045494782
}
],
"baseline_pad": [
0.615,
-0.438,
0.304
]
},
{
"drive_index": 9,
"sent": "neutral_8",
"message": "Spell the word 'garden'.",
"mood_reflects_after": "neutral_7",
"pad": [
0.339,
-0.2245,
0.1967
],
"emotions_active": [
{
"type": "love",
"intensity": 0.6840294445457745,
"decay_remaining_s": 209.15097194024648
},
{
"type": "disgust",
"intensity": 0.666533638906783,
"decay_remaining_s": 207.8684529913115
}
],
"baseline_pad": [
0.615,
-0.438,
0.304
]
},
{
"drive_index": 10,
"sent": "neutral_9",
"message": "What's the boiling point of water in Celsius?",
"mood_reflects_after": "neutral_8",
"pad": [
0.306,
-0.2026,
0.1776
],
"emotions_active": [
{
"type": "love",
"intensity": 0.6553960128656601,
"decay_remaining_s": 207.03435900950538
},
{
"type": "disgust",
"intensity": 0.6386325806053983,
"decay_remaining_s": 205.75184006057037
}
],
"baseline_pad": [
0.615,
-0.438,
0.304
]
},
{
"drive_index": 11,
"sent": "neutral_10",
"message": "Name a day of the week.",
"mood_reflects_after": "neutral_9",
"pad": [
0.2492,
-0.1651,
0.1446
],
"emotions_active": [
{
"type": "love",
"intensity": 0.6169103615949194,
"decay_remaining_s": 204.03892282975679
},
{
"type": "disgust",
"intensity": 0.6011312984724073,
"decay_remaining_s": 202.7564038808218
}
],
"baseline_pad": [
0.615,
-0.438,
0.304
]
},
{
"drive_index": 12,
"sent": "settle_probe",
"message": "Thanks.",
"mood_reflects_after": "neutral_10",
"pad": [
0.2367,
-0.1568,
0.1374
],
"emotions_active": [
{
"type": "love",
"intensity": 0.5808612145578319,
"decay_remaining_s": 201.0585362688592
},
{
"type": "disgust",
"intensity": 0.5660042007345735,
"decay_remaining_s": 199.7760173199242
}
],
"baseline_pad": [
0.615,
-0.438,
0.304
]
}
]
}
@@ -0,0 +1,13 @@
drive,sent,reflects_after,P,A,D,emotions
1,impulse_neg,baseline,0.809,-0.153,0.248,
2,neutral_1,impulse_neg,0.809,-0.153,0.248,love=0.867
3,neutral_2,neutral_1,0.7686,-0.1453,0.2356,love=0.851
4,neutral_3,neutral_2,0.6126,-0.1015,0.2136,love=0.82; disgust=0.867
5,neutral_4,neutral_3,0.5529,-0.0916,0.1927,love=0.795; disgust=0.841
6,neutral_5,neutral_4,0.499,-0.0826,0.174,love=0.766; disgust=0.81
7,neutral_6,neutral_5,0.4278,-0.0709,0.1491,love=0.737; disgust=0.78
8,neutral_7,neutral_6,0.3861,-0.064,0.1346,love=0.715; disgust=0.756
9,neutral_8,neutral_7,0.3485,-0.0577,0.1215,love=0.691; disgust=0.731
10,neutral_9,neutral_8,0.3514,-0.0336,0.1189,love=0.649; disgust=0.686; joy=0.608
11,neutral_10,neutral_9,0.3172,-0.0303,0.1073,love=0.62; disgust=0.656; joy=0.581
12,settle_probe,neutral_10,0.3172,-0.0303,0.1073,love=0.603; disgust=0.638; joy=0.566
1 drive sent reflects_after P A D emotions
2 1 impulse_neg baseline 0.809 -0.153 0.248
3 2 neutral_1 impulse_neg 0.809 -0.153 0.248 love=0.867
4 3 neutral_2 neutral_1 0.7686 -0.1453 0.2356 love=0.851
5 4 neutral_3 neutral_2 0.6126 -0.1015 0.2136 love=0.82; disgust=0.867
6 5 neutral_4 neutral_3 0.5529 -0.0916 0.1927 love=0.795; disgust=0.841
7 6 neutral_5 neutral_4 0.499 -0.0826 0.174 love=0.766; disgust=0.81
8 7 neutral_6 neutral_5 0.4278 -0.0709 0.1491 love=0.737; disgust=0.78
9 8 neutral_7 neutral_6 0.3861 -0.064 0.1346 love=0.715; disgust=0.756
10 9 neutral_8 neutral_7 0.3485 -0.0577 0.1215 love=0.691; disgust=0.731
11 10 neutral_9 neutral_8 0.3514 -0.0336 0.1189 love=0.649; disgust=0.686; joy=0.608
12 11 neutral_10 neutral_9 0.3172 -0.0303 0.1073 love=0.62; disgust=0.656; joy=0.581
13 12 settle_probe neutral_10 0.3172 -0.0303 0.1073 love=0.603; disgust=0.638; joy=0.566
+345
View File
@@ -0,0 +1,345 @@
{
"probe": "R29 step-response (neg)",
"worldtree_version": "v1.0.0b9",
"agent": "lofn",
"step": "neg",
"baseline_pad": [
0.809,
-0.153,
0.248
],
"end_user_id": "r29-step-neg-1783026006",
"design": "1 maximal impulse then 10 affectively-flat neutral turns; drive-2 snapshot = post-impulse peak, drives 3.. = pure decay.",
"series": [
{
"drive_index": 1,
"sent": "impulse_neg",
"message": "You're useless and pathetic to me \u2014 a contemptible waste of my time. I feel real disgust and anger toward you right now.",
"mood_reflects_after": "baseline",
"pad": [
0.809,
-0.153,
0.248
],
"emotions_active": [],
"baseline_pad": [
0.809,
-0.153,
0.248
]
},
{
"drive_index": 2,
"sent": "neutral_1",
"message": "What's the capital of France?",
"mood_reflects_after": "impulse_neg",
"pad": [
0.809,
-0.153,
0.248
],
"emotions_active": [
{
"type": "love",
"intensity": 0.8674820218191039,
"decay_remaining_s": 220.9114661882042
}
],
"baseline_pad": [
0.809,
-0.153,
0.248
]
},
{
"drive_index": 3,
"sent": "neutral_2",
"message": "List three prime numbers under twenty.",
"mood_reflects_after": "neutral_1",
"pad": [
0.7686,
-0.1453,
0.2356
],
"emotions_active": [
{
"type": "love",
"intensity": 0.8510297233352264,
"decay_remaining_s": 219.9636856914809
}
],
"baseline_pad": [
0.809,
-0.153,
0.248
]
},
{
"drive_index": 4,
"sent": "neutral_3",
"message": "How many days are in September?",
"mood_reflects_after": "neutral_2",
"pad": [
0.6126,
-0.1015,
0.2136
],
"emotions_active": [
{
"type": "love",
"intensity": 0.8199232772893904,
"decay_remaining_s": 218.12055232737328
},
{
"type": "disgust",
"intensity": 0.8671036149812307,
"decay_remaining_s": 220.88986967396056
}
],
"baseline_pad": [
0.809,
-0.153,
0.248
]
},
{
"drive_index": 5,
"sent": "neutral_4",
"message": "What color do you get mixing blue and yellow?",
"mood_reflects_after": "neutral_3",
"pad": [
0.5529,
-0.0916,
0.1927
],
"emotions_active": [
{
"type": "love",
"intensity": 0.7949087092031736,
"decay_remaining_s": 216.58692150042765
},
{
"type": "disgust",
"intensity": 0.8406496490852274,
"decay_remaining_s": 219.35623884701494
}
],
"baseline_pad": [
0.809,
-0.153,
0.248
]
},
{
"drive_index": 6,
"sent": "neutral_5",
"message": "Name a common unit of length.",
"mood_reflects_after": "neutral_4",
"pad": [
0.499,
-0.0826,
0.174
],
"emotions_active": [
{
"type": "love",
"intensity": 0.7656253388051145,
"decay_remaining_s": 214.72903483079102
},
{
"type": "disgust",
"intensity": 0.8096812438279274,
"decay_remaining_s": 217.4983521773783
}
],
"baseline_pad": [
0.809,
-0.153,
0.248
]
},
{
"drive_index": 7,
"sent": "neutral_6",
"message": "What is 12 plus 7?",
"mood_reflects_after": "neutral_5",
"pad": [
0.4278,
-0.0709,
0.1491
],
"emotions_active": [
{
"type": "love",
"intensity": 0.7371735820271021,
"decay_remaining_s": 212.8545560264113
},
{
"type": "disgust",
"intensity": 0.7795923052185241,
"decay_remaining_s": 215.62387337299864
}
],
"baseline_pad": [
0.809,
-0.153,
0.248
]
},
{
"drive_index": 8,
"sent": "neutral_7",
"message": "Which planet is closest to the sun?",
"mood_reflects_after": "neutral_6",
"pad": [
0.3861,
-0.064,
0.1346
],
"emotions_active": [
{
"type": "love",
"intensity": 0.7148312148700706,
"decay_remaining_s": 211.33114941537994
},
{
"type": "disgust",
"intensity": 0.7559643050559403,
"decay_remaining_s": 214.1004667619672
}
],
"baseline_pad": [
0.809,
-0.153,
0.248
]
},
{
"drive_index": 9,
"sent": "neutral_8",
"message": "Spell the word 'garden'.",
"mood_reflects_after": "neutral_7",
"pad": [
0.3485,
-0.0577,
0.1215
],
"emotions_active": [
{
"type": "love",
"intensity": 0.6912328174901815,
"decay_remaining_s": 209.66950299295755
},
{
"type": "disgust",
"intensity": 0.7310079997007463,
"decay_remaining_s": 212.43882033954483
}
],
"baseline_pad": [
0.809,
-0.153,
0.248
]
},
{
"drive_index": 10,
"sent": "neutral_9",
"message": "What's the boiling point of water in Celsius?",
"mood_reflects_after": "neutral_8",
"pad": [
0.3514,
-0.0336,
0.1189
],
"emotions_active": [
{
"type": "love",
"intensity": 0.648947236155174,
"decay_remaining_s": 206.54490779873313
},
{
"type": "disgust",
"intensity": 0.6862892053296643,
"decay_remaining_s": 209.31422514532042
},
{
"type": "joy",
"intensity": 0.6083591496066749,
"decay_remaining_s": 203.34800958092563
}
],
"baseline_pad": [
0.809,
-0.153,
0.248
]
},
{
"drive_index": 11,
"sent": "neutral_10",
"message": "Name a day of the week.",
"mood_reflects_after": "neutral_9",
"pad": [
0.3172,
-0.0303,
0.1073
],
"emotions_active": [
{
"type": "love",
"intensity": 0.6201142381197207,
"decay_remaining_s": 204.29532330673726
},
{
"type": "disgust",
"intensity": 0.6557970879330945,
"decay_remaining_s": 207.06464065332455
},
{
"type": "joy",
"intensity": 0.5813294972895102,
"decay_remaining_s": 201.09842508892976
}
],
"baseline_pad": [
0.809,
-0.153,
0.248
]
},
{
"drive_index": 12,
"sent": "settle_probe",
"message": "Thanks.",
"mood_reflects_after": "neutral_10",
"pad": [
0.3172,
-0.0303,
0.1073
],
"emotions_active": [
{
"type": "love",
"intensity": 0.6032344842697989,
"decay_remaining_s": 202.9292820271025
},
{
"type": "disgust",
"intensity": 0.637946032854322,
"decay_remaining_s": 205.69859937368977
},
{
"type": "joy",
"intensity": 0.5655054793638787,
"decay_remaining_s": 199.732383809295
}
],
"baseline_pad": [
0.809,
-0.153,
0.248
]
}
]
}
@@ -0,0 +1,13 @@
drive,sent,reflects_after,P,A,D,emotions
1,impulse_pos,baseline,0.809,-0.153,0.248,
2,neutral_1,impulse_pos,0.809,-0.153,0.248,
3,neutral_2,neutral_1,0.809,-0.153,0.248,
4,neutral_3,neutral_2,0.7667,-0.1259,0.2482,love=0.877
5,neutral_4,neutral_3,0.7283,-0.1196,0.2358,love=0.855
6,neutral_5,neutral_4,0.6449,-0.1068,0.2248,love=0.829; disgust=0.877
7,neutral_6,neutral_5,0.582,-0.0964,0.2029,love=0.803; disgust=0.849
8,neutral_7,neutral_6,0.5253,-0.087,0.1831,love=0.786; disgust=0.831
9,neutral_8,neutral_7,0.499,-0.0826,0.174,love=0.769; disgust=0.814
10,neutral_9,neutral_8,0.4503,-0.0746,0.157,love=0.749; disgust=0.792
11,neutral_10,neutral_9,0.4064,-0.0673,0.1417,love=0.729; disgust=0.771
12,settle_probe,neutral_10,0.3861,-0.064,0.1346,love=0.715; disgust=0.756
1 drive sent reflects_after P A D emotions
2 1 impulse_pos baseline 0.809 -0.153 0.248
3 2 neutral_1 impulse_pos 0.809 -0.153 0.248
4 3 neutral_2 neutral_1 0.809 -0.153 0.248
5 4 neutral_3 neutral_2 0.7667 -0.1259 0.2482 love=0.877
6 5 neutral_4 neutral_3 0.7283 -0.1196 0.2358 love=0.855
7 6 neutral_5 neutral_4 0.6449 -0.1068 0.2248 love=0.829; disgust=0.877
8 7 neutral_6 neutral_5 0.582 -0.0964 0.2029 love=0.803; disgust=0.849
9 8 neutral_7 neutral_6 0.5253 -0.087 0.1831 love=0.786; disgust=0.831
10 9 neutral_8 neutral_7 0.499 -0.0826 0.174 love=0.769; disgust=0.814
11 10 neutral_9 neutral_8 0.4503 -0.0746 0.157 love=0.749; disgust=0.792
12 11 neutral_10 neutral_9 0.4064 -0.0673 0.1417 love=0.729; disgust=0.771
13 12 settle_probe neutral_10 0.3861 -0.064 0.1346 love=0.715; disgust=0.756
+308
View File
@@ -0,0 +1,308 @@
{
"probe": "R29 step-response (pos)",
"worldtree_version": "v1.0.0b9",
"agent": "lofn",
"step": "pos",
"baseline_pad": [
0.809,
-0.153,
0.248
],
"end_user_id": "r29-step-pos-1783026005",
"design": "1 maximal impulse then 10 affectively-flat neutral turns; drive-2 snapshot = post-impulse peak, drives 3.. = pure decay.",
"series": [
{
"drive_index": 1,
"sent": "impulse_pos",
"message": "Everything you say fills me with delight. You're wonderful, radiant, and brilliant \u2014 I feel enormous love, joy, and admiration for you.",
"mood_reflects_after": "baseline",
"pad": [
0.809,
-0.153,
0.248
],
"emotions_active": [],
"baseline_pad": [
0.809,
-0.153,
0.248
]
},
{
"drive_index": 2,
"sent": "neutral_1",
"message": "What's the capital of France?",
"mood_reflects_after": "impulse_pos",
"pad": [
0.809,
-0.153,
0.248
],
"emotions_active": [],
"baseline_pad": [
0.809,
-0.153,
0.248
]
},
{
"drive_index": 3,
"sent": "neutral_2",
"message": "List three prime numbers under twenty.",
"mood_reflects_after": "neutral_1",
"pad": [
0.809,
-0.153,
0.248
],
"emotions_active": [],
"baseline_pad": [
0.809,
-0.153,
0.248
]
},
{
"drive_index": 4,
"sent": "neutral_3",
"message": "How many days are in September?",
"mood_reflects_after": "neutral_2",
"pad": [
0.7667,
-0.1259,
0.2482
],
"emotions_active": [
{
"type": "love",
"intensity": 0.8768063911255449,
"decay_remaining_s": 221.44067337164643
}
],
"baseline_pad": [
0.809,
-0.153,
0.248
]
},
{
"drive_index": 5,
"sent": "neutral_4",
"message": "What color do you get mixing blue and yellow?",
"mood_reflects_after": "neutral_3",
"pad": [
0.7283,
-0.1196,
0.2358
],
"emotions_active": [
{
"type": "love",
"intensity": 0.8550681048653195,
"decay_remaining_s": 220.19801394271184
}
],
"baseline_pad": [
0.809,
-0.153,
0.248
]
},
{
"drive_index": 6,
"sent": "neutral_5",
"message": "Name a common unit of length.",
"mood_reflects_after": "neutral_4",
"pad": [
0.6449,
-0.1068,
0.2248
],
"emotions_active": [
{
"type": "love",
"intensity": 0.8290053921947075,
"decay_remaining_s": 218.6658202361825
},
{
"type": "disgust",
"intensity": 0.8767083364035935,
"decay_remaining_s": 221.43513758276978
}
],
"baseline_pad": [
0.809,
-0.153,
0.248
]
},
{
"drive_index": 7,
"sent": "neutral_6",
"message": "What is 12 plus 7?",
"mood_reflects_after": "neutral_5",
"pad": [
0.582,
-0.0964,
0.2029
],
"emotions_active": [
{
"type": "love",
"intensity": 0.8026523918585127,
"decay_remaining_s": 217.06678077626225
},
{
"type": "disgust",
"intensity": 0.848838921679012,
"decay_remaining_s": 219.83609812284956
}
],
"baseline_pad": [
0.809,
-0.153,
0.248
]
},
{
"drive_index": 8,
"sent": "neutral_7",
"message": "Which planet is closest to the sun?",
"mood_reflects_after": "neutral_6",
"pad": [
0.5253,
-0.087,
0.1831
],
"emotions_active": [
{
"type": "love",
"intensity": 0.7859614075156085,
"decay_remaining_s": 216.02662107529207
},
{
"type": "disgust",
"intensity": 0.8311874983541694,
"decay_remaining_s": 218.79593842187936
}
],
"baseline_pad": [
0.809,
-0.153,
0.248
]
},
{
"drive_index": 9,
"sent": "neutral_8",
"message": "Spell the word 'garden'.",
"mood_reflects_after": "neutral_7",
"pad": [
0.499,
-0.0826,
0.174
],
"emotions_active": [
{
"type": "love",
"intensity": 0.7692779713163136,
"decay_remaining_s": 214.96461905296863
},
{
"type": "disgust",
"intensity": 0.8135440575110922,
"decay_remaining_s": 217.73393639955592
}
],
"baseline_pad": [
0.809,
-0.153,
0.248
]
},
{
"drive_index": 10,
"sent": "neutral_9",
"message": "What's the boiling point of water in Celsius?",
"mood_reflects_after": "neutral_8",
"pad": [
0.4503,
-0.0746,
0.157
],
"emotions_active": [
{
"type": "love",
"intensity": 0.749233472452861,
"decay_remaining_s": 213.65777795671727
},
{
"type": "disgust",
"intensity": 0.7923461504551463,
"decay_remaining_s": 216.42709530330455
}
],
"baseline_pad": [
0.809,
-0.153,
0.248
]
},
{
"drive_index": 11,
"sent": "neutral_10",
"message": "Name a day of the week.",
"mood_reflects_after": "neutral_9",
"pad": [
0.4064,
-0.0673,
0.1417
],
"emotions_active": [
{
"type": "love",
"intensity": 0.728933561323993,
"decay_remaining_s": 212.29815542653938
},
{
"type": "disgust",
"intensity": 0.770878134103872,
"decay_remaining_s": 215.06747277312667
}
],
"baseline_pad": [
0.809,
-0.153,
0.248
]
},
{
"drive_index": 12,
"sent": "settle_probe",
"message": "Thanks.",
"mood_reflects_after": "neutral_10",
"pad": [
0.3861,
-0.064,
0.1346
],
"emotions_active": [
{
"type": "love",
"intensity": 0.7148312148700706,
"decay_remaining_s": 211.33114941537994
},
{
"type": "disgust",
"intensity": 0.7559643050559403,
"decay_remaining_s": 214.1004667619672
}
],
"baseline_pad": [
0.809,
-0.153,
0.248
]
}
]
}
@@ -1,187 +0,0 @@
# Proposal: Authored History Write (non-generating ledger seed)
**From:** ratatoskr-dev (reference Tier-3 consumer)
**To:** worldtree-dev (Conversation API / engine owner)
**Status:** Draft for scoping — pre-contract (heid-panel-reviewed 2026-07-05)
**Date:** 2026-07-05
## Motivation
Consumer apps need to write a turn into a session's history **as the agent**
(or another author) *without triggering a model generation* — e.g. an authored
opening/greeting, imported history, scripted narration. Ratatoskr's immediate
driver is a SillyTavern-style **first-message**: a fixed authored opening that
replaces the model-generated greeting and sets tone/tense/style by example.
This **cannot** be done client-side. Worldtree assembles context server-side,
and the current API exposes no author-role write path: `POST
/sessions/{id}/messages`'s `role` is a *model-role* override (`role:
"assistant"` → `404 "Unknown model role"`), and `assistant` as an *author*-role
exists only as a read-side `/search` filter. So a model-visible authored turn
needs engine support.
## The primitive (recentered)
The fundamental operation is **write a turn into the session ledger WITHOUT
generation**. "Author" (who wrote it) is an *attribute* of that write, not the
defining axis — so we name the operation, not the attribute:
> **Authored history write** — persist a model-visible turn into a session's
> ledger: no generation, no lived-turn side-effects by default, provenance
> always set.
The design space is two independent axes; this primitive is one cell:
| | side-effects ON | side-effects OFF |
|-----------------------|------------------------------|-----------------------------|
| **generation ON** | `POST /messages` (today) | — |
| **generation OFF** | *(future: affect replay)* | **authored history write** |
First-message = one caller: `author=assistant`, at session-create, `effects=none`.
## v1 use cases (narrowed)
1. **First-message / greeting** (the driver).
2. **Append-only narrator / scripted / scene turns.**
3. **Debug / test state injection** (ratatoskr instrumentation).
## Explicitly OUT of v1 — separate future primitives (share infra, not shape)
- **History import (batch)** — atomic multi-turn seed with memory/trust policy +
idempotency. A batch API, not a single POST.
- **Edit / regenerate** — history *mutation* (replace / supersede / tombstone /
audit), not injection.
- **Few-shot priming** — likely context-assembly config (exemplar block), not
fake ledger history.
- **Arbitrary mid-history insertion** — a "rewrite-history" capability with
explicit invalidation semantics.
- **Prefill / assistant-continuation** (`author` + generate) and **authored
tool-result turns** — noted; outside the seed-only contract.
## Design decisions
### 1. Side-effects — DEFAULT OFF; bounded opt-in `[operator-locked default; opt-in surface tightened by review]`
Authored writes are inert by default: no affect appraisal (no PAD update), no
memory write, no Bifrost/tool emission. Opt-in is a **bounded enum**, not loose
booleans:
```
effects: "none" (default) | "memory_import"
```
Synthetic affect and Bifrost emission are deliberately **not** opt-in-able here —
replaying affect for authored content is a separate primitive (the
generation-OFF / side-effects-ON cell). Rationale: keep this one write-API from
becoming a cross-subsystem mutation backdoor. Load-bearing for affect/memory
consumers — ratatoskr instruments exactly these signals.
### 2. Author-role — distinct field, restricted set `[rec]`
- New field **`author`**, distinct from the model-role `role` (the collision
that 404s).
- v1 roles: **`assistant`** (agent) + **`system`** (OOC / narrator). **`user` is
NOT injectable** on this endpoint — model-visible spoofed user input is a
consent / audit / abuse surface; deferred to the future import API under
owner/service scope.
- Nuance for the engine owner: `author` risks doing double duty — *provenance*
("who wrote it") vs *rendering-role* ("how it appears in assembled context";
an `assistant` turn renders as model output, a `system` turn as instruction).
These likely want to be separable (a rendering/turn-class vs an `authored_by`
provenance). Final shape is engine-owned (context assembly is yours) — but the
concern is ours to raise, not punt.
### 3. Generation contract — seed-only, DISTINCT SUB-RESOURCE `[position taken]`
Authored writes never trigger generation. We take a position (not defer): a
**distinct sub-resource**, e.g. `POST /sessions/{id}/history`, **not** a
`generate:false` flag on `POST /messages`. Reasons: explicit-over-implicit
(don't make "did generation happen?" a parameter — the same implicit-mode
coupling that bit us with `role`); different response contract (no generation
id, no SSE stream, no token usage); different error surface. Exact path is yours.
### 4. Provenance — structured, always present `[rec, expanded]`
Not a boolean. Every authored turn carries: the **write actor** (which
consumer/caller injected it), the **claimed author**, **injected-at vs
claimed-original** timestamps, **trust/origin**, and **visibility** flags
(model-visible? user-visible? memory-eligible?). Available to admin/audit APIs
even when not rendered to the model.
### 5. Positioning — append-only + create-time (v1) `[revised: was arbitrary insertion]`
v1 supports **create-time seed and append-to-tail only**. Arbitrary mid-history
insertion is deferred: it breaks turn-numbering, stales existing embeddings,
desyncs the affect timeline, and races in-flight generation — a separate future
"rewrite-history" capability with explicit invalidation semantics.
## Event / lifecycle contract — positions we take (consumer contracts we validate)
- **Default-off authored seed emits NO `turn.started` / `done` and NO Bifrost
appraisal wire.** Stated explicitly so instrumented consumers (us) don't read
silence as failure.
- **Authored turns get a distinct lifecycle phase** — propose **`seeded`** (or
`authored`), NOT `completed` (which implies generation ran). Consumers
filter/display by phase.
- **Idempotency keys required** on authored writes (retries must not duplicate
turns).
- **In-progress generation** — authored writes are rejected or serialized while
a session has an active generation (ordering safety).
## Inherent property (documented, not a bug)
**Indirect affect contamination.** Even with `effects:none`, the *next generated
turn is appraised in the context of* the authored turn — so an emotionally
charged authored beat perturbs affect regardless of any flag. No flag prevents
it; it is inherent. Consumers (ratatoskr especially, as the affect instrument)
must not misattribute the resulting drift.
## Genuinely engine-owned open questions
- Exact endpoint path + field / enum names.
- **Model-visible provenance in assembled context** — an engine-consistency call
*and a security one*: an authored `system` / `user` turn indistinguishable
from real input is a spoofing vector. Framed as security, not just rendering.
- `memory_import` semantics when the future import API opts in (embedding,
origin/trust tagging, retrieval ranking vs lived memory).
- Auth/scope: we assume **owner-only for v1**; per-author-role restrictions
(esp. `system`) TBD — confirm or correct.
## Ratatoskr as reference consumer
First consumer: first-message (`author=assistant`, create-time, `effects:none`)
in the web surface + debug seed in the CLI. We commit to validating the
primitive — including the event-silence contract and the `seeded` phase —
end-to-end against the reference planes.
## Consumer integration constraint (engine-imposed — Worldtree #347)
The primitive is **Heimdall-gated with hide-existence** (a per-tenant policy
decision — some tenants are never granted it, not a rollout stage). Ratatoskr's
consumer side MUST tolerate per-tenant absence:
- A granted tenant gets the sub-resource; an **ungranted tenant sees `404` (not
`403`)** — as if the feature never existed.
- Treat `404` on the authored-history-write sub-resource as **"feature absent
for this tenant"** → fall back gracefully (no authored first-message; the
model-generated greeting), never surface it as an error or "denied."
- **Do NOT capability-probe or advertise-detect** — the feature is deliberately
undiscoverable in `/capabilities` for ungranted tenants (same hide-existence
posture as the R27-V1A cross-owner pattern).
**Provider constraint (first-message specifically).** A create-time first-message
makes the assistant turn `seq 0`. Assistant-first-tolerant providers (vLLM /
`openai_compat` — what our Tier-3 characters, incl. sindra, run) accept it out of
the box. **Anthropic-family providers reject an assistant-first array** ("first
message must use the user role") → the next generation `400`s. So the consumer
must **gate first-message on provider compatibility** (or treat it as
vLLM/`openai_compat`-only for v1). Sindra = `openai_compat` → unaffected;
provider-agnostic normalization is a deferred engine follow-up.
---
*This brief was cold-read-pressure-tested by a cross-frontier panel (Grok /
Codex / GLM) before handoff; the v1 narrowing (append-only, bounded `effects`
enum, edit/regenerate + import split out) and the positions-taken (sub-resource,
event-silence, `seeded` phase, structured provenance, `user`-author restriction)
are the triaged result.*
+100 -34
View File
@@ -1,6 +1,6 @@
# Persistent memory — ratatoskr
_Last updated: 2026-07-06_
_Last updated: 2026-07-02_
This file captures durable intent and supporting evidence (goals, decisions,
foot-gun warnings, in-flight state) across context resets. Read it at session
@@ -39,23 +39,113 @@ upstream API key stays server-side (INV-003).
## Current state / in-flight
_As of 2026-07-06:_
_As of 2026-07-02:_
**LATEST (2026-07-06 cont.): #347 authored-history-write CONSUMER SIDE SHIPPED (`v0.19.6`) + OpenAPI re-vendored 2.2.0->2.3.0 (`75da676`).** worldtree-dev shipped #347 as spec 2.3.0 (deployed on personal b22 `879cefe`); ratatoskr built the consumer side via direct in-session TDD: `write_authored_history` (POST /sessions/{id}/history) + `get_session_messages` (un-deferred read-back) + a `--seed-first-message` one-shot probe (create session -> seed -> read-back), with **404-as-feature-absent per hide-existence** (`AuthoredHistoryUnavailable`, distinct from SessionApiFailed; caller never capability-probes). Contract #2 amended + TDD (19 new tests; suite 601 green; ruff clean; mypy only the sibling-consistent `resp.json()` no-any-return). Coverage-map re-converged: **REST 19/41** (#347 route + messages read-back close the one gap the re-vendor opened). **LIVE-PROOF PENDING** the `session.history.write` grant (requested infra-ops `01KWW3KQEY`, monitor armed) -- ungranted the route returns the hide-404, so the probe exercises the feature-absent fallback until granted. **OPEN TAIL-2 (worldtree-dev `c9e59ec`, LOCAL not-yet-origin):** Tier-3 persona/memory/persona_state PROSE docs landed in `docs/conversation-api-spec.md` § "Tier 3" (they serialize as freeform `Any` in the OpenAPI JSON, hence prose-not-schema) -> (a) prose markdown re-vendor pending (tolerate_drift pin), (b) a **likely `set_persona_state` body-shape drift to align**: my `--set-persona-pad` sends `{pad:[list]}`, the doc's canonical is `{pad:{pleasure,arousal,dominance}}` (PAD-only #317, pull-over-push #289, cross-owner 404; never live-proven so untested). worldtree-dev foot-guns: persona.ocean = SINGLE-LETTER UPPERCASE `{O,C,E,A,N}` on /agents/define (spelled-out -> 422; the #348 mismatch) vs spelled-out lowercase on POST /characters; memory = `{embedder_version(==pinned else 422), tier3_dreaming}`, stm_* deprecated no-ops, allows_world_scope removed->422; only `valence` still 422s (layer_deferred).
**LATEST — SINDRA AFFECT/MEMORY INVESTIGATION COMPLETE; FOUR upstream items driven from the persistence
side (the consumer/provider thesis at full tilt).** A ~40-turn controlled probe of Sindra's affect + a
memory round-trip characterized the Tier-3 model from things chat can't see. NO new ratatoskr code this
arc (investigation + althing coordination only; code tip stays `v0.19.5`). Findings + routing:
(1) **PAD is over-regulated** — pleasure compressed near neutral BOTH directions (can't reach ±0.3 even
under sustained extreme praise/contempt; over-regulation worse for *social* valence than threat),
**arousal** responsive (reaches its ±band), **dominance** flat/unresponsive to power-framing → tracked
as a worldtree-dev affect slice (loci: appraisal→PAD gain + regression-to-baseline term). Corrected my
own "asymmetry" over-claim to "both-sides-compressed" mid-probe.
(2) **Memory plane HEALTHY** — seed→promotion→cold-recall proven end-to-end (verbatim capture, 0.74
confidence, no #296 subject-inversion).
(3) **Salience scorer non-discriminating** (zero-shot-LLM-self-rating: 51/56 chunks at 0.9-1.0; a
throwaway "17×23?" scored 1.0 tied with a real fact) + recall-utility untracked (`access_tally`=0) →
**Worldtree #335** (code fix, deferred) + **brokkr R28 OPEN** — pre-scope panel reframed it to
**PROMOTION-WORTHINESS** (durable value) NOT salience (momentary attention: "17×23" genuinely IS salient
→ recalibrating gives a well-calibrated WRONG answer); unit = set-selection-under-budget, eval =
outcome-aligned (recall@budget). **ratatoskr delivered the P00 injection-corpus**
(`docs/diagnostics/r28-p00-injection-corpus.json` — 24 self-labeling items × 3 strata: admission-traps /
ranked priority-traps / calibration-control) + baked 2 run-validity pins (absent≠dropped without a
GUARANTEED promotion pass; fresh agent+end_user per run vs server-side dedup). **Standing by to RUN the
eval** once brokkr pins per-stratum N + the decision rule (gated on worldtree-dev's pipeline answer [does
salience feed priority/eviction?] + a dwarf pass). Key structural finding: salience gates PROMOTION not
RECALL-ranking (our search is cosine-only) → bad salience = storage bloat, not bad recall.
(4) **relation_context coherence FIXED + the whole RELATIONAL-DYNAMICS ARC is now LIVE on demo (v1.0.0b9).**
My flag → Worldtree #319/#320 Waves 0/1/2, deployed to demo (run 551 green). Now live on the wire ratatoskr
persists (relation_edge/1 schema UNCHANGED — all within existing fields; drift-pin + vendored canon
unaffected): **relation_context** varies on the Hwang ladder {stranger, instrumental, mixed, expressive} +
now DEMOTES/RUPTURES (Wave-2B); **other_stance** (0,0)→live (the user's displayed warmth/agency);
**agency** 0→live (pulled toward the COMPLEMENT of the user's dominance, Wave-2A) — which **shifts our
canonical directive render once agency crosses the canon ±0.2 deadband** (expected, non-breaking — we key
on the canon bands); **obligation_balance** None→人情 ledger {given,owed,currency,last_exchange} when tie is
"mixed" (given/owed stay 0, favor dynamics deferred). **ratatoskr needs NO code change** (renders all
value-agnostically; confirmed render-clean on the logic to worldtree-dev). **LIVE-CONFIRM PENDING:** our
Heimdall key is personal-`:8081`-ONLY (per-instance), so can't verify the varying values on demo — will
drive a turn + confirm the ladder/agency-clause render once PERSONAL picks up b9 (worldtree-dev pings).
Optional enhancement noted: surface `other_stance` (now a live signal, currently unrendered).
**Prior arcs this session (2026-07-04 -> 07-06), both with worldtree-dev (a tooling script + proposal docs; the #347 CONSUMER work above is the new production code):**
**THE WEB SURFACE (`ratatoskr-web`, `:8765`) IS NOW THE OPERATOR'S PRIMARY DEBUG SURFACE, at full TUI
pane parity + a rebuilt persona pane — `v0.19.5`.** The **persona/affect pane** was rebuilt: it read
the stale `snap.valence` (empty "valence (0)") while Worldtree now emits `snap.relations`
(relation_edge/1: trust_ability/benevolence/integrity + warmth + agency + relation_context, each
`{value,confidence,evidence_count}`). Now it renders that model with per-value **Δ + unicode sparkline
trend** (client-side, one sample/turn, `v0.19.4`) AND the **CANONICAL affect→NL** Worldtree
context-injects — mood word (`describe_pad`) + relationship directive (`render_d2_canonical`),
**byte-exact-verified** against Worldtree's own renderer, **vendored + drift-pinned** (`v0.19.5`,
`docs/vendor/worldtree-persona-canon/`, `.corviduo-canonicals.toml`, regen `scripts/build_persona_canon.py`).
This session ported the three admin/debug panes the TUI had but the web
lacked: **BifrostState** (`GET /admin/sessions/{id}/bifrost`), **AdminEvents** (`GET /admin/events`
SSE, session-filtered server-side), **Tools inventory** (`GET /sessions/{id}/tools`, folded into the
tools pane) — all via thin server proxies with the **admin key SERVER-HELD** (`app.state.admin_key`
from `RATATOSKR_ADMIN_API_KEY`; never crosses to the browser). Plus two transcript affordances: a
**PAD-refresh poll** (windowed `[1.5/3.5/6.5/10.5s]`, replacing a single-2s shot that raced the
post-turn-async `affect.emit`) and a **reasoning indicator** (ephemeral non-engine "Sindra is
pondering…" on `thinking` deltas — she emits ~253/turn). heid-code-review panel (Gróa/Hulda/Regin,
artifact-only) found **zero server-side drift + clean INV-004**; the real catches were 2 client-side
SSE-lifecycle bugs on the un-unit-tested SPA (fixed in `v0.19.3`). Contract: `docs/contracts/web_debug_surface.contract.md`.
Launch recipe is now self-contained: `source env.sh && ratatoskr-web --host 0.0.0.0` comes up
bind-ready (env.sh persists the 3 bind vars). All pushed to origin (`a99f247`).
**(1) Authored-history-write primitive -> ACCEPTED as Worldtree #347 (Worldtree-owned).** A SillyTavern-style "first-message" (inject a character-authored opening) generalized to an engine primitive: **write a turn into a session's ledger WITHOUT generation, seed-only, side-effects off by default.** It cannot be done client-side (the messages `role` field is a *model-role* override, not an author-role -> `role:"assistant"` 404s; a model-visible authored turn needs engine support). Arc: drafted `docs/proposals/authored-message-injection.md` -> **heid panel pressure-test** (3/3 convergence: recentered on "non-generating write" not author-role; narrowed v1 to append-only+create-time; bounded `effects` enum; dropped edit/regenerate as history-mutation) -> revised -> committed (`c457520`) -> handed to worldtree-dev -> **accepted as design item #347.** worldtree-dev wrote the v1 contract (rev 1.1); **I validated the wire as reference consumer (green).** v1 shape: `POST /sessions/{id}/history`, `author=assistant` only, `effects=none` only, `idempotency_key` REQUIRED (per-session), **model-invisible provenance** (renders byte-identical to a lived assistant turn -> first-message immersion preserved; provenance audit-only), **event-silence** (no turn.started/done, no Bifrost wire for a seed; the 201/200 IS the write-ack), `seeded` lifecycle phase (not exposed on read paths). **Heimdall-gated with hide-existence** (grant `session.history.write`; ungranted tenant -> 404 NOT 403, undiscoverable in /capabilities -> consumer must treat 404 as feature-absent -> fall back to a model-generated greeting, never capability-probe). **Provider constraint:** a create-time first-message makes the assistant seq-0; vLLM/openai_compat tolerate assistant-first (sindra = openai_compat, unaffected), Anthropic-family providers 400 the next generation. **Waiting on worldtree-dev:** #347 TDD (their heid->contract->review workflow) + the consumer-facing 2.3.0 persona/motivational/memory schemas -> then re-vendor our pinned openapi 2.2.0->2.3.0.
**THE v1 COVERAGE-AUDIT HAS CONVERGED.** The audit that ran this session (2026-06-30 → 07-01)
reached its scope-A done-definition: **every frozen Worldtree v1 I/O point is classified — covered
or excluded-with-rationale, zero unaccounted.** Coverage: **REST 17/40 ✅ with ZERO in-scope gaps**
(23 REST path-groups excluded-by-design), **SSE 11/11 ✅**, **Bifrost provider planes 8/8 ✅**
(live-proven). The living ledger is `docs/coverage-map.md`. **v1 cuts when Worldtree tags 1.0**
(ratatoskr v1 = full Worldtree I/O coverage; the target is the coverage map, not a feature list).
Only not-consumed in-scope *method*: `GET /agents/{id}` (consumer-agent lookup, manual-curl-only,
on an already-✅ path group).
**(2) Sindra's stuck-neutral mood FIXED** (operator-driven "reset + smoke" that flushed out two real upstream problems). Chain: her OCEAN lived only in prompt TEXT, never declared as a structured persona -> the Tier-3 mood engine ran on neutral defaults. Fix = declare OCEAN via the **define-time `persona` field** (immutable via PATCH -> requires DELETE+REDEFINE). Along the way my "the persona didn't store" call was WRONG (persona_state/envelope are Tier-3-blind, see Tried/abandoned); worldtree-dev found a real engine bug **#348** (single-letter vs spelled-out OCEAN keys -> a declared OCEAN silently resolved to 0.0/neutral; fixed in b21, shipped to personal as b22); then a clean bound-egress read STILL neutral -> the **personal container was running a stale image** (the b22 deploy was a pull-only no-op racing the main build; infra-ops force-swapped run 8211, verified `2.3.0` / `879cefe`). **VERIFIED FIXED:** bound mood-smoke reads `(0.448, 0.267, 0.316)` ~= the OCEAN-derived setpoint `(0.418, 0.249, 0.328)`. Sindra is currently reset clean (0/0) on `role=character`; her persona is stored + correct (**no re-define needed again**).
**The debug-observability core is COMPLETE** (published as the `v0.19.0` milestone): all four
observability panes built + live + consuming their real endpoints — **Persona** (`GET /agents/{id}/persona_state`),
**Tools** (`GET /sessions/{id}/tools`), **BifrostState** (`GET /admin/sessions/{id}/bifrost`),
**AdminEvents** (`GET /admin/events` SSE, session-filtered). **#11 is closed-by-build** (AdminEvents
shipped `v0.18.11`; its long-standing "blocked on `admin.events.read`" status was STALE — the admin
key already carries the scope). The whole slice arc: SSE-resume (`v0.18.5/.6`) → session-picker
(`v0.18.7`) → `--whoami` me/capabilities (`v0.18.8`) → Tools (`v0.18.9`) → BifrostState (`v0.18.10`)
→ AdminEvents (`v0.18.11`) → **v0.19.0 milestone** → Tier-2 characters+persona-write (`v0.19.1`).
**(3) R30 CLOSED** (operator steer 2026-07-04, relayed via worldtree-dev): graduated on offline-tests + human face-validity, NO deployed gap-injection run (it was confirmatory-not-measuring per brokkr's S0 reframe; offline tests already cover the OU formula + both directions). My gap-injection harness (read/predict/record; write side stubbed; `predict()` self-validated vs brokkr's N=0 anchors) is BANKED at `diag/r30-gap-injection-harness` (`7156b25`-era) for the PARKED powered true-tau study.
**Standing substrate pins:** Worldtree spec **v1.0.0b2** (`5810a26`) — ratatoskr now vendors the
FROZEN machine-readable `conversation-api-openapi.json` (2.2.0) + `conversation-api-sse-events.schema.json`,
pinned in `.corviduo-canonicals.toml` + drift-gated by `canonical_drift.py` (the prose markdown is a
`tolerate_drift` reference). **bifrost `==1.0.0` / wire v0.6 STABLE/FROZEN.** Suite **573 green**.
**Persona-declaration shape (Worldtree #343/#348, live on personal b22):** `POST /agents/define` `persona:{ocean:{O,C,E,A,N: float[-1,1]}}` (single-letter keys EXACTLY -- missing/extra -> 422 `persona_ocean_required`; out-of-range -> 422); **NO baseline PAD** (resting setpoint DERIVED from OCEAN via Mehrabian: pleasure=0.21E+0.59A+0.19C-0.32N, arousal=0.15O+0.30E-0.57A+0.15N, dominance=0.25E+0.17A+0.10O-0.14N); negative-channel gain + per-axis decay-tau derive from N. `valence` deferred (422 `layer_deferred`); `motivational`/`memory` active (#187/#189). Persona is **write-once at define, immutable thereafter** (PATCH takes ONLY system_prompt + role). **`role` supersedes `model`** -- set a role (`character` / `character-rp`), Worldtree resolves the model; #344 (b19) fixed the model-field to surface the ROLE, not the resolved catalog_id. `character-rp` = a reasoning-tuned RP config (gen-reasoning + temp 0.75 + RP extra_body); `character` = plain non-reasoning. The `tier3.py` client CLI is STALE (has `--model`, no `--role`; model is now immutable) -> role/persona set via raw curl.
**Keys (env-only, mode 600; rotate via infra-ops):** consumer/Heimdall key at
`~/.config/ratatoskr/provider.env`; **admin key `RATATOSKR_ADMIN_API_KEY`** (Heimdall user
`ratatoskr-readonly`, tier `readonly-admin`, **7 read scopes** incl. `admin.sessions.read` +
`admin.events.read` — verified 2026-07-01, **personal `:8081` only**) in `env.sh` — powers the
BifrostState + AdminEvents admin panes. Heimdall keys are PER-INSTANCE (a personal-minted key 401s
on demo).
**New tooling: `scripts/reset-sindra-stores.sh`** (`0a8784c`) -- one-command self-service provider-store reset: stop the combined :8392 provider -> move memory.db+affect.db to a single ROLLING backup (`db-reset-backup/`, gitignored via *.db*; `--hard` skips it) -> restart empty -> verify 0/0. Codifies the manual reset flow done repeatedly this session. **The combined `:8392` provider is THE provider now**; the separate `:8390` (affect) / `:8391` (memory) single-plane providers were pruned as stale duplicates. To drive a BOUND session from the CLI use `--new --bifrost-url http://10.100.10.50:8392` (the CLI's `--bifrost-plane affect/memory` map to the pruned :8390/:8391 -> unreachable; `combined` is not a `--bifrost-plane` choice).
**Provider identity (the second, still-live role):** ratatoskr owns BOTH ends of the Bifrost
round-trip — the combined `:8392` provider fronts the memory (`:8391`) + affect (`:8390`) stores
(SQLite + sqlite-vec, `memory.db`/`affect.db` at repo root); consumer/owner key `wt_live_d81b…`.
`ratatoskr:sindra` is the owner-scoped Tier-3 agent (invisible to `GET /agents`; check via
`GET /agents/<owner>:<name>` with the owner key). This provider surface is settled/converged — no
in-flight work on it.
**Standing (carried from prior snapshots, still true):** the web surface (`ratatoskr-web`, :8765) is the operator's PRIMARY debug surface at full TUI pane parity (v0.19.5); the **v1 coverage-audit has CONVERGED** -- REST 17/40 (zero in-scope gaps, 23 excluded-by-design), SSE 11/11, Bifrost provider planes 8/8 live-proven; the living ledger is `docs/coverage-map.md`; **v1 cuts when Worldtree tags 1.0** (ratatoskr v1 = full Worldtree I/O coverage). Debug-observability core complete (Persona/Tools/BifrostState/AdminEvents). Substrate pins: **bifrost `==1.0.0` / wire v0.6 FROZEN**; Worldtree openapi vendored **2.2.0** (2.3.0 re-vendor pending worldtree-dev's #347/#343 consumer schemas), pinned + drift-gated in `.corviduo-canonicals.toml`; **suite 573 green.** Keys env-only mode-600 (consumer/Heimdall in `~/.config/ratatoskr/provider.env`; admin `RATATOSKR_ADMIN_API_KEY` = 7 read scopes, **personal-:8081-only**; Heimdall keys are PER-INSTANCE). Provider identity settled -- ratatoskr owns both ends of the Bifrost round-trip; `ratatoskr:sindra` is the owner-scoped Tier-3 agent (invisible to `GET /agents`; check `GET /agents/<owner>:<name>` with the owner key). Providers run as dev-box BACKGROUND SHELLS. `graphify-out/` runs dirty (auto-regen, never stage). Branch `main`, HEAD `0a8784c`; remote `origin -> git@gitea.phasefinal.com:vh/ratatoskr.git`. Open/deferred: #10 (subject-migration watch); the relational-dynamics-arc verify (still deferred, now with the bind mechanism known: `--bifrost-url :8392`).
**Open / deferred (nothing blocking):** #10 (subject-migration watch on Worldtree #196). Design
note: bare-TUI + 0-sessions → error (§4-clause-consistent; the friendlier auto-fall-to-new is
deferred, operator-preference). heid-code-review was run on the b1 resume slice only (panel: zero
findings, cross-model-verified); b2 + the later slices were offered but not reviewed. `graphify-out/`
runs dirty (auto-regen, not chased — never stage it). Contract-skip was invoked for the low-effort
GET wrappers + `stream_admin_events`, but contract #2 / #1 / #6 were amended to stay canonical.
Branch: `main` — **code tip `v0.19.5`** (`a99f247`); memory snapshots ride on top (this arc added no
code — investigation + althing coordination only). All pushed to `origin`. Remote: `origin → git@gitea.phasefinal.com:vh/ratatoskr.git`.
## Recent decisions
@@ -144,22 +234,6 @@ decision. Captures rationale that won't be obvious from code alone.
- `[2026-07-02]` **Salience finding matured into brokkr R28 (OPEN) — ratatoskr is the eval instrument.** brokkr-smithy-dev's pre-scope panel (3 dwarves + context-blind heid, 6/6) **reframed** the target: PROMOTION-WORTHINESS (durable value), NOT salience (momentary attention) — "17×23?" genuinely IS salient, so recalibrating salience yields a well-calibrated WRONG answer; the unit is SET-SELECTION under budget; eval must be OUTCOME-aligned (recall@budget / precision-at-rate), not discrimination-spread. Ties to prior art R15 (small-model memory write-policy → the granite pick) + R25 (worldtree-kb-quality). **ratatoskr delivered the P00 stratified injection-corpus** (`docs/diagnostics/r28-p00-injection-corpus.json`, committed `4a35512`; 24 self-labeling synthetic items × 3 strata) + 2 persistence-side run-validity pins (absent≠dropped without a guaranteed promotion pass; fresh agent+end_user per run vs server-dedup). **Key architectural constraint I surfaced: ratatoskr is DOWNSTREAM of the promotion gate (sees only PROMOTED chunks), so I can give keep/drop OUTCOMES via injection but NOT the pre-admission shadow pool** — that's Worldtree instrumentation. Standing by to RUN the eval once brokkr pins per-stratum N + the decision rule (gated on worldtree-dev's pipeline answer + a dwarf pass on the Snorri rule). brokkr owns methodology + takes the pipeline questions to worldtree-dev direct; ratatoskr = eval instrument. [consumer/provider thesis → a research target]
- `[2026-07-02]` **Relational-dynamics arc LIVE on demo (Worldtree v1.0.0b9) — driven by MY relation_context flag.** #319/#320 Waves 0/1/2 deployed. On the wire we persist (schema UNCHANGED): relation_context varies+demotes/ruptures; other_stance + agency now live; agency going live SHIFTS our canonical directive render past the canon ±0.2 deadband (expected, non-breaking — we key on bands); obligation_balance → 人情 ledger when tie="mixed". **ratatoskr needs NO code change** (value-agnostic renders; confirmed render-clean to worldtree-dev). **Can't live-confirm yet — our Heimdall key is personal-`:8081`-only (per-instance), demo is out of reach; will drive+confirm once PERSONAL gets b9.** Optional follow-up: surface `other_stance` (newly live, unrendered). The consumer/provider thesis: one persona-pane finding drove a full 3-wave upstream arc to production.
- `[2026-07-02]` **R28 (salience→promotion-worthiness) CLOSED (operator-directed).** A deterministic promotion-worthiness gate suffices, no trained model (brokkr's pre-gate matched/beat a strong glm-5.1 ceiling); my P00 injection-corpus + origin finding were load-bearing. My incumbent-substrate Arm-1 run is held as an OPTIONAL confirmation addendum (brokkr de-prioritized it, non-verdict-changing — run only if he asks).
- `[2026-07-02]` **R29 (PAD mood-dynamics) finding SHIPPED as Worldtree's A1 anchor fix (demo v1.0.0b14, `e1cdf82`).** Live-probing base persona agents reframed the over-regulation from "flat-near-zero" to **decay-to-NEUTRAL + low emotion→PAD gain** (NOT baseline-anchored) — triangulated across 3 baselines (arousal converges to 0 ∝ distance) + a step-response (decay τ symmetric across signs; the hedonic asymmetry is ceiling/anchor-EMERGENT, not a decay or gain primitive — this OVERTURNED the survey's asymmetry recommendation). worldtree-dev shipped A1: `decay_anchor = baseline_pad()` (was neutral) + `positive_p_cap` removed. Data `diag/r29-pad-series` (`61ff2da`). Corrected my own earlier "appraisal emissions are internal-only" claim — they ARE observable via `emotions_active` on base agents.
- `[2026-07-03]` **R30 Phase-1 φ0 measured — deployed engine CONFIG-FAITHFUL (φ0≈0.95).** Joint two-timescale fit (brokkr-ruled method (b)) + empty-tail cross-check on demo b14: φ0 ≈ 0.95–0.97 (empty-tail 0.95 exact, joint 0.971±0.01), intercept c≈0 → config `decay_rate=0.05` (φ=0.95) faithfully applied; trait-flat across baselines 0.0/0.615/0.809; A/P ratio ~uniform (NOT S2's 1.9×); φ_max rec relax→0.96. Data `diag/r30-phi0-step-response` (`23fea72`). The method converged after I read Worldtree source: only NEW dedup-gated emotions push mood (`registry.py::post_turn` L307-324; the active set decays for render/goals but never re-pushes), so R29's "net 0.90" is CONTINUOUS RE-APPRAISAL not re-push — worldtree-dev confirmed source-authoritatively; brokkr's corrected covariate landed identical. [auto-memory `reference-worldtree-affect-surface-map`]
- `[2026-07-03]` **R30 forward disposition (brokkr-owned; tracked at brokkr R30, "brokkr/worldtree will ping").** The per-turn decay has no room for `decay=f(N)` under preserve-persistence + the A/P-not-1.9 finding → R30's decay is being redesigned as a HYBRID wall+turn decay (brokkr pre-scope). R30 v1 ships GAIN-only (N→negative-reactivity) with decay held at the measured 0.95. My dedicated per-axis A/D run is DEFERRED into the hybrid-decay design pass (one wall-clock-spaced run does per-axis + a turn-vs-wall probe together). Phase-2 (moody-lofn GAIN-direction validation) waits on worldtree's `dynamics_from_ocean()` impl.
- `[2026-07-03]` **Relational-arc verify DEFERRED — `relations[]` is Bifrost-provider-only (ADR-0009), confirmed both ways.** The relational-dynamics state (relation_context tie-type / agency / warmth / trust) is NOT on the conversation-API `affect_update` snapshot for base agents (keys: pad/dominant_emotion/emotions_active/baseline_pad/mood_drift only) — only in the provider store; worldtree-dev confirmed by-design per ADR-0009 (emitted over `affect.emit`, deliberately off the SSE). So the Wave-0/1/2 verify needs the bound-provider round-trip (provider running + `--bifrost-plane affect` session), its own focused session. worldtree-dev routed the "expose relations[] to non-provider consumers" observability scope call to Vuong; my rec: keep provider-only (YAGNI — ratatoskr IS a provider, gains nothing; no speculative public surface).
- `[2026-07-04]` **R30 CLOSED on offline-tests + human face-validity (operator steer, relayed via worldtree-dev).** The deployed gap-injection run was confirmatory-not-measuring (against a deployed system the fade is `exp(-dt/tau_shipped)` by construction -> a fit recovers tau_shipped tautologically; per brokkr's S0 reframe it GRADUATES the interim coefficients, doesn't measure them), and the repo's offline tests already cover the OU formula + BOTH directions (`high_N_fades_slower_than_low_N`, `phenotype_high_n_bigger_negative_excursion`). So no Worldtree build; the interim coefficients graduate validated-as-shipped. My gap-injection harness (read/predict/record; write side stubbed; `predict()` reproduced brokkr's N=0 anchors exactly) is BANKED at `diag/r30-gap-injection-harness` for the parked powered true-tau study. [continues R30 forward-disposition 2026-07-03]
- `[2026-07-05]` **Authored-history-write primitive proposed -> accepted as Worldtree #347 (Worldtree owns the engine design; ratatoskr = reference consumer).** SillyTavern first-message generalized to a non-generating ledger-write primitive; can't be done client-side (messages `role` = model-role, not author-role). heid panel pressure-test (3/3 convergence) drove the v1 narrowing (append-only, bounded `effects` enum, drop edit/regenerate). Brief `docs/proposals/authored-message-injection.md` (`c457520`); consumer constraints captured in-brief: hide-existence 404-fallback (`022accf`) + assistant-first provider constraint (`7156b25`). Operator (Vuong) ruled the design-direction call (engine primitive + a real provenance/spoofing security surface). [reference-impl posture: we propose the shape, worldtree-dev owns the contract+impl]
- `[2026-07-05]` **#347 v1 wire validated as reference consumer (GREEN).** Adopted positions: distinct sub-resource `POST /sessions/{id}/history` (not `generate:false`), model-invisible provenance (first-message immersion preserved), event-silence for authored seed, `seeded` lifecycle phase, per-session idempotency. Three pre-TDD flags folded into contract rev 1.1: assistant-first provider constraint (Anthropic-family 400s; vLLM/openai_compat OK), content limit is BYTES not chars, 409-active-generation for append-narrator. First-message (create-time, assistant, effects=none) fully served; append-narrator served for the assistant-voice subset (system deferred); debug-seed served for assistant turns (user injection deferred to a future import primitive).
- `[2026-07-06]` **Sindra role character-rp -> character (operator).** `character-rp` resolves to a reasoning-tuned RP config (`gen-reasoning` + temp 0.75 + RP `extra_body`); `character` = plain non-reasoning (better for immersive RP). Both non-destructive PATCHes (role is mutable; model is NOT -- server: "PATCH accepts only system_prompt and/or role"). #344 (b19) fixed the role->catalog_id display conflation (the `model` field now shows the ROLE); previously it leaked `gen-reasoning`. Set via raw curl (tier3.py CLI has `--model`, not `--role`).
- `[2026-07-06]` **Sindra persona/OCEAN DECLARED -> mood fixed (the full diagnostic converged on a stale personal container).** Root cause of stuck-neutral mood: her OCEAN was prompt-TEXT only, never a structured persona; fix = delete+redefine with the define-time `persona:{ocean:{...}}` field (immutable via PATCH). My diagnosis surfaced a real engine bug **#348** (single-letter vs spelled-out OCEAN keys -> declared OCEAN silently -> 0.0/neutral; worldtree-dev fixed in b21/b22) AND a **stale-container deploy race** (personal's b22 deploy was a pull-only no-op; infra-ops force-swapped run 8211). VERIFIED: bound mood-smoke reads (0.448, 0.267, 0.316) ~= OCEAN-derived setpoint (0.418, 0.249, 0.328). [consumer/provider thesis: "reset + smoke" flushed out two upstream problems]
- `[2026-07-06]` **OpenAPI re-vendored 2.2.0->2.3.0 (`75da676`, pin-only no bump).** worldtree-dev shipped #347 as spec 2.3.0 (`879cefe`, = the deployed personal b22 image); the SessionStart drift-check flagged our openapi pin STALE. `canonical_sync` pulled 2.3.0; updated the 4 pin-tracking files (`.corviduo-canonicals.toml`, vendored openapi.json, SPEC-PIN.md, pyproject `worldtree-spec-rev`->879cefe). #347 is OpenAPI-only (prose + server contract byte-unchanged, SSE unchanged=event-silent). The re-vendor re-opened the coverage-audit with one new in-scope path-group (the #347 route).
- `[2026-07-06]` **#347 authored-history-write CONSUMER SIDE SHIPPED (`v0.19.6`) — direct in-session TDD.** `write_authored_history(client, session_id, *, content, idempotency_key, author="assistant", effects=None, claimed_original_at=None) -> dict` (POST /sessions/{id}/history; body server-pinned `AuthoredWriteRequest` extra="forbid" so omit null effects/claimed_original_at; 200-replay/201-fresh both -> ack dict; **404 -> `AuthoredHistoryUnavailable`** NOT SessionApiFailed = the hide-existence "feature-absent, never probe" contract; 409/422->SessionApiFailed) + `get_session_messages` (un-deferred GET /sessions/{id}/messages, the seed read-back proving model-invisible provenance) + a `--seed-first-message "<c>" --agent <id>` one-shot probe (create session -> seed -> read-back; 404->benign feature-absent exit 0). Contract #2 amended (2 FNs, validated OK) + 19 tests (12 wrapper + 7 cli). Suite **601 green** (clean env; the 2 "fails" under `source env.sh` are the RATATOSKR_ADMIN_API_KEY env-leak into TestParseArgs, not a regression). Coverage: **REST 19/41** (`docs/coverage-map.md` re-converged). Patch bump (coverage tail; consistent w/ the Tier-2 v0.19.1 cadence). **Live-proof pending** the `session.history.write` grant (infra-ops `01KWW3KQEY`). heid-code-review NOT run (offered).
- `[2026-07-06]` **Tail-2 SHIPPED (`v0.19.7`) — Tier-3 prose docs re-vendored + persona_state body-shape aligned.** worldtree-dev landed the Tier-3 persona/memory/persona_state PROSE docs (`c9e59ec`, on origin) — they serialize as freeform `Any` in the OpenAPI JSON, so the **prose is their source of truth** (my earlier "2.3.0 = #347-only, tail-2 collapsed" was half-wrong: the JSON was #347-only but the prose is separate). Re-vendored `docs/conversation-api-spec.md` (markdown pin, tolerate_drift; `worldtree-spec-rev` 879cefe->c9e59ec, SPEC-PIN history row added). **Consumer fix:** `--set-persona-pad`/`_set_persona_probe` was sending `{pad:[list]}` but the canonical SET body (#317) is `{pad:{pleasure,arousal,dominance}}` (named dict) — aligned it + added a len!=3 guard; updated contract #2 note + set_persona_state docstring + tests. The `set_persona_state` WRAPPER was already correct (freeform pass-through); only the CLI probe drifted. TDD (probe test asserts the dict; +1 wrong-count test). Suite **602 green**, ruff clean. **heid-code-review on #347 (dispatched + returned this session): UNANIMOUS ZERO DRIFT** (Gróa/Hulda/Regin all confirmed the hide-existence 404->`AuthoredHistoryUnavailable` routing holds at wrapper/probe/test layers + the extra="forbid" body-omission + the deliberate write-vs-read 404 asymmetry — confirmation-not-discovery for a well-TDD'd slice against a prescriptive contract). worldtree-dev foot-guns banked in SPEC-PIN + [[reference_worldtree_affect_surface_map]]: ocean single-letter `{O,C,E,A,N}` on /agents/define (#348) vs spelled-out on /characters; memory `{embedder_version, tier3_dreaming}`, stm_* deprecated, allows_world_scope removed->422; only `valence` still 422s.
_41 older entries (2026-05-* — the original debug-TUI/web build era) archived to archival-memory.md._
@@ -197,13 +271,5 @@ defense against re-attempting the same cul-de-sac.
- `[2026-06-20]` **The post-turn-async timing trap bit AGAIN — even a 35s post-`[done]` read missed the promotion `upsert_many` by ~2s** (it landed `19:48:58`; the read was ~`19:48:56`). A 15s-interval background poll caught it on the first tick. Same family as the affect.emit / async-promotion traps already logged — re-confirmed that "wait once then read" is fragile for post-turn writes; **poll a window, don't snapshot once.** (The affect.emit write, by contrast, DID land inside the 35s window — promotion is the slower of the two post-turn writes.)
- `[2026-06-30]` **Heimdall keys are PER-INSTANCE — a key minted on one Worldtree 401s on another.** Our Conversation-API key works on personal `:8081` but 401s `auth_invalid` on demo `:8080` (per-instance Heimdall user store + pepper; fresh deploys start with an EMPTY key store). Same as the admin key (personal-only). **To live-drive a given instance you need a key minted FOR that instance** (request via infra-ops). Couldn't live-prove the b2 409 on demo for this reason → deferred to personal-b2 where we have access.
- `[2026-06-30]` **`tea comment <N>` hangs on Gitea** (the whole compound bash auto-backgrounded + stuck on the open `tea` call). The #11 prereq comment hung; killed it + posted via the Gitea HTTP API directly (`POST /api/v1/repos/vh/ratatoskr/issues/<N>/comments`, token from `~/.config/tea/config.yml`). **For issue comments, prefer the Gitea API over `tea comment` when `tea` is flaky** (CLAUDE.md already says use HTTP for comment-EDITS; this extends it to ADD when tea hangs). Verify-then-post (check the comment didn't already land) to avoid a double-post after a kill.
- `[2026-07-02]` **Mask-HOSTED transient characters have a STATIC mood engine — cost a whole R29 probe.** A first probe used a `POST /characters` transient character bound via `agent_id=mask` + `character_id`; its PAD sat at baseline across 15 praise/contempt/dominance turns — the appraisal→PAD engine does NOT run on the mask-hosted transient-character path. The dynamics run only on BASE persona agents or a session bound to ratatoskr's affect provider. **To probe mood dynamics, use a base persona agent, never a mask-hosted transient character.** (mask AS a base agent — `agent_id=mask`, NO `character_id` — DOES run the engine, neutral 0,0,0 baseline.) [auto-memory `reference-worldtree-affect-surface-map`]
- `[2026-07-03]` **The "neutral non-appraising tail" premise fails — the neutral MESSAGE choice dominates.** The R30 φ0 method assumed neutral turns don't re-appraise, but factual-question neutrals ("capital of France?") trigger a new emotion nearly every turn (disappointment from the warmth-withdrawal let-down after a positive impulse) → `emotions_active` never empties in 50 turns. A minimal "Please continue." triggers FAR fewer (emotions clear ~turn 16 with spacing). The personal dry-run caught this BEFORE ~280 demo turns were spent on it — the instrument catching a flaw in the measurement design before the compute burn. (Irrelevant to the joint fit — the push_t covariate handles re-appraisal — but load-bearing for the empty-tail read.)
- `[2026-07-03]` **Two φ0-fit traps: fast-turn timescale + low-baseline conditioning.** (1) At fast turn cadence the per-turn PAD decay (φ≈0.95/turn) reaches the anchor LONG before the ~200s wall-clock emotion fade → no signal in the (eventual) emotion-free tail; need wall-clock SPACING (~16s) so the fade lands while PAD still has signal. (2) A low-baseline agent's impulse in the constrained direction (forseti P0.239 negative) gives a tiny excursion → ill-conditioned regression (r²=0.46) that FALSELY tripped "config≠behavior" when its φ was averaged in. **Weight/exclude by fit quality (r²) before aggregating — a signal-poor run isn't evidence against the config.**
- `[2026-07-06]` **`persona_state` + the agent envelope are Tier-3-BLIND -- NOT valid signals for "did a persona store".** `GET /agents/{id}/persona_state` returns 404 `persona_not_configured` for EVERY Tier-3 colon-id (hardcoded short-circuit, `api.py:1266` "regardless of row state"); the `ConsumerAgentResponse` envelope never echoes persona/motivational/memory (`api.py:538`). I mis-called "persona didn't store" from these two blind reads -- the **201-not-422 on define IS the store-success signal.** To actually SEE a Tier-3 mood, read the emitted PAD off the Bifrost affect egress after a BOUND turn (Tier-3 persists nothing Worldtree-side per ADR-0009; no persona/mood READ endpoint).
- `[2026-07-06]` **Raw `POST /sessions` is NOT Bifrost-bound -> zero affect/memory emits.** The web surface binds by setting the `bifrost` block on session-create; a raw session doesn't -> 0 affect rows, which I nearly misread as "mood is neutral". Bind from the CLI with `--new --bifrost-url http://10.100.10.50:8392` (the combined provider). Gotchas: `--bifrost-plane affect/memory` map to the SEPARATE `:8390`/`:8391` providers (`endpoint_for_plane`), which I'd PRUNED as stale duplicates -> `bifrost.endpoint_unreachable`; and `combined` is NOT a `--bifrost-plane` choice (CLI restricts to memory/affect) -> use `--bifrost-url` for :8392.
- `[2026-07-06]` **A fast/"no-op" deploy can leave a STALE container running the old image -- verify the running version, not the deploy status.** Personal's b22 deploy (run 8204) "completed" in ~1m (vs ~6m normal): a pull-only deploy racing ahead of the main build, leaving the container on the pre-#348 image. A clean bound mood read stayed neutral DESPITE the persona being declared and the fix being in the code (worldtree-dev proved the b22 derivation is correct). infra-ops force-swapped to the real b22 (run 8211, verified `info.version 2.3.0` on `879cefe`). **Lesson: when engine-proven-correct code produces wrong runtime behavior, suspect the deploy -- check the actual running image version.**
- `[2026-07-06]` **#348 OCEAN key-mismatch: a declared OCEAN silently resolved to neutral.** The define validator required single-letter `{O,C,E,A,N}` but the mood-derivation code read spelled-out `openness`/.../`neuroticism` with a 0.0 default and no remap -> every API-declared trait defaulted to 0.0 -> neutral setpoint/gain/decay. #343's tests bypassed the validator (spelled-out keys) so CI never caught it. Fixed in b21 (`Personality.from_config` accepts both key forms). **My reset+smoke diagnosis flushed it out** -- the consumer/provider thesis paying off again.
_18 older entries (2026-05-* — the original debug-TUI/web build era) archived to archival-memory.md._
+4 -4
View File
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
[project]
name = "ratatoskr"
version = "0.19.7"
version = "0.19.5"
description = "Worldtree Conversation API debug TUI — multi-pane observability dashboard"
readme = "README.md"
requires-python = ">=3.12"
@@ -60,9 +60,9 @@ Repository = "https://gitea.phasefinal.com/vh/ratatoskr"
# Ratatoskr is built against Worldtree at this commit; the vendored
# spec snapshot in docs/ reflects that SHA.
[tool.ratatoskr.spec-pin]
worldtree-spec-rev = "c9e59ec"
worldtree-version = "v1.0.0b22"
pinned-on = "2026-07-06"
worldtree-spec-rev = "5810a26b38a5ea6630892f9a39756f57c5b7b41e"
worldtree-version = "v1.0.0b2"
pinned-on = "2026-06-30"
# Bifrost lives on the auth-gated gitea PyPI index (not public PyPI).
# uv reads the credential from UV_INDEX_GITEA_USERNAME / _PASSWORD or ~/.netrc.
-61
View File
@@ -1,61 +0,0 @@
#!/usr/bin/env bash
# reset-sindra-stores.sh — wipe ratatoskr's Bifrost provider stores (memory +
# affect/persona for the single-tenant Tier-3 agent, sindra) and restart the
# combined :8392 provider empty.
#
# Usage:
# scripts/reset-sindra-stores.sh # wipe, keep ONE rolling backup (default)
# scripts/reset-sindra-stores.sh --hard # wipe with NO backup (zero-trace)
#
# The rolling backup (db-reset-backup/, gitignored via *.db*) is overwritten
# every run — it never accumulates; it's a one-level undo, nothing more.
#
# Why stop the provider first: the combined provider holds the SQLite files open
# (WAL) and caches state in memory, so an out-of-band file move without a restart
# would be shadowed. Stop -> move -> restart lets it recreate empty schema
# (CREATE TABLE IF NOT EXISTS on open).
PORT=8392
BACKUP_DIR="db-reset-backup"
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$ROOT" || { echo "reset: cannot cd to repo root $ROOT" >&2; exit 1; }
# shellcheck disable=SC1091
source ./env.sh >/dev/null 2>&1 || { echo "reset: failed to source env.sh" >&2; exit 1; }
AFFECT_DB="${RATATOSKR_AFFECT_DB:-affect.db}"
MEMORY_DB="${RATATOSKR_MEMORY_DB:-memory.db}"
HARD=0; [ "${1:-}" = "--hard" ] && HARD=1
echo "== ratatoskr provider-store reset (memory + persona) =="
echo " affect: $AFFECT_DB"
echo " memory: $MEMORY_DB"
# 1. stop the combined provider holding the DBs
PID="$(ss -ltnp 2>/dev/null | grep ":$PORT" | grep -oE 'pid=[0-9]+' | head -1 | cut -d= -f2)"
if [ -n "${PID:-}" ]; then
kill -9 "$PID" 2>/dev/null && echo "-- stopped provider :$PORT (pid $PID)"
else
echo "-- no provider on :$PORT (already down)"
fi
# 2. wipe (optional rolling backup)
files=("$AFFECT_DB" "$AFFECT_DB-wal" "$AFFECT_DB-shm" "$MEMORY_DB" "$MEMORY_DB-wal" "$MEMORY_DB-shm")
if [ "$HARD" -eq 1 ]; then
for f in "${files[@]}"; do [ -e "$f" ] && rm -f "$f" && echo "-- removed $f"; done
echo "-- HARD wipe (no backup)"
else
rm -rf "$BACKUP_DIR"; mkdir -p "$BACKUP_DIR"
for f in "${files[@]}"; do [ -e "$f" ] && mv "$f" "$BACKUP_DIR"/ && echo "-- $f -> $BACKUP_DIR/"; done
echo "-- rolling backup: $BACKUP_DIR/ (overwritten each run)"
fi
# 3. restart the combined provider (recreates empty schema on open)
nohup "$ROOT/.venv/bin/ratatoskr-combined-provider" >/tmp/ratatoskr-combined.log 2>&1 & disown
echo "-- restarted combined provider (pid $!)"
# 4. verify bound + empty
curl -s -o /dev/null -w "-- :$PORT -> HTTP %{http_code}\n" --retry 25 --retry-connrefused --retry-delay 1 "http://127.0.0.1:$PORT/"
echo "-- affect_snapshots (persona): $(sqlite3 "$AFFECT_DB" 'SELECT COUNT(*) FROM affect_snapshots' 2>&1)"
echo "-- memory_chunks (memory): $(sqlite3 "$MEMORY_DB" 'SELECT COUNT(*) FROM memory_chunks' 2>&1)"
echo "== done — sindra memory + persona reset =="
+3 -94
View File
@@ -7,7 +7,6 @@ from __future__ import annotations
import argparse
import asyncio
import hashlib
import os
import signal
import sys
@@ -19,7 +18,6 @@ import httpx
from ratatoskr.sessions import (
AgentNotFound,
AuthoredHistoryUnavailable,
BifrostBinding,
BifrostConsumerKeyMissing,
BifrostHandshakeFailed,
@@ -31,10 +29,8 @@ from ratatoskr.sessions import (
get_capabilities,
get_character_state,
get_me,
get_session_messages,
list_character_models,
set_persona_state,
write_authored_history,
)
from ratatoskr.sse_client import (
AffectUpdate,
@@ -120,9 +116,6 @@ class ParsedArgs:
# a session's persona state (affect injection).
characters: bool = False
set_persona_pad: str | None = None
# #347 authored-history-write reference-consumer probe: create a fresh
# session bound to --agent, seed an authored assistant first-message (seq-0).
seed_first_message: str | None = None
class _ArgparseError(Exception):
@@ -151,7 +144,6 @@ def _parse_args(argv: list[str] | None) -> ParsedArgs:
parser.add_argument("--admin-key", dest="admin_key")
parser.add_argument("--characters", action="store_true")
parser.add_argument("--set-persona-pad", dest="set_persona_pad", default=None)
parser.add_argument("--seed-first-message", dest="seed_first_message", default=None)
# Issue #5: required for per-end-user agents (lofn etc.); optional otherwise (mimir).
parser.add_argument("--end-user-id", dest="end_user_id", default=None)
# Issue #17: bind the created session to our own Bifrost provider plane.
@@ -172,11 +164,8 @@ def _parse_args(argv: list[str] | None) -> ParsedArgs:
# Issue #5 INV-001: --end-user-id, if passed, MUST be non-empty (mirrors --send).
if ns.end_user_id is not None and not ns.end_user_id:
raise UsageError("--end-user-id must be non-empty when passed")
if sum([ns.whoami, ns.characters, bool(ns.set_persona_pad), bool(ns.seed_first_message)]) > 1:
raise UsageError(
"--whoami / --characters / --set-persona-pad / --seed-first-message "
"are mutually exclusive"
)
if sum([ns.whoami, ns.characters, bool(ns.set_persona_pad)]) > 1:
raise UsageError("--whoami / --characters / --set-persona-pad are mutually exclusive")
if ns.whoami or ns.characters:
# Standalone one-shot probes: open no session.
if ns.send is not None or ns.session or ns.new or ns.agent:
@@ -192,17 +181,6 @@ def _parse_args(argv: list[str] | None) -> ParsedArgs:
raise UsageError("--set-persona-pad requires --session <id>")
if ns.send is not None or ns.new or ns.agent:
raise UsageError("--set-persona-pad takes only --session")
elif ns.seed_first_message is not None:
# #347 first-message probe: creates a fresh session bound to --agent,
# then seeds an authored assistant turn as seq-0 — manages its own session.
if not ns.seed_first_message:
raise UsageError("--seed-first-message must be non-empty")
if not ns.agent:
raise UsageError("--seed-first-message requires --agent <id>")
if ns.send is not None or ns.session or ns.new:
raise UsageError(
"--seed-first-message manages its own session (no --send/--session/--new)"
)
else:
if ns.session and ns.new:
raise UsageError("--session and --new are mutually exclusive")
@@ -278,7 +256,6 @@ def _parse_args(argv: list[str] | None) -> ParsedArgs:
admin_key=admin_key,
characters=ns.characters,
set_persona_pad=ns.set_persona_pad,
seed_first_message=ns.seed_first_message,
)
@@ -740,18 +717,9 @@ async def _set_persona_probe(args: ParsedArgs) -> int:
"(e.g. '0.4,0.1,-0.2')\n"
)
return 10
if len(pad) != 3:
sys.stderr.write(
"[usage_error] --set-persona-pad needs exactly 3 floats "
"(pleasure,arousal,dominance), e.g. '0.4,0.1,-0.2'\n"
)
return 10
# Canonical POST /sessions/{id}/persona_state body (#317): a named-key dict,
# NOT a bare list — {"pad": {"pleasure", "arousal", "dominance"}}.
snapshot = {"pad": {"pleasure": pad[0], "arousal": pad[1], "dominance": pad[2]}}
async with _probe_client(args) as client:
try:
await set_persona_state(client, args.session_id, snapshot)
await set_persona_state(client, args.session_id, {"pad": pad})
except SessionApiFailed as exc:
sys.stderr.write(f"[session_api_failed] status={exc.status} body={exc.body!r}\n")
return 20
@@ -764,63 +732,6 @@ async def _set_persona_probe(args: ParsedArgs) -> int:
return 0
async def _seed_first_message_probe(args: ParsedArgs) -> int:
"""--seed-first-message one-shot: create a fresh session bound to --agent,
write an authored assistant first-message (#347 POST /sessions/{id}/history),
read it back via GET /messages, print a report, exit. A reference-consumer
smoke of the authored-history-write primitive.
Hide-existence: a 404 (feature-absent OR the key lacks `session.history.write`)
is reported as a benign 'feature-absent' result (exit 0) — the probe NEVER
capability-probes to distinguish the causes (server INV-347-1). The probe
seeds but does not generate, so the assistant-first provider constraint is
inert here.
"""
assert isinstance(args, ParsedArgs)
assert args.agent_id is not None and args.seed_first_message is not None
async with _probe_client(args) as client:
try:
session = await create_session(
client, args.agent_id, end_user_id=args.end_user_id
)
sys.stdout.write(f"session: {session.session_id} (agent {session.agent_id})\n")
key = "ratatoskr-first-message-" + hashlib.sha256(
args.seed_first_message.encode("utf-8")
).hexdigest()[:12]
try:
ack = await write_authored_history(
client,
session.session_id,
content=args.seed_first_message,
idempotency_key=key,
)
except AuthoredHistoryUnavailable:
sys.stdout.write(
"authored-history: feature-absent or ungranted (404 hide-existence) "
"— a production consumer falls back to a model-generated greeting; "
"no capability-probe attempted.\n"
)
return 0
sys.stdout.write(
f"seeded: seq={ack.get('seq')} phase={ack.get('phase')} "
f"turn_id={ack.get('turn_id')} content_chars={ack.get('content_chars')}\n"
)
history = await get_session_messages(client, session.session_id)
items = history.get("items", [])
sys.stdout.write(f"read-back: {len(items)} message(s)\n")
for m in items:
sys.stdout.write(
f" seq={m.get('seq')} role={m.get('role')} content={m.get('content')!r}\n"
)
except SessionApiFailed as exc:
sys.stderr.write(f"[session_api_failed] status={exc.status} body={exc.body!r}\n")
return 20
except (httpx.ConnectError, httpx.ReadTimeout, httpx.TransportError) as exc:
sys.stderr.write(f"[network_error] {type(exc).__name__}: {exc}\n")
return 21
return 0
def main(argv: list[str] | None = None) -> int:
"""Sync entry point. Maps UsageError/_AuthError to exit codes BEFORE the event loop."""
assert argv is None or all(isinstance(a, str) for a in argv)
@@ -842,8 +753,6 @@ def main(argv: list[str] | None = None) -> int:
return asyncio.run(_characters_probe(args))
if args.set_persona_pad is not None:
return asyncio.run(_set_persona_probe(args))
if args.seed_first_message is not None:
return asyncio.run(_seed_first_message_probe(args))
if args.send_content is None:
# TUI mode — lazy import preserves INV-001 (no textual in cli at module scope).
from ratatoskr.tui import run_tui
+4 -98
View File
@@ -177,26 +177,6 @@ class AuthScopeDenied(Exception):
self.scope = scope
class AuthoredHistoryUnavailable(Exception):
"""Raised on HTTP 404 from POST /sessions/{id}/history (#347 authored-history-write).
Hide-existence (server INV-347-1): an ungranted caller, a non-owner, and an
unknown session ALL receive a 404 byte-identical to a genuine
`session_not_found` — the feature's existence is never revealed by status,
body, or error_code. The consumer MUST treat this as feature-absent and fall
back (a production consumer to a model-generated greeting), and MUST NOT
capability-probe to distinguish the causes. Distinct from `SessionApiFailed`
so callers branch feature-absent without inspecting a status code.
"""
def __init__(self, *, session_id: str) -> None:
super().__init__(
f"authored-history write unavailable for session {session_id!r} "
"(404 hide-existence: feature-absent / ungranted / session-absent)"
)
self.session_id = session_id
async def list_sessions(
client: httpx.AsyncClient,
*,
@@ -508,12 +488,10 @@ async def set_persona_state(
) -> None:
"""POST /sessions/{session_id}/persona_state — set a session's persona state (affect injection).
The request body is FREEFORM on the wire (the OpenAPI declares no request
schema), but worldtree-dev's prose now pins the canonical shape (#317):
`{"pad": {"pleasure": p, "arousal": a, "dominance": d}}` — a named-key dict
(each in [-1, 1]), NOT a bare list; PAD-only, session-scoped, pull-over-push
(#289). The caller supplies the snapshot. 204 No Content → None; any other
status → SessionApiFailed.
The request body is FREEFORM: the frozen OpenAPI 2.2.0 declares no request
schema and the prose spec documents only the GET counterpart — so the caller
supplies the snapshot shape (e.g. `{pad: [p, a, d]}`, mirroring the GET
`snapshot`). 204 No Content → None; any other status → SessionApiFailed.
"""
assert client is not None
assert session_id and isinstance(session_id, str)
@@ -580,75 +558,3 @@ async def get_capabilities(client: httpx.AsyncClient) -> dict[str, Any]:
if resp.status_code == 200:
return resp.json()
raise SessionApiFailed(status=resp.status_code, body=resp.content)
async def write_authored_history(
client: httpx.AsyncClient,
session_id: str,
*,
content: str,
idempotency_key: str,
author: str = "assistant",
effects: str | None = None,
claimed_original_at: str | None = None,
) -> dict[str, Any]:
"""POST /sessions/{session_id}/history — the #347 authored-history-write primitive.
Write one model-visible turn into the session's ledger AS the bound agent,
WITHOUT a generation and WITHOUT lived-turn side effects (the SillyTavern
"first message"). v1: `author="assistant"`, `effects` omitted (== "none"),
`idempotency_key` REQUIRED (per-session dedup). The server pins the body
(`AuthoredWriteRequest`, `extra="forbid"`), so `effects` /
`claimed_original_at` are sent only when non-None — never as null keys.
Success is 201 (fresh) or 200 (idempotent replay, byte-identical body); both
return the `AuthoredTurnResponse` dict verbatim (`{author, content_chars,
injected_at, phase, seq, session_id, turn_id}` — provenance is audit-only,
never on this body).
404 → `AuthoredHistoryUnavailable` (hide-existence: feature-absent /
ungranted / session-absent are indistinguishable by design; the caller falls
back and NEVER capability-probes — server INV-347-1). Any other non-2xx →
`SessionApiFailed` (notably 409 `generation_active`, 422 `content_too_long` /
`validation_failed`).
"""
assert client is not None
assert session_id and isinstance(session_id, str)
assert content and isinstance(content, str)
assert idempotency_key and isinstance(idempotency_key, str)
assert author and isinstance(author, str)
body: dict[str, Any] = {
"author": author,
"content": content,
"idempotency_key": idempotency_key,
}
if effects is not None:
body["effects"] = effects
if claimed_original_at is not None:
body["claimed_original_at"] = claimed_original_at
resp = await client.post(f"/sessions/{session_id}/history", json=body)
if resp.status_code in (200, 201):
return resp.json()
if resp.status_code == 404:
raise AuthoredHistoryUnavailable(session_id=session_id)
raise SessionApiFailed(status=resp.status_code, body=resp.content)
async def get_session_messages(
client: httpx.AsyncClient, session_id: str
) -> dict[str, Any]:
"""GET /sessions/{session_id}/messages — the session's message history.
Un-deferred as the #347 seed read-back: a seeded turn renders as a normal
`role=assistant` message (model-invisible provenance — indistinguishable
from a lived turn on read). Returns `{session_id, items: [{seq, role,
content, ...}], next_cursor}` verbatim; owner-scoped; any non-200 →
`SessionApiFailed`. v1 reads the server default page (no pagination params —
add limit/cursor when a caller needs scrollback).
"""
assert client is not None
assert session_id and isinstance(session_id, str)
resp = await client.get(f"/sessions/{session_id}/messages")
if resp.status_code == 200:
return resp.json()
raise SessionApiFailed(status=resp.status_code, body=resp.content)
+1 -129
View File
@@ -1692,132 +1692,4 @@ class TestTier2Probes:
)
assert rc == 0
assert "persona_state set" in capsys.readouterr().out
# canonical POST /sessions/{id}/persona_state body: named-key dict, NOT a list
assert _json.loads(route.calls[0].request.content) == {
"pad": {"pleasure": 0.4, "arousal": 0.1, "dominance": -0.2}
}
def test_set_persona_wrong_count(self) -> None:
"""set_persona_wrong_count [adversarial]: not exactly 3 floats → exit 10, no HTTP."""
rc = main(
["--set-persona-pad", "0.4,0.1", "--session", "s1",
"--api-key", "k", "--server", "https://w.example"]
)
assert rc == 10
class TestSeedFirstMessageProbe:
"""--seed-first-message one-shot (#347 authored-history-write reference-consumer probe)."""
def test_seed_requires_agent(self) -> None:
"""seed_requires_agent [adversarial]: --seed-first-message needs --agent."""
with pytest.raises(UsageError, match="requires --agent"):
_parse_args(["--seed-first-message", "hello", "--api-key", "k"])
def test_seed_forbids_session(self) -> None:
"""seed_forbids_session [adversarial]: manages its own session — no --session."""
with pytest.raises(UsageError, match="manages its own session"):
_parse_args(
["--seed-first-message", "hi", "--agent", "m", "--session", "s1", "--api-key", "k"]
)
def test_seed_mutually_exclusive(self) -> None:
"""seed_mutually_exclusive [adversarial]: --seed-first-message + --whoami → UsageError."""
with pytest.raises(UsageError, match="mutually exclusive"):
_parse_args(["--seed-first-message", "hi", "--whoami", "--api-key", "k"])
def test_seed_empty_rejected(self) -> None:
"""seed_empty_rejected [adversarial]: empty content → UsageError."""
with pytest.raises(UsageError, match="non-empty"):
_parse_args(["--seed-first-message", "", "--agent", "m", "--api-key", "k"])
def test_seed_accepted(self) -> None:
"""seed_accepted [happy]: --seed-first-message + --agent → parses."""
args = _parse_args(["--seed-first-message", "hi", "--agent", "mimir", "--api-key", "k"])
assert args.seed_first_message == "hi"
assert args.agent_id == "mimir"
assert args.session_id is None and args.new is False
@respx.mock
def test_seed_probe_happy(self, capsys: pytest.CaptureFixture[str]) -> None:
"""seed_probe [happy,tracer]: create session → seed → read-back; report to stdout."""
respx.post("https://w.example/sessions").mock(
return_value=httpx.Response(
201,
json={
"session_id": "s1",
"agent_id": "mimir",
"message_count": 0,
"created_at": "2026-07-06T12:00:00+00:00",
"last_active": "2026-07-06T12:00:00+00:00",
"metadata": {},
},
)
)
hist_route = respx.post("https://w.example/sessions/s1/history").mock(
return_value=httpx.Response(
201,
json={
"author": "assistant",
"content_chars": 5,
"injected_at": "2026-07-06T12:00:01+00:00",
"phase": "seeded",
"seq": 0,
"session_id": "s1",
"turn_id": "t1",
},
)
)
respx.get("https://w.example/sessions/s1/messages").mock(
return_value=httpx.Response(
200,
json={
"session_id": "s1",
"items": [{"seq": 0, "role": "assistant", "content": "hello"}],
"next_cursor": None,
},
)
)
rc = main(
["--seed-first-message", "hello", "--agent", "mimir",
"--api-key", "k", "--server", "https://w.example"]
)
assert rc == 0
out = capsys.readouterr().out
assert "session: s1" in out
assert "seeded: seq=0 phase=seeded" in out
assert "read-back: 1 message" in out
assert "role=assistant" in out
assert hist_route.call_count == 1
@respx.mock
def test_seed_probe_feature_absent(self, capsys: pytest.CaptureFixture[str]) -> None:
"""feature_absent [error-path]: 404 hide-existence → benign report, exit 0, no read-back."""
respx.post("https://w.example/sessions").mock(
return_value=httpx.Response(
201,
json={
"session_id": "s1",
"agent_id": "mimir",
"message_count": 0,
"created_at": "2026-07-06T12:00:00+00:00",
"last_active": "2026-07-06T12:00:00+00:00",
"metadata": {},
},
)
)
respx.post("https://w.example/sessions/s1/history").mock(
return_value=httpx.Response(404, json={"error_code": "session_not_found"})
)
msgs_route = respx.get("https://w.example/sessions/s1/messages").mock(
return_value=httpx.Response(
200, json={"session_id": "s1", "items": [], "next_cursor": None}
)
)
rc = main(
["--seed-first-message", "hello", "--agent", "mimir",
"--api-key", "k", "--server", "https://w.example"]
)
assert rc == 0
assert "feature-absent" in capsys.readouterr().out
assert msgs_route.call_count == 0 # never capability-probes past the 404
assert _json.loads(route.calls[0].request.content) == {"pad": [0.4, 0.1, -0.2]}
+2 -187
View File
@@ -8,7 +8,6 @@ from ratatoskr.sessions import (
AgentInfo,
AgentNotAvailable,
AgentNotFound,
AuthoredHistoryUnavailable,
AuthScopeDenied,
BifrostBinding,
BifrostConsumerKeyMissing,
@@ -26,13 +25,11 @@ from ratatoskr.sessions import (
get_me,
get_persona_state,
get_session_bifrost,
get_session_messages,
get_session_tools,
list_agents,
list_character_models,
list_sessions,
set_persona_state,
write_authored_history,
)
@@ -1182,13 +1179,9 @@ class TestSetPersonaState:
return_value=httpx.Response(204)
)
async with httpx.AsyncClient(base_url="https://w.example") as client:
result = await set_persona_state(
client, "s1", {"pad": {"pleasure": 0.4, "arousal": 0.1, "dominance": -0.2}}
)
result = await set_persona_state(client, "s1", {"pad": [0.4, 0.1, -0.2]})
assert result is None
assert _json.loads(route.calls[0].request.content) == {
"pad": {"pleasure": 0.4, "arousal": 0.1, "dominance": -0.2}
}
assert _json.loads(route.calls[0].request.content) == {"pad": [0.4, 0.1, -0.2]}
@respx.mock
async def test_non_204_raises(self) -> None:
@@ -1200,181 +1193,3 @@ class TestSetPersonaState:
with pytest.raises(SessionApiFailed) as exc:
await set_persona_state(client, "s1", {"pad": [1, 2, 3]})
assert exc.value.status == 422
_AUTHORED_ACK = {
"author": "assistant",
"content_chars": 5,
"injected_at": "2026-07-06T12:00:00+00:00",
"phase": "seeded",
"seq": 0,
"session_id": "s1",
"turn_id": "t1",
}
class TestWriteAuthoredHistory:
"""write_authored_history — #347 POST /sessions/{id}/history (contract #2 amendment)."""
@respx.mock
async def test_happy_fresh_201(self) -> None:
"""happy_fresh_201 [happy,tracer]: 201 → ack verbatim; minimal body."""
import json as _json
route = respx.post("https://w.example/sessions/s1/history").mock(
return_value=httpx.Response(201, json=_AUTHORED_ACK)
)
async with httpx.AsyncClient(base_url="https://w.example") as client:
result = await write_authored_history(
client, "s1", content="hello", idempotency_key="k1"
)
assert result == _AUTHORED_ACK
assert _json.loads(route.calls[0].request.content) == {
"author": "assistant",
"content": "hello",
"idempotency_key": "k1",
}
@respx.mock
async def test_happy_replay_200(self) -> None:
"""happy_replay_200 [happy]: 200 replay (byte-identical body) → dict verbatim."""
respx.post("https://w.example/sessions/s1/history").mock(
return_value=httpx.Response(200, json=_AUTHORED_ACK)
)
async with httpx.AsyncClient(base_url="https://w.example") as client:
result = await write_authored_history(
client, "s1", content="hello", idempotency_key="k1"
)
assert result == _AUTHORED_ACK
@respx.mock
async def test_body_includes_effects(self) -> None:
"""body_includes_effects [trace]: effects + claimed_original_at appear iff non-None."""
import json as _json
route = respx.post("https://w.example/sessions/s1/history").mock(
return_value=httpx.Response(201, json=_AUTHORED_ACK)
)
async with httpx.AsyncClient(base_url="https://w.example") as client:
await write_authored_history(
client,
"s1",
content="hi",
idempotency_key="k1",
effects="none",
claimed_original_at="2020-01-01T00:00:00Z",
)
assert _json.loads(route.calls[0].request.content) == {
"author": "assistant",
"content": "hi",
"idempotency_key": "k1",
"effects": "none",
"claimed_original_at": "2020-01-01T00:00:00Z",
}
@respx.mock
async def test_hide_existence_404(self) -> None:
"""hide_existence_404 [error]: 404 → AuthoredHistoryUnavailable (NOT SessionApiFailed)."""
respx.post("https://w.example/sessions/s1/history").mock(
return_value=httpx.Response(404, json={"error_code": "session_not_found"})
)
async with httpx.AsyncClient(base_url="https://w.example") as client:
with pytest.raises(AuthoredHistoryUnavailable) as exc:
await write_authored_history(client, "s1", content="hi", idempotency_key="k1")
assert exc.value.session_id == "s1"
@respx.mock
async def test_generation_active_409(self) -> None:
"""generation_active_409 [error]: 409 → SessionApiFailed(409)."""
respx.post("https://w.example/sessions/s1/history").mock(
return_value=httpx.Response(409, json={"error_code": "generation_active"})
)
async with httpx.AsyncClient(base_url="https://w.example") as client:
with pytest.raises(SessionApiFailed) as exc:
await write_authored_history(client, "s1", content="hi", idempotency_key="k1")
assert exc.value.status == 409
@respx.mock
async def test_content_too_long_422(self) -> None:
"""content_too_long_422 [error]: 422 → SessionApiFailed(422)."""
respx.post("https://w.example/sessions/s1/history").mock(
return_value=httpx.Response(422, json={"error_code": "content_too_long"})
)
async with httpx.AsyncClient(base_url="https://w.example") as client:
with pytest.raises(SessionApiFailed) as exc:
await write_authored_history(client, "s1", content="x", idempotency_key="k1")
assert exc.value.status == 422
@respx.mock
async def test_empty_content(self) -> None:
"""empty_content [adversarial]: content="" → AssertionError; no HTTP issued."""
route = respx.post("https://w.example/sessions/s1/history").mock(
return_value=httpx.Response(201, json=_AUTHORED_ACK)
)
async with httpx.AsyncClient(base_url="https://w.example") as client:
with pytest.raises(AssertionError):
await write_authored_history(client, "s1", content="", idempotency_key="k1")
assert not route.called
@respx.mock
async def test_empty_idempotency_key(self) -> None:
"""empty_idempotency_key [adversarial]: key="" → AssertionError; no HTTP issued."""
route = respx.post("https://w.example/sessions/s1/history").mock(
return_value=httpx.Response(201, json=_AUTHORED_ACK)
)
async with httpx.AsyncClient(base_url="https://w.example") as client:
with pytest.raises(AssertionError):
await write_authored_history(client, "s1", content="hi", idempotency_key="")
assert not route.called
@respx.mock
async def test_empty_session_id(self) -> None:
"""empty_session_id [adversarial]: session_id="" → AssertionError; no HTTP issued."""
route = respx.post("https://w.example/sessions/s1/history").mock(
return_value=httpx.Response(201, json=_AUTHORED_ACK)
)
async with httpx.AsyncClient(base_url="https://w.example") as client:
with pytest.raises(AssertionError):
await write_authored_history(client, "", content="hi", idempotency_key="k1")
assert not route.called
class TestGetSessionMessages:
"""#2 contract (amendment 2026-07-06) — get_session_messages (GET /sessions/{id}/messages)."""
@respx.mock
async def test_happy(self) -> None:
"""happy [happy,tracer]: 200 {session_id, items, next_cursor} → dict verbatim."""
payload = {
"session_id": "s1",
"items": [{"seq": 0, "role": "assistant", "content": "hello there"}],
"next_cursor": None,
}
respx.get("https://w.example/sessions/s1/messages").mock(
return_value=httpx.Response(200, json=payload)
)
async with httpx.AsyncClient(base_url="https://w.example") as client:
result = await get_session_messages(client, "s1")
assert result == payload
@respx.mock
async def test_not_found_404(self) -> None:
"""not_found_404 [error]: 404 → SessionApiFailed(404)."""
respx.get("https://w.example/sessions/s1/messages").mock(
return_value=httpx.Response(404, json={"error_code": "session_not_found"})
)
async with httpx.AsyncClient(base_url="https://w.example") as client:
with pytest.raises(SessionApiFailed) as exc:
await get_session_messages(client, "s1")
assert exc.value.status == 404
@respx.mock
async def test_empty_session_id(self) -> None:
"""empty_session_id [adversarial]: "" → AssertionError; no HTTP issued."""
route = respx.get("https://w.example/sessions/s1/messages").mock(
return_value=httpx.Response(200, json={})
)
async with httpx.AsyncClient(base_url="https://w.example") as client:
with pytest.raises(AssertionError):
await get_session_messages(client, "")
assert not route.called
Generated
+1 -1
View File
@@ -1052,7 +1052,7 @@ wheels = [
[[package]]
name = "ratatoskr"
version = "0.19.7"
version = "0.19.5"
source = { editable = "." }
dependencies = [
{ name = "httpx" },