# state/ — must-do follow-ups

- Versioned ZIP membership/digest recipe and immutable capture descriptor for
  native-transcript.jsonl (native-transcript-capture.md stage 4). Inventory now
  accepts a sealed snapshot as the transcript member; old publisher ZIPs keep
  implicit history.jsonl. Do not invent descriptors for restored old records.

- process_scope_projection.py callers in spawn_service.py and process_cleanup.py:
  move synchronous projection reads off the async event-loop thread with
  `asyncio.to_thread()`. Reads now have a bounded lock wait, but can still block
  the loop for up to that bound when a projection writer is wedged.
- [#454] state↔ops import cycle for identity migration: user_paths.py
  dynamically imports ops/migration.py, which imports back into state identity;
  legacy-id reading is duplicated in both. #388's B2 already removed the
  lock_held cross-cycle flag and the unlocked writer; the residual is
  structural — move the identity-transition mechanism into a state-owned
  project_identity module and leave ops with only active-spawn policy + CLI
  rendering. (B3)
