"""Persist and reload :class:`SessionTrace` as JSONL. A run file is JSON Lines: one ``SessionTrace`` JSON object per line. Appending lets a batch of sessions accumulate into a single file; one CLI ``run`` writes exactly one line. This is the analysis/handoff boundary described in the spec (§7: "세션당 JSONL 1개"). """ from __future__ import annotations from pathlib import Path from proteus.game.runtime.trace import SessionTrace def append_trace(trace: SessionTrace, path: str | Path) -> Path: """Append one ``SessionTrace`` as a JSON line to *path*. Creates parent directories if needed. Args: trace: The session trace to persist. path: Destination ``.jsonl`` file (created/appended). Returns: The :class:`~pathlib.Path` written to. """ path = Path(path) path.parent.mkdir(parents=True, exist_ok=True) with path.open("a", encoding="utf-8") as handle: handle.write(trace.model_dump_json() + "\n") return path def read_traces(path: str | Path) -> list[SessionTrace]: """Read all ``SessionTrace`` records from a JSONL *path*. Blank lines are skipped. Args: path: A ``.jsonl`` file written by :func:`append_trace`. Returns: The traces in file order. """ path = Path(path) return [ SessionTrace.model_validate_json(line) for line in path.read_text(encoding="utf-8").splitlines() if line.strip() ]