Merge branch 'codex/simp-session-log-representation' into codex/simp-snapshot-fixture-inventory

This commit is contained in:
Tianyi Cui
2026-07-14 14:08:44 +08:00
5 changed files with 16 additions and 8 deletions

View File

@@ -245,7 +245,7 @@ list(): Session[]
fork(source: SessionForkSource, boundary?: number, childSessionId?: SessionId): Session
```
Source: [`packages/core/session/src/index.ts:604`](../../packages/core/session/src/index.ts)
Source: [`packages/core/session/src/index.ts:607`](../../packages/core/session/src/index.ts)
## `ctx.skills` — `SkillService`

View File

@@ -10,7 +10,7 @@ The session log maintains two representations that cost more machinery than thei
The request-header subsystem implements a custom system/tool delta codec and transmission-decision layer even though its contract says deltas are an encoding optimization, not a reconstructability requirement. Retaining the initial/resume full snapshot at each loop-instance boundary, then writing a canonical full `request/header` whenever that instance's assembled header changes, preserves replay while deleting `SystemDelta`, `ToolsDelta`, round-trip fallback, and the durable `request/header-delta` variant. Codec-only vocabulary disappears with the codec, not because its individual arms were invalid.
This proposal deliberately retains append and replacement `sourceEventSeqs`, crash-repair provenance, and all `SessionStartSource` variants: implemented RFCs give those fields an audit/interception role that zero current readers does not overturn.
The implementation retains append and replacement `sourceEventSeqs`, crash-repair provenance, and all `SessionStartSource` variants because those fields have an audit/interception role that zero current readers does not overturn.
## Decision

View File

@@ -214,6 +214,9 @@ function assertSessionEventEnvelope(value: Record<string, unknown>, index: numbe
/** Reject request-header vocabulary removed with the legacy delta codec. */
function assertSupportedRequestHeader(type: string, data: unknown, location: string): void {
if (type === 'request/header-delta') {
throw new Error(`${location} uses unsupported legacy request/header-delta format`)
}
if (type === 'request/header'
&& data !== null && typeof data === 'object' && !Array.isArray(data)
&& (data as Record<string, unknown>)['reason'] === 'fallback') {

View File

@@ -62,11 +62,17 @@ describe('foldRequestHeader', () => {
})
describe('legacy request-header format', () => {
it('rejects a v0 seed containing request/header-delta', () => {
it('rejects request/header-delta in seeds and untyped appends', () => {
const legacy = [{
type: 'request/header-delta', seq: 0, time: 1, data: { config: CONFIG },
}] as unknown as SessionEvent[]
expect(() => new Session(SessionId('legacy'), legacy)).toThrow(/unsupported legacy request\/header-delta/)
const session = new Session(SessionId('legacy-append-delta'))
const appendLegacy = session.append.bind(session) as (type: string, data: unknown) => SessionEvent
expect(() => appendLegacy('request/header-delta', { config: CONFIG }))
.toThrow(/unsupported legacy request\/header-delta/)
expect(session.events).toHaveLength(0)
})
it('rejects the removed fallback reason in seeds and untyped appends', () => {

View File

@@ -185,7 +185,7 @@ describe('SessionPersistence service registration', () => {
await fiber.dispose()
})
it('rejects a legacy header delta buffered by a pre-change live producer', async () => {
it('rejects a legacy header delta from a pre-change live producer', async () => {
const ctx = new Context()
await ctx.plugin(SessionStore)
const fiber = await ctx.plugin(MemoryPersistence)
@@ -193,10 +193,9 @@ describe('SessionPersistence service registration', () => {
// Model the runtime shape available to JavaScript or a hot-loaded plugin
// compiled against the obsolete event vocabulary.
const appendLegacy = session.append.bind(session) as (type: string, data: unknown) => SessionEvent
appendLegacy('request/header-delta', { config: { model: 'legacy' } })
await expect(ctx.sessions.flush(session))
.rejects.toThrow(/unsupported legacy request\/header-delta event at seq 0/)
expect(() => appendLegacy('request/header-delta', { config: { model: 'legacy' } }))
.toThrow(/unsupported legacy request\/header-delta format/)
expect(session.events).toHaveLength(0)
await fiber.dispose()
})