3cbeeaa175
Same defect as the compression-rotation fix in the prior commit, found during a full-audit of every create_session() call site per the repo's 'fix the whole bug class, sibling call paths included' contribution guidance. _handle_branch_command() (gateway/slash_commands.py) creates the branched child session via create_session() without chat_id/chat_type/thread_id. The routing columns are only backfilled later, when switch_session() runs at the end of the function and calls _record_gateway_session_peer(). In between, the function copies the parent's conversation history to the new session_id one message at a time, with each append_message() call independently try/excepted (best-effort) — a crash/kill anywhere in that window leaves the branched session permanently unroutable, same failure mode as the compression bug: NULL chat_id/thread_id can never be found by find_latest_gateway_session_for_peer, AND unreachable via /resume's IDOR guard (which requires the row's chat_id/thread_id to match the caller's). Fix: forward source.chat_id/chat_type/thread_id at create_session() time, mirroring the existing correct pattern already used by /title's auto-create path a few hundred lines up in the same file (which has an explicit IDOR-scoping comment justifying it). Tests: tests/gateway/test_branch_routing_columns.py drives the real _handle_branch_command against a real SessionStore + SessionDB (SQLite in tmp_path, no DB/session-store mocks). Patches switch_session to simulate a crash landing before it runs (the exact gap the routing columns need to survive), then asserts the branched child's chat_id/chat_type/thread_id are already correct in state.db at that point. RED verified against unpatched code (assert None == '170829464'), GREEN after the fix. Regression: 102/102 across the new test + pre-existing /branch, session boundary, compression rotation, DM thread seeding, session API, and resume-command suites. Broader tests/gateway/ -k "branch or session_api or resume or topic_mode or session_boundary" sweep: 255/255 passed, 1 (unrelated) skip.