Resume a session: update bootstrap identity, restore cost, reconstruct the per-conversation record from disk. Ch03 round-2 (R2.2): single entry point that keeps the three operations in lockstep (CC-34 single-setter discipline at the resume layer). Callers (REPL ``/re
(cls, session_id: str)
| 117 | |
| 118 | @classmethod |
| 119 | def resume(cls, session_id: str) -> Optional['Session']: |
| 120 | """Resume a session: update bootstrap identity, restore cost, |
| 121 | reconstruct the per-conversation record from disk. |
| 122 | |
| 123 | Ch03 round-2 (R2.2): single entry point that keeps the three |
| 124 | operations in lockstep (CC-34 single-setter discipline at the |
| 125 | resume layer). Callers (REPL ``/resume``, headless / SDK) |
| 126 | should use this rather than calling ``Session.load`` plus |
| 127 | ``switch_session`` plus ``restore_cost_state_for_session`` |
| 128 | independently. |
| 129 | |
| 130 | Order matters: ``switch_session`` fires BEFORE |
| 131 | ``restore_cost_state_for_session`` so any subscriber that reads |
| 132 | ``get_session_id()`` during the cost restore sees the loaded id. |
| 133 | """ |
| 134 | from src.bootstrap.state import SessionId, switch_session |
| 135 | from src.services.cost_restore import restore_cost_state_for_session |
| 136 | |
| 137 | loaded = cls.load(session_id) |
| 138 | if loaded is None: |
| 139 | return None |
| 140 | switch_session(SessionId(session_id)) |
| 141 | restore_cost_state_for_session(session_id) |
| 142 | return loaded |
| 143 | |
| 144 | |
| 145 | def _snapshot_cost_block() -> dict: |