- peer_messages.row_get gains default=None (was None-only); the
three old variants agree on all real row types (None / dict /
sqlite3.Row): auto_memory's old default was already None, and
lifecycle's old None special-case and dict .get give identical
results on those types, so no call-site behavior changes and no
call site passes a non-None default.
- auto_memory and lifecycle delete their private _row_get copies
and import peer_messages.row_get as _row_get (precedent: server,
worker, handler_project, handler_support already do this);
peer_messages imports no cloud modules, so no import cycle.
lifecycle's old broad-Exception catch differs only for pathological
__getitem__ inputs, which are not DB rows and are out of contract;
this is documented on row_get, not left as a second story.
- Scope note: other modules' own row_get copies (approvals,
automations, marker_tools, todos, wait_ops) are out of this item's
stated scope and are untouched.
- Also drops auto_memory's unused 'import os' (pre-existing F401),
so touched files are ruff E,F clean.
- Tests: cloud/tests/test_row_get_unified.py locks the identity
(both aliases ARE row_get), the real-row-type matrix, the
None-default fallback, and snapshot_to_dict via the unified path.
(cherry picked from commit 1644a0b837bfefb13cdc3c93d87fc1b246026607)