feat(session): refuse session logs a build cannot faithfully read
Old runtimes meeting a newer session format now fail loud instead of misreading: version refusal names the direction (newer: upgrade the harness; older: no upgrade path) and points at the raw JSONL log, and an event type outside the generated known vocabulary refuses resume unless its envelope carries the new ignorable: true marker (default: required, so a forgotten marker over-refuses instead of silently resuming a gutted session). gen-persistence-catalog now also emits KNOWN_SESSION_EVENT_TYPES; SQLite stores the marker in a dedicated column (SCHEMA_VERSION 15). The versioning design (monotonic integer, n->n+1 upgrader chain, migrate-on-continue) is recorded in the session-log-version-mechanism Agent Note.
This commit is contained in:
@@ -32,6 +32,7 @@ export type { ChunkRow, StorageRecord } from './chunk-rows.ts'
|
||||
export type { SessionSurface, SurfaceFoldReplacement, SurfaceFoldResult } from './surface.ts'
|
||||
export { deriveEventMessage, foldSurface, isAppendSurfaceEvent, isReplacementSurfaceEvent, isSurfaceEvent, isSurfaceEligibleType } from './surface.ts'
|
||||
export { canonicalHeader, foldRequestHeader, headerEquals } from './request-header.ts'
|
||||
export { KNOWN_SESSION_EVENT_TYPES } from './known-event-types.ts'
|
||||
|
||||
/**
|
||||
* Find the latest closed turn that entered at least one model step, ignoring
|
||||
@@ -243,6 +244,7 @@ function assertSessionEventEnvelope(value: Record<string, unknown>, index: numbe
|
||||
case 'data':
|
||||
case 'surfaceOp':
|
||||
case 'sourceEventSeqs':
|
||||
case 'ignorable':
|
||||
break
|
||||
default:
|
||||
throw new Error(`seed event at index ${index} has an invalid event envelope`)
|
||||
@@ -254,7 +256,8 @@ function assertSessionEventEnvelope(value: Record<string, unknown>, index: numbe
|
||||
if (typeof type !== 'string'
|
||||
|| typeof seq !== 'number' || !Number.isSafeInteger(seq) || seq < 0
|
||||
|| typeof time !== 'number' || !Number.isSafeInteger(time)
|
||||
|| event['data'] === undefined) {
|
||||
|| event['data'] === undefined
|
||||
|| (event['ignorable'] !== undefined && event['ignorable'] !== true)) {
|
||||
throw new Error(`seed event at index ${index} has an invalid event envelope`)
|
||||
}
|
||||
switch (type) {
|
||||
|
||||
Reference in New Issue
Block a user