What
Three SQLite-backed tests emit Python's DeprecationWarning for the default
datetime adapter, which is scheduled for removal:
tests_py/handlers/test_consolidate.py::TestConsolidateHandler::test_with_memories
tests_py/handlers/test_consolidate.py::TestConsolidateHandler::test_protected_memories_skip_compression
tests_py/integration/test_memory_lifecycle.py::TestFullLifecycle::test_store_consolidate_recall
mcp_server/infrastructure/sqlite_compat.py:287: DeprecationWarning: The default
datetime adapter is deprecated as of Python 3.12; see the sqlite3 documentation
for suggested replacement recipes
cur = self._real.execute(translated, params)
Reproduction (2026-07-29, macOS, Python 3.12, worktree at c1f449f)
$ env -u DATABASE_URL CORTEX_MEMORY_STORE_BACKEND=sqlite python -m pytest -q
6367 passed, 81 skipped, 3 warnings, 117 subtests passed in 123.48s
The three warnings above are the three. sqlite_compat.py:287 passes a
datetime straight through to sqlite3.Connection.execute, so the stdlib's
deprecated implicit adapter converts it.
Why it is not a drive-by fix
sqlite3.register_adapter(datetime, ...) is a process-global side effect that
changes the ON-DISK text of every datetime column the SQLite store writes.
That is a persisted-format change (§13.1 E3): it needs a decision on the
serialization (ISO-8601 with or without timezone), a read path that accepts
both the old and the new spelling or a one-shot migration, and a test that
feeds old-data-in/new-code. Picking one silently inside an unrelated PR is
exactly the shim the project forbids.
Acceptance criteria
mcp_server/infrastructure/sqlite_compat.py no longer relies on the
implicit stdlib adapter: datetimes are serialized explicitly at the one
boundary that writes them.
- The chosen wire format is stated in the module docstring, with the read
path that parses it.
- Existing SQLite stores keep reading: a test writes a row in the pre-change
spelling and asserts the post-change reader returns the same value (or a
one-shot migration ships and is tested).
- The suite runs warning-free for this rule — a
filterwarnings entry that
turns this DeprecationWarning into an error, so it cannot silently return.
Provenance
Seen while running the standard suite during #253 (pyright/tree-sitter
resolution divergence). Outside that change's blast radius — #253 touches
core/ast_parser.py, core/ast_extractor_registry.py, the dependency pin
and CI/doc wiring, with no import path to infrastructure/sqlite_compat.py —
so it is deferred here per coding-standards §14.3 rather than folded in.
What
Three SQLite-backed tests emit Python's
DeprecationWarningfor the defaultdatetimeadapter, which is scheduled for removal:Reproduction (2026-07-29, macOS, Python 3.12, worktree at
c1f449f)The three warnings above are the three.
sqlite_compat.py:287passes adatetimestraight through tosqlite3.Connection.execute, so the stdlib'sdeprecated implicit adapter converts it.
Why it is not a drive-by fix
sqlite3.register_adapter(datetime, ...)is a process-global side effect thatchanges the ON-DISK text of every datetime column the SQLite store writes.
That is a persisted-format change (§13.1 E3): it needs a decision on the
serialization (ISO-8601 with or without timezone), a read path that accepts
both the old and the new spelling or a one-shot migration, and a test that
feeds old-data-in/new-code. Picking one silently inside an unrelated PR is
exactly the shim the project forbids.
Acceptance criteria
mcp_server/infrastructure/sqlite_compat.pyno longer relies on theimplicit stdlib adapter: datetimes are serialized explicitly at the one
boundary that writes them.
path that parses it.
spelling and asserts the post-change reader returns the same value (or a
one-shot migration ships and is tested).
filterwarningsentry thatturns this DeprecationWarning into an error, so it cannot silently return.
Provenance
Seen while running the standard suite during #253 (pyright/tree-sitter
resolution divergence). Outside that change's blast radius — #253 touches
core/ast_parser.py,core/ast_extractor_registry.py, the dependency pinand CI/doc wiring, with no import path to
infrastructure/sqlite_compat.py—so it is deferred here per coding-standards §14.3 rather than folded in.