"""Regression tests for cross-session transcript isolation in loadSession.

The checks lock behavior at both levels:

1) Structural guard checks in ``loadSession()`` and ``_ensureMessagesLoaded()``
   around ownership tokens and catch-path mutations.
2) Runtime ordering/catch coverage using an executable Node harness to reproduce
   old->new load overlap and stale rejected continuation behavior.
"""

from __future__ import annotations

import json
import re
import shutil
import subprocess
from pathlib import Path

import pytest


REPO = Path(__file__).resolve().parents[1]
SESSIONS_SRC = (REPO / "static" / "sessions.js").read_text(encoding="utf-8")
NODE = shutil.which("node")


def _extract_function(source: str, name: str) -> str:
    """Return the full function source for ``name`` from a single js file.

    Brace-depth tracking handles nested blocks and avoids fragile substring
    matching in the large, hand-formatted source file.
    """
    marker = f"async function {name}("
    start = source.find(marker)
    if start < 0:
        marker = f"function {name}("
        start = source.find(marker)
    assert start >= 0, f"{name} not found in sessions.js"

    brace_start = source.find("{", start)
    assert brace_start >= 0, f"function {name} is missing '{{'"

    depth = 0
    in_string = None
    escaped = False
    in_line_comment = False
    in_block_comment = False

    for index in range(brace_start, len(source)):
        ch = source[index]
        nxt = source[index + 1] if index + 1 < len(source) else ""

        if in_line_comment:
            if ch == "\n":
                in_line_comment = False
            continue
        if in_block_comment:
            if ch == "*" and nxt == "/":
                in_block_comment = False
            continue
        if in_string:
            if escaped:
                escaped = False
            elif ch == "\\":
                escaped = True
            elif ch == in_string:
                in_string = None
            continue

        if ch == "/" and nxt == "/":
            in_line_comment = True
            continue
        if ch == "/" and nxt == "*":
            in_block_comment = True
            continue
        if ch in ('\'', '"', "`"):
            in_string = ch
            continue

        if ch == "{":
            depth += 1
        elif ch == "}":
            depth -= 1
            if depth == 0:
                return source[start : index + 1]

    raise AssertionError(f"Could not extract function {name}")


LOAD_SESSION_SRC = _extract_function(SESSIONS_SRC, "loadSession")
ENSURE_MESSAGES_LOADED_SRC = _extract_function(SESSIONS_SRC, "_ensureMessagesLoaded")
INFLIGHT_HAS_VISIBLE_STATE_SRC = _extract_function(SESSIONS_SRC, "_inflightHasVisibleLiveState")
SELECT_LIVE_RECOVERY_INFLIGHT_SRC = _extract_function(SESSIONS_SRC, "_selectLiveRecoveryInflight")
MERGE_PENDING_SESSION_MESSAGE_SRC = _extract_function(SESSIONS_SRC, "_mergePendingSessionMessage")


def _normalise_ws(s: str) -> str:
    return re.sub(r"\s+", "", s)


def test_loadsession_has_generation_token_and_forwards_to_ensure_messages_loaded():
    body = LOAD_SESSION_SRC
    assert "_loadSessionGeneration" in body, (
        "loadSession() must use a global generation counter so superseded loads "
        "can be rejected by continuation ownership checks"
    )
    assert "const _loadGeneration = ++_loadSessionGeneration" in body, (
        "loadSession() must increment and capture per-call generation"
    )
    assert "const _isCurrentLoad = () => _loadingSessionId === sid && _loadSessionGeneration === _loadGeneration" in body
    assert "loadGeneration:_loadGeneration" in body, (
        "loadSession() must thread generation into _ensureMessagesLoaded()"
    )
    # Guard each await/catch branch so stale continuation cannot mutate shared pane state.
    # Two calls exist in this function: INFLIGHT and idle branches.
    norm = _normalise_ws(body)
    assert norm.count("if(!_isCurrentLoad())") >= 6, (
        "loadSession() should check ownership in multiple await/catch paths, "
        "including stale _ensureMessagesLoaded catch branches"
    )
    ensure_call = _normalise_ws("await _ensureMessagesLoaded(sid, {force:_keepStaleUntilLoaded, loadGeneration:_loadGeneration});")
    assert ensure_call in norm, (
        "loadSession() must pass generation into _ensureMessagesLoaded() for stale-owner checks"
    )
    assert (
        "showToast('Failed to load session" in LOAD_SESSION_SRC
        or "showToast('Failed to load conversation messages" in LOAD_SESSION_SRC
    ), "loadSession() should preserve toast-based failure paths"


