Closes the second half of P0-6: once memory injects memory_save / memory_search
into body["tools"] for a session, every subsequent turn injects the byte-equal
same definitions — even if memory is disabled mid-session. Toggling tool list
mid-session busts Anthropic prefix cache per guide §6.3 #2.
Adds in headroom/proxy/helpers.py:
* SessionToolTracker — bounded LRU keyed by (provider, session_id) storing
GOLDEN tool-definition bytes from the first injection. Tracker is
provider-aware so the same session_id under Anthropic and OpenAI keeps
independent state. Reentrant lock for concurrent access; LRU eviction at
HEADROOM_TOOL_TRACKER_MAX_SESSIONS (default 1000).
* apply_session_sticky_memory_tools — single coordination point with three
paths: first-time inject (record golden bytes), sticky replay (always
inject golden bytes regardless of inject_this_turn), and skip. Honors
HEADROOM_TOOL_INJECTION_STICKY=disabled as a loud operator opt-in for
rollback (NOT a fallback).
* serialize_tool_definition_canonical — deterministic byte serialization
via the same separators=(",",":")/ensure_ascii=False rules as
serialize_body_canonical.
* log_tool_injection_decision — structured per-decision log line; never
logs the tool definition contents.
Wires the helper into all four memory tool injection sites:
* handlers/anthropic.py — /v1/messages
* handlers/openai.py — /v1/chat/completions
* handlers/openai.py — /v1/responses
* handlers/openai.py — Codex WS path
memory_handler.MemoryHandler gains compute_memory_tool_definitions(provider) —
a pure builder that returns the tool definitions without mutating a tools
list, so the proxy can route through the sticky tracker. The legacy
inject_tools(...) is preserved for callers without a session_id.
Tests: tests/test_memory_tool_session_sticky.py — 29 unit + integration
cases covering: turn-1→turn-2 byte-equality (Anthropic + OpenAI), sticky
replay after memory disabled, golden-fixture pin, LRU eviction, provider
isolation under shared session_id, thread-safe concurrent access, env-var
contract, disabled-mode passthrough, dedupe with client tools.
Golden fixtures pin canonical bytes:
* tests/fixtures/memory_tool_definitions/anthropic.json
* tests/fixtures/memory_tool_definitions/openai.json
No regex. No hardcodes (env-configurable: HEADROOM_TOOL_INJECTION_STICKY,
HEADROOM_TOOL_TRACKER_MAX_SESSIONS). No silent fallbacks. Per-decision
structured logging. Realignment build constraints satisfied.