From 46afbfec108b3ce2b144b894b49aa63014469909 Mon Sep 17 00:00:00 2001 From: teknium1 <127238744+teknium1@users.noreply.github.com> Date: Fri, 11 Sep 2026 02:28:00 -0700 Subject: [PATCH] fix(state): route the remaining model_config marker reads through _sql_json_extract Sibling widening of the #101726 salvage: FTS_TRIGRAM_SESSION_SQL (trigram view/triggers/backfill), the v16 delegate-tagging data migration and reopen_session's legacy reset-child stamp still called json_extract() on the raw model_config cell, so one malformed JSON row could still abort FTS maintenance, a schema migration or /resume of a reset child. Zero raw model_config json_extract reads remain in hermes_state_*.py. --- hermes_state_common.py | 2 +- hermes_state_schema.py | 8 ++++---- hermes_state_sessions.py | 3 +-- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/hermes_state_common.py b/hermes_state_common.py index a5a824ed08..b1f4ec28aa 100644 --- a/hermes_state_common.py +++ b/hermes_state_common.py @@ -763,7 +763,7 @@ FTS_TRIGRAM_EXCLUDED_SOURCES = ("cron", "subagent") FTS_TRIGRAM_SESSION_SQL = ( "source NOT IN (" + ", ".join(f"'{src}'" for src in FTS_TRIGRAM_EXCLUDED_SOURCES) - + ") AND json_extract(COALESCE(model_config, '{}'), '$._delegate_from') IS NULL" + + f") AND {_sql_json_extract('model_config', '$._delegate_from')} IS NULL" ) diff --git a/hermes_state_schema.py b/hermes_state_schema.py index 996c5163f5..977ee163e4 100644 --- a/hermes_state_schema.py +++ b/hermes_state_schema.py @@ -24,7 +24,7 @@ from hermes_state_common import ( DEFERRED_INDEX_SQL, FTS_CJK_STALE_KEY, FTS_REBUILD_DEFERRAL_KEY, FTS_STALE_KEY, FTS_SQL, FTS_STORAGE_VERSION, FTS_TOOL_FULL_CONTENT_HIGH_WATER_KEY, FTS_TRIGRAM_SQL, LEGACY_FTS_SQL, LEGACY_FTS_TRIGRAM_SQL, SCHEMA_SQL, - SCHEMA_VERSION, _FTS_CJK_TRIGGERS, _FTS_TRIGGERS, _ephemeral_child_sql, fts_rebuild_admission, + SCHEMA_VERSION, _FTS_CJK_TRIGGERS, _FTS_TRIGGERS, _ephemeral_child_sql, _sql_json_extract, fts_rebuild_admission, ) from hermes_state_holders import _read_proc_argv @@ -979,14 +979,14 @@ class SessionSchemaMixin: "UPDATE sessions SET model_config = json_set(" "COALESCE(model_config, '{}'), '$._delegate_from', parent_session_id) " f"WHERE parent_session_id IS NOT NULL " - "AND json_extract(COALESCE(model_config, '{}'), '$._delegate_from') IS NULL " + f"AND {_sql_json_extract('model_config', '$._delegate_from')} IS NULL " f"AND {_ephemeral_child_sql('sessions')}" ) cursor.execute( "UPDATE sessions SET model_config = json_set(" "COALESCE(model_config, '{}'), '$._delegate_from', '__orphaned__') WHERE parent_session_id IS NULL " - "AND json_extract(COALESCE(model_config, '{}'), '$._delegate_from') IS NULL " - "AND json_extract(COALESCE(model_config, '{}'), '$._branched_from') IS NULL " + f"AND {_sql_json_extract('model_config', '$._delegate_from')} IS NULL " + f"AND {_sql_json_extract('model_config', '$._branched_from')} IS NULL " "AND title IS NULL AND message_count <= 25 AND EXISTS (SELECT 1 FROM messages m " " WHERE m.session_id = sessions.id AND m.role = 'tool') " "AND NOT EXISTS (SELECT 1 FROM sessions ch " diff --git a/hermes_state_sessions.py b/hermes_state_sessions.py index 74d2c3da8b..37834b9227 100644 --- a/hermes_state_sessions.py +++ b/hermes_state_sessions.py @@ -454,8 +454,7 @@ class SessionSessionsMixin: conn.execute( "UPDATE sessions AS child SET model_config = json_set(" "COALESCE(child.model_config, '{}'), '$._reset_from', child.parent_session_id) " - "WHERE child.parent_session_id = ? AND json_extract(COALESCE(child.model_config, '{}'), " - " '$._reset_from') IS NULL " + f"WHERE child.parent_session_id = ? AND {_sql_json_extract('child.model_config', '$._reset_from')} IS NULL " f"AND {_legacy_reset_child_sql('child', _session_ids_placeholders(_RESET_END_REASONS))}", (session_id, *_RESET_END_REASONS), )