def test_ensure_messages_loaded_ownership_guard_pre_and_post_await():
    body = ENSURE_MESSAGES_LOADED_SRC
    assert "_loadSessionGeneration" in body, "_ensureMessagesLoaded should read generation"
    assert "const _loadGeneration = Number.isFinite(opts.loadGeneration) ? Number(opts.loadGeneration) : null" in body
    norm = _normalise_ws(body)
    assert (
        "_loadGeneration===null||_loadSessionGeneration===_loadGeneration" in norm
    ), "_ensureMessagesLoaded must compare generation token"
    assert norm.count("if(!_ownsLoad())return;") >= 2, (
        "_ensureMessagesLoaded needs pre/post await ownership guards"
    )
    assert "_loadGeneration" in body, "_ensureMessagesLoaded should read generation from opts"


_NODE_SCRIPT_TEMPLATE = r'''
function makeHarness() {
  const apiCalls = [];
  const queue = [];
  const pending = [];
  function enqueue(url, value, mode="resolve") {
    const defer = { url: String(url), value, mode, resolved: false };
    defer.promise = new Promise((resolve, reject) => {
      defer._resolve = resolve;
      defer._reject = reject;
    });
    queue.push(defer);
    return defer;
  }

  async function api(url) {
    apiCalls.push(String(url));
    const entry = queue.shift();
    if (!entry) {
      throw new Error('Unexpected API call: ' + String(url));
    }
    if (entry.url !== String(url)) {
      throw new Error('API order mismatch, expected ' + entry.url + ', got ' + String(url));
    }
    pending.push(entry);
    return entry.promise;
  }

  return { api, apiCalls, enqueue, pending };
}

function snapshotState() {
  return {
    sid: S.session && S.session.session_id,
    messages: Array.isArray(S.messages) ? S.messages.map((m) => (m && m.role ? String(m.content || '') : null)).filter(Boolean) : [],
    toolCalls: Array.isArray(S.toolCalls) ? S.toolCalls.slice() : [],
    truncated: _messagesTruncated,
    oldestIdx: _oldestIdx,
    loadingSid: _loadingSessionId,
    loadingGeneration: _loadSessionGeneration,
    msgInner: _msgInner.innerHTML,
    toastCalls: toastCalls.slice(),
    rearmCalls,
    apiCalls: apiHost.apiCalls.slice(),
    clearHintCalls,
    visibleCacheClears,
    liveCardClears,
    toolSyncCalls,
  };
}

function createEnvironment() {
  globalThis.INFLIGHT = {};
  globalThis.S = {
    session: { session_id: 'sid-init', message_count: 0 },
    messages: [{ role: 'assistant', content: 'seed' }],
    toolCalls: [],
    pendingFiles: [],
    busy: false,
    activeStreamId: null,
  };
  globalThis._loadingSessionId = null;
  globalThis._loadingOlder = false;
  globalThis._loadSessionGeneration = 0;
  globalThis._pendingCarryForwardSnapshot = null;
  globalThis._messagesTruncated = false;
  globalThis._oldestIdx = 0;
  globalThis._messageRenderWindowSize = 0;
  globalThis._messageReloadLimitForSession = () => 2;
  // sessions.js module-level const, referenced by _ensureMessagesLoaded's
  // boundedReloadLimit ceiling check (#6152/#6154). Not one of the extracted
  // functions, so define it in the harness (matching the real value) or the
  // reload-width path resolves it as undefined -> boundedReloadLimit=null ->
  // the fetch URL drops msg_limit/expand_renderable and mismatches the
  // enqueued buildMessageUrl(), stalling the ordered api() harness.
  globalThis._MSG_LIMIT_MAX = 500;
  // #6177: _msgLimitMax is a module-scope `let` (live server-advertised ceiling,
  // defaulting to _MSG_LIMIT_MAX). It's read by _ensureMessagesLoaded's
  // boundedReloadLimit and _loadOlderMessages's useBeforePaging; the harness
  // injects only the extracted functions, not module-level lets, so define it
  // here or those reads resolve undefined -> wrong fetch URL -> ordered-api stall.
  globalThis._msgLimitMax = 500;
  globalThis._currentMessageRenderWindowSize = () => 1;
  globalThis._messageRenderableMessageCount = () => 2;

  globalThis._rearmActiveSessionStream = () => { rearmCalls += 1; };
  globalThis.stopApprovalPolling = () => {};
  globalThis.hideApprovalCard = () => {};
  globalThis.stopSessionStream = () => {};
  globalThis._yoloEnabled = false;
  globalThis._updateYoloPill = () => {};
  globalThis.stopClarifyPolling = () => {};
  globalThis.hideClarifyCard = () => {};
  globalThis._saveComposerDraftNow = () => Promise.resolve();
  globalThis._sessionProfileMismatchFromError = () => null;
  globalThis._switchProfileForSessionLoad = async () => {};
  globalThis._clearSameSessionForceReloadHint = () => { clearHintCalls += 1; };
  globalThis._clearStuckSessionOnBoot = () => {};
  globalThis._setSessionViewedCount = () => {};
  // #4946: loadSession() now routes its viewed-count/unread clear through
  // _acknowledgeSessionVisit(). This harness exercises cross-session load
  // ordering + stale-reject, not unread-dot state, so stub it (and its
  // same-session-guard predicate) to no-ops — mirroring the pre-existing
  // _setSessionViewedCount / _clearSessionCompletionUnread stubs it replaced.
  globalThis._acknowledgeSessionVisit = () => {};
  globalThis._sessionVisitHasUnreadState = () => false;
  globalThis.scheduleTodosRefresh = () => {};
  globalThis.startSessionStream = () => {};
  globalThis.syncTopbar = () => {};
  globalThis._captureSameSessionForceReloadHint = () => {};
  globalThis._resolveSessionModelForDisplaySoon = () => {};
  globalThis._setSessionCompletionUnread = () => {};
  globalThis._clearSessionCompletionUnread = () => {};
  globalThis._setActiveSessionUrl = () => {};
  globalThis._deferWorkspaceRefreshForSession = () => {};
  globalThis._sessionListRender = () => {};
  globalThis._setSessionToolset = () => {};
  globalThis._applyPendingSessionModelForSession = () => {};
  globalThis.populateModelDropdown = () => {};
  globalThis._deferSessionSideEffect = (sid, fn) => Promise.resolve(fn());
  globalThis._hydrateTodosFromSession = () => {};
  globalThis._resolveLineage = () => {};
  globalThis._clearPendingSelections = () => {};
  globalThis._clearQueueCardDisplay = () => {};
  globalThis._syncTodosForSession = () => {};
  globalThis._clearAllTodosFromSession = () => {};
  globalThis._setSessionModelFromSession = () => {};
  globalThis._clearEmptyComposerModelOverride = () => {};
  globalThis._deferSessionProfileSwitch = () => {};
  globalThis._resolveSessionSideEffect = () => {};


  globalThis._clearMessageCache = () => {};
  globalThis._syncToolCallsForLoadedMessages = (msgs, toolCalls) => {
    toolSyncCalls += 1;
    S.toolCalls = [];
    if (Array.isArray(toolCalls)) {
      S.toolCalls = toolCalls.map((tc) => ({ ...tc, done: true }));
    }
  };
  globalThis.clearVisibleMessageRowCache = () => { visibleCacheClears += 1; };
  globalThis.clearLiveToolCards = () => { liveCardClears += 1; };

  globalThis._syncCtxIndicator = () => {};
  globalThis._renderPendingPromptsForActiveSession = () => {};
  globalThis._restoreComposerDraft = () => {};
  globalThis.renderSessionArtifacts = () => {};
  globalThis.renderMessages = () => {};
  globalThis._checkAndShowHandoffHint = () => {};
  globalThis._hideHandoffHint = () => {};
  globalThis._isMessagingSession = () => true;
  globalThis._clearDeferredActiveSessionExternalRefresh = () => {};

  globalThis.setStatus = () => {};
  globalThis.setComposerStatus = () => {};
  globalThis.setBusy = () => {};
  globalThis.updateSendBtn = () => {};
  globalThis.updateQueueBadge = () => {};
  globalThis.startApprovalPolling = () => {};
  globalThis.startClarifyPolling = () => {};
  globalThis._fetchYoloState = () => {};

  globalThis._resolveSessionIdFromSidebarLineage = (sid) => sid;
  globalThis._resolveSessionLineage = (sid) => sid;

  globalThis._messageReloadLimitForSession = () => 2;

  globalThis._msgInner = { innerHTML: 'INIT_LOADING' };
  const _msgInput = { value: '' };
  globalThis.$ = (id) => {
    if (id === 'msgInner') return _msgInner;
    if (id === 'msg') return _msgInput;
    return null;
  };

  globalThis.autoResize = () => {};
  globalThis.showToast = (msg) => {
    toastCalls.push(String(msg));
  };

  globalThis.window = {};
  globalThis.history = { replaceState: () => {} };
  globalThis.localStorage = {
    removeItem: () => {},
    setItem: () => {},
    getItem: () => null,
  };
  globalThis._appRootPath = () => '/';

  rearmCalls = 0;
  clearHintCalls = 0;
  visibleCacheClears = 0;
  liveCardClears = 0;
  toolSyncCalls = 0;
  toastCalls = [];
}

let rearmCalls = 0;
let clearHintCalls = 0;
let visibleCacheClears = 0;
let liveCardClears = 0;
let toolSyncCalls = 0;
let toastCalls = [];

// Source under test
__INFLIGHT_HAS_VISIBLE_STATE_SRC__
__SELECT_LIVE_RECOVERY_INFLIGHT_SRC__
__MERGE_PENDING_SESSION_MESSAGE_SRC__
__LOAD_SESSION_SRC__
__ENSURE_MESSAGES_LOADED_SRC__

async function waitForQueued(apiHost, url) {
  const target = String(url);
  while (!apiHost.pending.some((entry) => entry.url === target)) {
    await Promise.resolve();
  }
}

const API_BEACON_META = {
  session: {
    session_id: 'sid-beacon',
    message_count: 12,
    active_stream_id: null,
    resolve_model: 'qwen/qwq-32b-instruct',
  },
};

const API_BEACON_MSGS = {
  session: {
    session_id: 'sid-beacon',
    _messages_truncated: true,
    _messages_offset: 7,
    messages: [{ role: 'assistant', content: 'stale-beacon-transcript' }],
    message_count: 12,
    tool_calls: [{ name: 'tool-beacon-stale' }],
  },
};

const API_BEACON_INFLIGHT_STATE = {
  messages: [
    {
      role: 'assistant',
      content: 'beacon-inflight-tail',
      _live: true,
    },
  ],
  uploaded: [],
  toolCalls: [{ name: 'tool-beacon-inflight' }],
};

const API_ATLAS_META = {
  session: {
    session_id: 'sid-atlas',
    message_count: 21,
    active_stream_id: null,
    resolve_model: 'qwen/qwq-32b-instruct',
  },
};

const API_ATLAS_MSGS = {
  session: {
    session_id: 'sid-atlas',
    _messages_truncated: false,
    _messages_offset: 98,
    messages: [{ role: 'assistant', content: 'new-active-transcript' }],
    message_count: 21,
    tool_calls: [{ name: 'tool-atlas' }],
  },
};

const API_ATLAS_RELOAD_META = {
  session: {
    session_id: 'sid-atlas',
    message_count: 31,
    active_stream_id: null,
    resolve_model: 'qwen/qwq-32b-instruct',
  },
};

const API_ATLAS_RELOAD_MSGS = {
  session: {
    session_id: 'sid-atlas',
    _messages_truncated: true,
    _messages_offset: 33,
    messages: [{ role: 'assistant', content: 'reloaded-active-transcript' }],
    message_count: 31,
    tool_calls: [{ name: 'tool-atlas-new' }],
  },
};

function buildMessageUrl(sid, mode, suffix='') {
  const base = `/api/session?session_id=${encodeURIComponent(sid)}&messages=${mode}&resolve_model=0`;
  if (mode === 0) return base;
  return `${base}&msg_limit=${_messageReloadLimitForSession()}&expand_renderable=1${suffix}`;
}

function makeCrossSessionCalls(apiHost) {
  return {
    beaconMeta: apiHost.enqueue(buildMessageUrl('sid-beacon', 0)),
    beaconMsgs: apiHost.enqueue(buildMessageUrl('sid-beacon', 1)),
    atlasMeta: apiHost.enqueue(buildMessageUrl('sid-atlas', 0)),
    atlasMsgs: apiHost.enqueue(buildMessageUrl('sid-atlas', 1)),
  };
}

function runCrossSessionOrderingBase({seedBeaconInflight, resolveBeaconMsgsBeforeAtlasMeta}) {
  createEnvironment();
  if (seedBeaconInflight) {
    INFLIGHT['sid-beacon'] = JSON.parse(JSON.stringify(API_BEACON_INFLIGHT_STATE));
  }

  const apiHost = makeHarness();
  globalThis.apiHost = apiHost;
  globalThis.api = apiHost.api;

  const calls = makeCrossSessionCalls(apiHost);

  const first = loadSession('sid-beacon', { force: true });
  return (async () => {
    await waitForQueued(apiHost, calls.beaconMeta.url);
    calls.beaconMeta._resolve(API_BEACON_META);

    await waitForQueued(apiHost, calls.beaconMsgs.url);
    const second = loadSession('sid-atlas', { force: true });
    await waitForQueued(apiHost, calls.atlasMeta.url);

    if (resolveBeaconMsgsBeforeAtlasMeta) {
      calls.beaconMsgs._resolve(API_BEACON_MSGS);
      // Wait for the stale first load continuation to process so we can continue the
      // Atlas path from a clearly stale state.
      await first;
      calls.atlasMeta._resolve(API_ATLAS_META);
      await waitForQueued(apiHost, calls.atlasMsgs.url);
    } else {
      calls.atlasMeta._resolve(API_ATLAS_META);
      await waitForQueued(apiHost, calls.atlasMsgs.url);
      calls.beaconMsgs._resolve(API_BEACON_MSGS);
    }

    calls.atlasMsgs._resolve(API_ATLAS_MSGS);
    await Promise.all([first, second]);

    return {
      finalSid: S.session && S.session.session_id,
      messages: snapshotState().messages,
      toolCalls: snapshotState().toolCalls,
      truncated: snapshotState().truncated,
      oldestIdx: snapshotState().oldestIdx,
      msgInner: snapshotState().msgInner,
      toastCalls: snapshotState().toastCalls,
      apiCalls: snapshotState().apiCalls,
      loadingSid: snapshotState().loadingSid,
      loadingGeneration: snapshotState().loadingGeneration,
      rearmCalls: snapshotState().rearmCalls,
    };
  })();
}

async function runCrossSessionOrdering() {
  return {
    scenario: 'cross-session-ordering',
    ...(await runCrossSessionOrderingBase({ seedBeaconInflight: true, resolveBeaconMsgsBeforeAtlasMeta: false })),
  };
}

async function runObservedIdleCrossSessionOrdering() {
  return {
    scenario: 'observed-idle-cross-session-ordering',
    ...(await runCrossSessionOrderingBase({ seedBeaconInflight: false, resolveBeaconMsgsBeforeAtlasMeta: true })),
  };
}

async function runStaleRejectedIdleCatch() {
  createEnvironment();
  const apiHost = makeHarness();
  globalThis.apiHost = apiHost;
  globalThis.api = apiHost.api;

  S.session = { session_id: 'sid-atlas', message_count: 0 };

  const calls = {
    firstMeta: apiHost.enqueue(buildMessageUrl('sid-atlas', 0)),
    firstMsgs: apiHost.enqueue(buildMessageUrl('sid-atlas', 1)),
    secondMeta: apiHost.enqueue(buildMessageUrl('sid-atlas', 0)),
    secondMsgs: apiHost.enqueue(buildMessageUrl('sid-atlas', 1)),
  };

  const first = loadSession('sid-atlas', { force: true });
  calls.firstMeta._resolve(API_ATLAS_META);

  // Ensure the first load has entered the messages fetch and owns the pending API
  // call before the superseding same-session load begins.
  await waitForQueued(apiHost, calls.firstMsgs.url);

  const second = loadSession('sid-atlas', { force: true });

  // The stale first request rejects while the second newer request is in flight.
  calls.firstMsgs._reject(new Error('owner lost while load was in-flight'));
  calls.secondMeta._resolve(API_ATLAS_RELOAD_META);
  calls.secondMsgs._resolve(API_ATLAS_RELOAD_MSGS);

  await Promise.all([first, second]);

  return {
    scenario: 'stale-idle-catch',
    finalSid: S.session && S.session.session_id,
    messages: snapshotState().messages,
    toolCalls: snapshotState().toolCalls,
    truncated: snapshotState().truncated,
    oldestIdx: snapshotState().oldestIdx,
    msgInner: snapshotState().msgInner,
    toastCalls: snapshotState().toastCalls,
    apiCalls: snapshotState().apiCalls,
    loadingSid: snapshotState().loadingSid,
    loadingGeneration: snapshotState().loadingGeneration,
    rearmCalls: snapshotState().rearmCalls,
  };
}

async function runAll() {
  return {
    crossSessionOrdering: await runCrossSessionOrdering(),
    observedIdleCrossSessionOrdering: await runObservedIdleCrossSessionOrdering(),
    staleIdleCatch: await runStaleRejectedIdleCatch(),
  };
}

runAll()
  .then((r) => console.log(JSON.stringify(r)))
  .catch((err) => {
    console.error('NODE_ERROR', err && err.stack || err);
    process.exit(1);
  });
'''


