# TASK-159-04-01: Session Capability State Model And Persistence Split

**Parent:** [TASK-159-04](./TASK-159-04_Session_Capabilities_Modularization_And_Guided_State_Boundaries.md)
**Status:** ✅ Done
**Priority:** 🔴 High

## Objective

Separate the session-capability dataclasses, normalization helpers, and sync/async
persistence seam from the rest of `session_capabilities.py` while keeping the
module import facade stable, including the already-shipped `guided_handoff`,
`guided_flow_state`, `gate_plan`, `reference_understanding_summary`, and
`reference_understanding_gate_ids` state envelope.

## Repository Touchpoints

- `server/adapters/mcp/session_capabilities.py`
- likely new helper module such as `server/adapters/mcp/session_capabilities_state.py`
- `server/adapters/mcp/session_state.py`
- `tests/unit/adapters/mcp/test_guided_flow_state_contract.py`
- `tests/unit/adapters/mcp/test_context_bridge.py`
- `tests/unit/adapters/mcp/test_session_phase.py`
- `tests/unit/router/application/test_router_contracts.py`

## Current Code Anchors

- `SessionCapabilityState`
- `GuidedReferenceReadinessState`
- `SESSION_GUIDED_HANDOFF_KEY`
- `_normalize_guided_flow_state(...)`
- `_normalize_gate_plan(...)`
- `_normalize_reference_understanding_summary(...)`
- `_normalize_reference_understanding_gate_ids(...)`
- `get_session_capability_state(...)`
- `get_session_capability_state_async(...)`
- `set_session_capability_state(...)`
- `set_session_capability_state_async(...)`

## Planned Code Shape

```python
from .session_capabilities_state import (
    SessionCapabilityState,
    get_session_capability_state,
    set_session_capability_state,
)

state = SessionCapabilityState(
    guided_handoff=...,
    guided_flow_state=...,
    gate_plan=...,
    reference_understanding_summary=...,
    reference_understanding_gate_ids=...,
)
```

## Runtime / Security Contract Notes

- keep current session-key vocabulary, normalization rules, and no-cross-session
  leakage guarantees
- preserve paired sync/async persistence behavior
- do not change which session keys are written or how typed contracts are rebuilt
  from raw session storage
- do not drop, rename, or silently stop normalizing `guided_handoff`,
  `reference_understanding_summary`, or
  `reference_understanding_gate_ids` while extracting the persistence seam

## Tests To Add/Update

- `tests/unit/adapters/mcp/test_guided_flow_state_contract.py`
- `tests/unit/adapters/mcp/test_context_bridge.py`
- `tests/unit/adapters/mcp/test_session_phase.py`
- `tests/unit/router/application/test_router_contracts.py`

## Validation Commands

- `PYTHONPATH=. poetry run pytest tests/unit/adapters/mcp/test_guided_flow_state_contract.py tests/unit/adapters/mcp/test_context_bridge.py tests/unit/adapters/mcp/test_session_phase.py tests/unit/router/application/test_router_contracts.py -q`

## Docs To Update

- inherit parent docs closeout unless session-state ownership wording changes

## Changelog Impact

- include in the parent `TASK-159` changelog entry when shipped

## Acceptance Criteria

- state model and persistence helpers have a bounded home outside the monolith
- session serialization/deserialization semantics remain unchanged
- the extracted state seam still owns `guided_handoff`,
  `reference_understanding_summary`, and `reference_understanding_gate_ids` as
  part of the same canonical persisted envelope
- the facade still exports the same state access functions used elsewhere in the
  repo

## Status / Board Update

- keep promoted tracking on parent `TASK-159`

## Completion Summary

Completed on 2026-05-04.

- moved the canonical session envelope, session-key constants, normalization
  helpers, and sync/async persistence functions into
  `server/adapters/mcp/session_capabilities_state.py`
- kept `guided_handoff`, `guided_flow_state`, `gate_plan`,
  `reference_understanding_summary`, `reference_understanding_gate_ids`, and
  `guided_part_registry` inside the same persisted session contract
- preserved the facade exports for `get_session_capability_state(...)`,
  `get_session_capability_state_async(...)`,
  `set_session_capability_state(...)`, and
  `set_session_capability_state_async(...)`
