Skip to content

v1.0.2 — persona_instances FKs + LLM-reply parse helper

Choose a tag to compare

@enriquephl enriquephl released this 05 Aug 12:33
· 121 commits to main since this release
v1.0.2
6015ee5

Referential integrity for persona_instances plus an internal parse-helper cleanup. One breaking change for direct DB writers — see below.

⚠️ Breaking

  • fix(store)!: missing persona_instances foreign keys are now real constraints (#224). chat_sessions.instance_id, companion_affinity.instance_id and companion_memories.instance_id referenced engine.persona_instances(id) by convention only — they predate the world/story tables (00350039), which all declare a real FK. Nothing stopped a bogus instance_id from being written, and no cascade fired when an instance was removed out of band.

    Migration 0040_persona_instance_fks.sql adds all three with ON DELETE CASCADE, matching the six existing FKs into persona_instances. The constraints go in validated (not NOT VALID) — all three columns were verified orphan-free and the tables are small. companion_memories.instance_id stays nullable; a FK ignores NULL, so the profile layer is unaffected.

    Impact: a direct DB writer that inserted an unknown instance_id now gets 23503, and deleting an instance now removes its chat history. The engine itself never DELETEs an instance (it flips status to archived — see PersonaStore::ensure_active_instance), so the cascade only governs deliberate out-of-band deletion, where wiping the instance's data is the point.

    Beyond integrity this restores navigability: without the FK the Supabase table editor renders instance_id as a plain UUID column, so there is no way to click through from a session to its persona instance.

Fixes & internals

  • refactor(server): dedupe LLM-reply JSON parsing (#221). The repeated direct-then-find_json_block parse ladder is extracted into pipeline::parse_llm_json<T> and applied to the seven exact-pattern call sites (input filter, PDE verdict, image vision, compose reply, affinity eval, fact extraction, story output). The insight-extraction site keeps its per-arm is_object filter — folding it in would drop the array-wrapped-object salvage — and the block-first strict parsers (world, world_town, dreaming) are deliberately untouched. In drive_chat_burst, each of the three arms serialized the same last_usage twice (full DB copy + filtered wire copy); a single hoisted usage_full per arm now matches the existing product_qa pattern. No behavior change; four new unit tests for parse_llm_json.

Docs

  • docs(readme): simplified abstract, "Why this exists" renamed to "Highlights" across README.md, README.zh.md, README.ja.md (#222, promoted to main separately via #223).

Upgrading

Run the migration — 0040_persona_instance_fks.sql applies on start like every other migration. If you write to engine.* from outside the engine, audit for inserts carrying an instance_id that does not exist in persona_instances before upgrading; those now fail with 23503.

docker pull ghcr.io/etherfunlab/eros-engine:1.0.2

Full Changelog: v1.0.1...v1.0.2