def _run_node(script: str, tmp_path: Path) -> dict:
    assert NODE is not None, "node is required"
    script_path = tmp_path / "cross-session-message-load-isolation.mjs"
    script_path.write_text(script, encoding="utf-8")
    completed = subprocess.run(
        [NODE, str(script_path)],
        cwd=str(REPO),
        text=True,
        capture_output=True,
        timeout=60,
        check=False,
    )
    assert completed.returncode == 0, completed.stderr or completed.stdout
    output_lines = [line.strip() for line in completed.stdout.splitlines() if line.strip()]
    assert output_lines, f"node produced no parseable output\nstdout={completed.stdout}\nstderr={completed.stderr}"
    return json.loads(output_lines[-1])


@pytest.mark.skipif(NODE is None, reason="node not on PATH")
def test_loadsession_cross_session_ordering_and_stale_reject_behavior(tmp_path):
    script = (
        _NODE_SCRIPT_TEMPLATE.replace(
            "__INFLIGHT_HAS_VISIBLE_STATE_SRC__", INFLIGHT_HAS_VISIBLE_STATE_SRC
        )
        .replace(
            "__SELECT_LIVE_RECOVERY_INFLIGHT_SRC__", SELECT_LIVE_RECOVERY_INFLIGHT_SRC
        )
        .replace(
            "__MERGE_PENDING_SESSION_MESSAGE_SRC__", MERGE_PENDING_SESSION_MESSAGE_SRC
        )
        .replace("__LOAD_SESSION_SRC__", LOAD_SESSION_SRC)
        .replace("__ENSURE_MESSAGES_LOADED_SRC__", ENSURE_MESSAGES_LOADED_SRC)
    )
    body = _run_node(script, tmp_path)

    cross = body["crossSessionOrdering"]
    stale = body["staleIdleCatch"]
    observed = body["observedIdleCrossSessionOrdering"]

    def _assert_atlas_wins(session_result, *, label):
        assert session_result["finalSid"] == "sid-atlas", f"{label}: stale overlap should end on Atlas session"
        assert session_result["messages"] == ["new-active-transcript"], (
            f"{label}: stale Beacon transcript must not replace Atlas transcript"
        )
        assert session_result["toolCalls"] == [{"name": "tool-atlas", "done": True}], (
            f"{label}: Atlas tool summary must apply on fresh load"
        )
        assert session_result["truncated"] is False and session_result["oldestIdx"] == 98, (
            f"{label}: Atlas metadata should remain the active state"
        )

    # 1) Cross-session ordering: old (Beacon) loads first, but user advances to Atlas.
    assert cross["apiCalls"][0] == "/api/session?session_id=sid-beacon&messages=0&resolve_model=0", (
        "first API call should target old session's metadata"
    )
    assert cross["apiCalls"][1] == "/api/session?session_id=sid-beacon&messages=1&resolve_model=0&msg_limit=2&expand_renderable=1", (
        "beacon transcript request should queue before atlas metadata resolves"
    )
    assert cross["apiCalls"][2] == "/api/session?session_id=sid-atlas&messages=0&resolve_model=0", (
        "second API call should target atlas metadata while stale beacon messages are in flight"
    )
    assert cross["apiCalls"][3] == "/api/session?session_id=sid-atlas&messages=1&resolve_model=0&msg_limit=2&expand_renderable=1", (
        "atlas should still fetch a transcript while beacon was stale"
    )
    assert cross["apiCalls"].count("/api/session?session_id=sid-beacon&messages=1&resolve_model=0&msg_limit=2&expand_renderable=1") == 1, (
        "stale overlap should still issue the Beacon transcript call, but it must not win"
    )
    _assert_atlas_wins(cross, label="cross-session-ordering")

    # 2) Observed idle-path race with no INFLIGHT: stale Beacon transcript returns
    #    before Atlas metadata, but ownership guard must still force Atlas fetch+swap.
    assert observed["apiCalls"][0] == "/api/session?session_id=sid-beacon&messages=0&resolve_model=0", (
        "idle-path race should start from old Beacon metadata"
    )
    assert observed["apiCalls"][1] == "/api/session?session_id=sid-beacon&messages=1&resolve_model=0&msg_limit=2&expand_renderable=1", (
        "Beacon transcript call should remain queued before Atlas metadata under observed race"
    )
    assert observed["apiCalls"][2] == "/api/session?session_id=sid-atlas&messages=0&resolve_model=0", (
        "Atlas metadata must start while Beacon continuation returns stale"
    )
    assert observed["apiCalls"][3] == "/api/session?session_id=sid-atlas&messages=1&resolve_model=0&msg_limit=2&expand_renderable=1", (
        "Atlas transcript request must still issue despite stale Beacon return"
    )
    assert observed["apiCalls"].count("/api/session?session_id=sid-beacon&messages=1&resolve_model=0&msg_limit=2&expand_renderable=1") == 1, (
        "stale Beacon transcript should occur once in observed race"
    )
    assert observed["apiCalls"].count("/api/session?session_id=sid-atlas&messages=1&resolve_model=0&msg_limit=2&expand_renderable=1") == 1, (
        "Atlas transcript must be issued once once stale Beacon is processed first"
    )
    _assert_atlas_wins(observed, label="observed-idle-cross-session-ordering")
    assert observed["toastCalls"] == [], "stale Beacon return in idle-path race should not show toast"

    # 3) Stale rejected idle-branch catch must be ownership-guarded and not mutate shared pane.
    assert stale["messages"] == ["reloaded-active-transcript"], "stale catch must not keep stale transcript"
    assert stale["toolCalls"] == [{"name": "tool-atlas-new", "done": True}], "stale catch must not overwrite tool state"
    assert stale["truncated"] is True and stale["oldestIdx"] == 33, "active owner should install latest metadata"
    assert stale["msgInner"] == "INIT_LOADING", (
        "stale reject from superseded load must not write failure placeholder"
    )
    assert stale["toastCalls"] == [], "stale reject must not surface toast for superseded load"
    assert stale["apiCalls"].count(
        "/api/session?session_id=sid-atlas&messages=1&resolve_model=0&msg_limit=2&expand_renderable=1"
    ) == 2, "both old and active loads should have attempted message fetch"

    assert cross["loadingSid"] is None, "load marker should be cleared after successful completion"
    assert stale["loadingSid"] is None, "load marker should be cleared after stale reject + re-owner completion"
