Migrate and validate per-turn runtime truth with conversation current-runtime semantics.
This playbook explains the runtime-semantics cutover:
turns.runtime_key, turns.inference_id),resolved_runtime_key in debug APIs).Use this when upgrading existing SQLite stores or validating runtime-switch correctness.
Two fields now represent different truths:
turns.runtime_key and turns.inference_id./api/debug/conversations and /api/debug/conversations/:id return resolved_runtime_key.Do not treat conversation current runtime as full turn history.
Conversation debug payloads:
current_runtime_keyresolved_runtime_keyTurn debug payloads:
/api/debug/turns items include runtime_key and inference_id./api/debug/turn/:conv/:session/:turn phase items include runtime_key and inference_id.Inspect schema columns:
PRAGMA table_info(turns);
Expected additive columns:
runtime_key TEXT NOT NULL DEFAULT ''inference_id TEXT NOT NULL DEFAULT ''Check indexes:
SELECT name, sql
FROM sqlite_master
WHERE type = 'index'
AND tbl_name = 'turns'
AND name IN ('turns_by_conv_runtime_updated', 'turns_by_conv_inference_updated');
Validate runtime history for one conversation:
SELECT turn_id, runtime_key, inference_id, updated_at_ms
FROM turns
WHERE conv_id = 'your-conv-id'
ORDER BY updated_at_ms ASC, turn_id ASC;
Detect rows that still have empty backfill values:
SELECT COUNT(*) AS missing_runtime_or_inference
FROM turns
WHERE COALESCE(runtime_key, '') = ''
OR COALESCE(inference_id, '') = '';
Inspect candidate metadata for manual recovery:
SELECT conv_id, session_id, turn_id, turn_metadata_json
FROM turns
WHERE COALESCE(runtime_key, '') = ''
OR COALESCE(inference_id, '') = ''
LIMIT 50;
Backfill is best-effort and uses turn metadata keys. Some old rows may remain empty when metadata was missing or non-canonical.
Recommended response:
Use this snippet in release notes:
Runtime persistence semantics changed:
- per-turn runtime/inference are now first-class and queryable in turns.db,
- conversation debug APIs now expose resolved_runtime_key (latest pointer only),
- consumers must not infer historical runtime from conversation-level fields.