refactor(state): compact verbose docstrings (rules/invariants kept)

This commit is contained in:
Teknium
2026-09-02 16:14:33 -07:00
parent 95714f6d93
commit 5340109e61
3 changed files with 56 additions and 80 deletions
+6 -9
View File
@@ -242,15 +242,12 @@ class SessionPortabilityMixin:
Stranded-bot-session heal: before the desktop routed session RPCs by
target session, a profile bot's rows accumulated in the DEFAULT
profile's state.db; this moves the conversation to where routing now
looks. Pure composition: ``donor_db.export_session_lineage()`` ->
``self.import_sessions()`` — routing/handoff/activity fields reset,
already-present ids skipped (idempotent re-adoption).
With ``retire_donor`` and a complete adoption, donor rows are ARCHIVED
(never deleted) with ``end_reason='adopted_by_profile'``. That
end_reason is deliberately NOT in the recoverable set
(agent_close/ws_orphan_reap): resurrection must not undo an adoption.
looks. Pure composition ``donor_db.export_session_lineage()`` ->
``self.import_sessions()``: routing/handoff/activity fields reset,
already-present ids skipped (idempotent re-adoption). With
``retire_donor`` and a complete adoption, donor rows are ARCHIVED
(never deleted) with ``end_reason='adopted_by_profile'`` — deliberately
NOT in the recoverable set, so resurrection cannot undo an adoption.
Returns the ``import_sessions`` dict plus ``adopted`` and
``donor_retired`` (True only when EVERY segment's retirement applied).
"""
+24 -33
View File
@@ -134,18 +134,14 @@ def schema_read_probe_statements() -> tuple:
"""SELECT statements that fail iff a live store is behind SCHEMA_SQL.
Read-only opens skip ``_reconcile_columns()`` by design (no DDL against
another profile's live DB), so a store created before a schema addition
keeps failing on read paths until something opens it writable. Healing
callers (``_open_session_db_at_path`` in the web server) run these probes
after a read-only open: a missing table/column raises at prepare time.
Derived from SCHEMA_SQL so a column added there is covered automatically
(a hand-maintained list went stale within days). Each statement is
``LIMIT 0`` (resolution at prepare time, zero rows read). Column
references are table-qualified: an unqualified double-quoted identifier
that fails to resolve silently degrades to a string literal (SQLite
misfeature), which would make the probe pass on exactly the stale store
it exists to catch.
another profile's live DB), so healing callers (``_open_session_db_at_path``
in the web server) run these probes after a read-only open: a missing
table/column raises at prepare time. Derived from SCHEMA_SQL so a column
added there is covered automatically (a hand-maintained list went stale
within days); ``LIMIT 0`` so zero rows are read. Column references are
table-qualified: an unqualified double-quoted identifier that fails to
resolve silently degrades to a string literal (SQLite misfeature), which
would make the probe pass on exactly the stale store it exists to catch.
"""
global _READ_PROBE_STATEMENTS
if _READ_PROBE_STATEMENTS is None:
@@ -470,19 +466,15 @@ class SessionSchemaMixin:
return self._recover_stale_fts_locked(cursor, legacy=legacy)
def retry_deferred_fts_recovery(self) -> bool:
"""Retry a deferred stale-FTS rebuild on this open SessionDB.
``_recover_stale_fts`` fails closed at open when holders or the rebuild
lock are busy, leaving ``_fts_stale`` set and search on LIKE. Live
write/search paths must never start a full rebuild, and a gateway
opens state.db once for days, so "next open" never comes. This is the
in-process retry from the gateway housekeeping tick: bounded backoff
(``_FTS_STALE_RETRY_SECONDS`` doubling to the max), non-blocking
admission (``timeout=0``), no new thread.
"""Retry a deferred stale-FTS rebuild on this open SessionDB (gateway
housekeeping tick). ``_recover_stale_fts`` fails closed at open when
holders or the rebuild lock are busy, leaving ``_fts_stale`` set and
search on LIKE; live write/search paths must never start a full
rebuild, and a gateway opens state.db once for days, so "next open"
never comes. Bounded backoff (``_FTS_STALE_RETRY_SECONDS`` doubling to
the max), non-blocking admission (``timeout=0``), no new thread.
Returns True only when the index was rebuilt and sync triggers
restored. Never raises.
"""
restored. Never raises."""
if not self._fts_stale or self.read_only or self._conn is None:
return False
now = time.monotonic()
@@ -1130,15 +1122,14 @@ class SessionSchemaMixin:
Reached when the sync triggers were missing and the DDL just recreated
them: the index has a gap of unknown extent. Two processes opening the
same DB after an update commonly hit this simultaneously — the
concurrent-rebuild interleaving that structurally corrupted state.db
in production — so this admits through ``fts_rebuild_admission`` and
FAILS CLOSED. On deferral the just-repaired triggers are dropped again
and the stale breadcrumb persisted (``_enter_fts_fail_open``'s
ordering contract: triggers must never be live over an unrebuilt gap);
the winner's rebuild, ``retry_deferred_fts_recovery``, or
``_recover_stale_fts`` at next startup restores index and triggers.
"""
same DB after an update commonly hit this simultaneously (the
interleaving that structurally corrupted state.db in production), so
this admits through ``fts_rebuild_admission`` and FAILS CLOSED. On
deferral the just-repaired triggers are dropped again and the stale
breadcrumb persisted — triggers must never be live over an unrebuilt
gap (``_enter_fts_fail_open``'s ordering contract); the winner's
rebuild, ``retry_deferred_fts_recovery`` or ``_recover_stale_fts`` at
next startup restores index and triggers."""
with fts_rebuild_admission(self.db_path) as admitted:
if admitted:
rebuild_fn()
+26 -38
View File
@@ -662,19 +662,15 @@ class SessionSearchMixin:
self, session_id: str, around_message_id: int, window: int = 5, bookend: int = 3,
keep_roles: Optional[Tuple[str, ...]] = ("user", "assistant"),
) -> Dict[str, Any]:
"""Anchored window (``get_messages_around``) plus session bookends.
- ``window``: filtered to ``keep_roles``, EXCEPT the anchor itself is
always kept regardless of role.
- ``bookend_start`` / ``bookend_end``: first/last ``bookend`` messages
with ids strictly outside the window (empty when the window already
overlaps the head/tail). Empty-content rows (tool-call-only turns)
are skipped so they don't crowd out prose.
Bookends let a hit anywhere in a long session yield the goal and the
resolution in one call. Empty slices + zero counts when the anchor
isn't in the session. ``keep_roles=None`` disables role filtering.
"""
"""Anchored window (``get_messages_around``) plus session bookends, so a
hit anywhere in a long session yields the goal and the resolution in
one call. ``window`` is filtered to ``keep_roles`` EXCEPT the anchor,
which is always kept; ``bookend_start`` / ``bookend_end`` are the
first/last ``bookend`` messages with ids strictly outside the window
(empty when the window already overlaps the head/tail), skipping
empty-content rows (tool-call-only turns) so they don't crowd out
prose. Empty slices + zero counts when the anchor isn't in the
session. ``keep_roles=None`` disables role filtering."""
bookend = max(bookend, 0)
primitive = self.get_messages_around(session_id, around_message_id, window=window)
window_rows = primitive["window"]
@@ -1345,15 +1341,12 @@ class SessionSearchMixin:
def rebuild_fts(self) -> int:
"""Rebuild FTS5 indexes from ``messages`` (``'rebuild'``) — the
documented recovery for a corrupt index that rejects writes while
reads succeed.
A full structural rebuild must never run concurrently in two processes
sharing one state.db (that interleaving corrupted production DBs), so
this admits through ``fts_rebuild_admission`` and FAILS CLOSED,
returning 0 on deferral; callers treat 0 as "no progress" and fall
back to the stale-FTS breadcrumb path. Skips absent tables. Returns
the number of indexes rebuilt.
"""
reads succeed. A full structural rebuild must never run concurrently
in two processes sharing one state.db (that interleaving corrupted
production DBs), so this admits through ``fts_rebuild_admission`` and
FAILS CLOSED, returning 0 on deferral (callers treat 0 as "no
progress" and fall back to the stale-FTS breadcrumb path). Skips
absent tables; returns the number of indexes rebuilt."""
rebuilt = 0
with fts_rebuild_admission(self.db_path) as admitted:
if not admitted:
@@ -1379,22 +1372,17 @@ class SessionSearchMixin:
"""Run bounded FTS5 ``'merge'`` commands against each present index.
A positive merge rank stops after ~that many output pages, so each
command holds the write lock for milliseconds regardless of index
size — unlike ``'optimize'`` (9-18 s per index on a 10 GB DB, enough
to exhaust a competing writer's lock-retry patience).
- ``usermerge`` is lowered to its minimum of 2 (persisted in the
``%_config`` shadow table, once per instance) so a positive merge
acts on ANY level with >= 2 segments; at the default 4 a fragmented
index cannot converge.
- Up to *max_commands* per index, stopping on the documented
no-progress signal: ``total_changes`` delta < 2 (the command's own
INSERT is 1 change).
Each command is its own implicit transaction (``isolation_level=None``),
so competing processes interleave mid-pass. Missing tables are valid
variants (optimize_fts_storage drops + backfills them live) and are
skipped; other SQLite errors propagate. Returns commands executed.
command holds the write lock for milliseconds regardless of index size
(``'optimize'`` takes 9-18 s per index on a 10 GB DB, exhausting a
competing writer's lock-retry patience). ``usermerge`` is lowered to
its minimum of 2 (persisted in ``%_config``, once per instance) so a
positive merge acts on ANY level with >= 2 segments; at the default 4 a
fragmented index cannot converge. Up to *max_commands* per index,
stopping on the no-progress signal ``total_changes`` delta < 2 (the
command's own INSERT is 1 change). Each command is its own implicit
transaction, so competing processes interleave mid-pass. Missing tables
are valid variants (optimize_fts_storage drops + backfills them live)
and are skipped; other SQLite errors propagate. Returns commands executed.
"""
if isinstance(max_pages, bool) or not isinstance(max_pages, int):
raise TypeError("max_pages must be an integer")