docs(run-journal): specify live-only metering and optional writes (#7272)

This commit is contained in:
laitekin committed 2026-09-21 23:03:24 +08:00
1 parent 87338e8098
commit 9b3c749302
2 files changed
+27 -2

No files matched your search

+1 -1
View File
@@ -454,7 +454,7 @@ class RunJournalWriter:
self._path = _run_path(self.session_id, self.run_id, session_dir=self.session_dir)
self._lock = _lock_for(self._path)
def append_sse_event(self, event_name: str, payload=None) -> dict:
def append_sse_event(self, event_name: str, payload=None) -> dict | None:
# Live-UI-only telemetry (metering) has no recovery value in the journal:
# nothing reads those rows back for recovery, and journaling them at ~10 Hz
# on marathon runs balloons the durable file (12+ MB of a single 18 MB run
+26 -1
View File
@@ -183,7 +183,7 @@ when integrating with the live chat SSE relay.
| `cancel` | Run cancelled |
| `done` | Turn finalized (session payload); title/`stream_end` may follow |
| `stream_end` | SSE fence — close the client EventSource |
| `metering` | Token/cost metering snapshot |
| `metering` | Best-effort live token/cost metering snapshot; not journal-replayed |
| `context_status` | Context window / usage status |
| `goal` | Goal / plan card update |
| `goal_continue` | Goal continuation signal |
@@ -228,6 +228,31 @@ A future implementation must replay from the run journal via the existing
`_replay_run_journal()` path (in `api/routes.py`) and fall back to the
snapshot mechanism when journal entries are unavailable for a given cursor.
### Live-only metering (implemented replay behavior)
`metering` is best-effort live telemetry, not durable recovery content.
`RunJournalWriter.append_sse_event()` returns `None` for metering without
writing a row or allocating a sequence number. Other journaled events retain
contiguous sequence numbers. Local-agent and gateway producers carry an
explicit per-frame event ID, including `None`, through `StreamChannel`;
an unjournaled metering frame emits no new SSE `id:` and must not borrow the
previous frame's journal ID. The last-ID fallback is limited to legacy
two-element queue entries.
Existing journals are not rewritten. Direct readers (`read_run_events()` and
`read_session_run_events()`) retain legacy metering rows for cursor validation
and gap/coverage checks. Both run-level and per-session journal replay emitters
apply `journal_replay_visible()` to omit those rows from reconnect delivery.
Consequently, replayed legacy event IDs can have gaps where metering was
filtered; clients must not infer missing durable content from those gaps.
Metering missed while disconnected is not recovered from the journal; fresh
live updates remain available. This exception does not remove token, reasoning,
tool, or terminal events from durable replay.
Coverage: `tests/test_run_journal.py`, `tests/test_run_journal_routes.py`,
`tests/test_issue4812_session_sse_stream.py`, and
`tests/test_stage364_opus_live_sse_event_id.py`.
## Snapshot fallback
When the `Last-Event-ID` cursor is evicted, expired, unknown, or refers to a