b54b246071
Three coordinated changes to make guided mode actually answer 'catch me up
on X' questions without needing summary:
1. New SessionDB.get_anchored_view() helper: returns the anchored window
plus the first/last N user+assistant messages of the session as
'bookend_start' / 'bookend_end'. Bookends are skipped when the window
already overlaps the session head or tail, so the response stays tight.
Default bookend=3, keep_roles=('user','assistant'). Tool messages are
dropped from the window EXCEPT the anchor itself (which may legitimately
be a tool message — dropping it would break the contract).
2. session_search mode='guided' switched to get_anchored_view (both primary
path and the child-session rebind fallback). Response shape gains
bookend_start + bookend_end alongside the existing messages array;
single-anchor response mirrors them at the top level for back-compat.
3. session_search mode='fast' now defaults role_filter to 'user,assistant'
when the caller doesn't pass one. Tool messages are mostly noise for
FTS5 (large outputs, serialised tool calls). Callers can opt back in
via role_filter='user,assistant,tool' for debugging or 'tool' for tool
output only.
Schema description updated to document bookends + tool filtering, and the
role_filter param description spells out the new default.
Test coverage:
- tests/hermes_state/test_get_anchored_view.py (12 tests): window/bookend
contract, role filtering, anchor-as-tool preservation, session isolation
- tests/tools/test_session_search.py: existing _make_db fixtures bridged
get_anchored_view → get_messages_around so the old guided tests still
pass; new TestGuidedBookendsInResponse asserts response shape; new
TestFastModeRoleFilterDefault pins the role_filter default.
122/122 passing across tests/hermes_state/ + tests/tools/test_session_search.py.
Single-commit revert-friendly.