fix review findings: bump session format version + restore late turn-end warn
Codex review of the trace-event fold found two merge-blockers. Blocker #1 — format version. Folding usage onto assistant/message and removing the standalone usage/error events changed the persisted SessionEventMap shape, which per the AGENTS.md "bump the version and reject — don't migrate" policy requires a backend to reject any non-current log. Centralize the version in an exported SESSION_FORMAT_VERSION constant (dsh-session), read by both write sites (Session constructor default, SessionStore.prepare header) and the coordinator's load-time assertVersion check. The constant is pinned at 0: while unreleased the on-disk format is unstable/pre-release, so breaking shape churn is absorbed at v0 (no monotonic bump until the first tagged release) and any non-0 log is rejected on load — no migration. Update every test/fixture/doc that stamps a currently-written header to the constant, bump the ACP snapshot fixture + golden headers to v0, and keep the version-rejection test meaningful by switching its bad value to a clearly non-current 99. AGENTS.md documents both the monotonic (SQLite SCHEMA_VERSION) and pinned-0 (session log) pre-release stances. Blocker #2 — restore the late turn-end warn. failTurn now sets the error reason only while the turn is still open; once turn/end is appended (a throwing agent/turn-end listener after closeTurn) the reason can no longer reach the durable log, so the late throw is logged via ctx.logger.warn instead of vanishing into a futile post-close assignment. A regression test asserts the warn fires. Also guard the normal-step assistant/message append with the same content-or-usage condition as the max-tokens branch (a content-less, usage-less step records no trace-only row), with a covering test.
This commit is contained in:
@@ -25,7 +25,7 @@ The JSONL durable session-persistence backend — a concrete `SessionPersistence
|
||||
- **Append-only.** Committed events (at or below a flushed `turn/end`) are never rewritten. Subsequent appends are line appends at EOF + `fsync`.
|
||||
- **Crash recovery — close, don't truncate.** A crash can leave a log whose final turn never closed (real events after the last `turn/end`). `load` PRESERVES those events (a turn can be huge — they are real work) and closes the orphaned turn by durably appending synthetic boundary events: an error `tool/result` for every `tool-call` the crash left unanswered (the loop logs the assistant message before running the tools, so a mid-tool crash leaves dangling calls — and `deriveMessages()` would replay an assistant tool-call with no result, which providers reject), then a `step/end` if a step was open, then `turn/end {kind:'interrupted'}`, returning a balanced log. Only a never-fully-written **torn tail fragment** (a final line with no newline / unparseable) is `ftruncate`d away before the closers are written. See [session persistence](../../../docs/rfc/implemented/architecture/2026-06-14-session-persistence.md).
|
||||
- **Contiguous-seq.** `load` rejects a mid-log parse error or `seq` gap (unloadable); `append` rejects a batch whose first `seq` does not continue the stored log, and rejects non-JSON-serializable `event.data` naming the offending event type.
|
||||
- **Format version.** Only v1 is supported; `load` rejects an unknown version. While the harness is unreleased a format change bumps the version and rejects non-current logs — there is no migration (no persisted user data to preserve).
|
||||
- **Format version.** Only the current `SESSION_FORMAT_VERSION` (v0) is supported; `load` rejects any other version. While the harness is unreleased the on-disk format is pre-release/unstable: a breaking format change is absorbed at v0 (no bump until the first tagged release) and non-current logs are rejected — there is no migration (no persisted user data to preserve).
|
||||
|
||||
## Write path
|
||||
|
||||
|
||||
Reference in New Issue
Block a user