Skip to content

fix: resume sessions across client restarts instead of orphaning them#427

Merged
BYK merged 1 commit into
mainfrom
fix/session-id-stability
May 20, 2026
Merged

fix: resume sessions across client restarts instead of orphaning them#427
BYK merged 1 commit into
mainfrom
fix/session-id-stability

Conversation

@BYK
Copy link
Copy Markdown
Owner

@BYK BYK commented May 20, 2026

Summary

When an AI agent (OpenCode, etc.) restarts, it regenerates its session header value (e.g. x-session-affinity nanoid). The gateway's Tier 1 identification treated this as a brand-new session, orphaning all prior distillations, gradient calibration, and cache warming state. This caused cold starts, wasted tokens, and fragmented conversation logs.

Changes

  • OpenCode plugin (packages/opencode/src/index.ts): Injects stable x-lore-session-id using OpenCode's persistent DB session ID (input.sessionID) which survives restarts
  • Header priority (packages/gateway/src/session.ts): Reorders KNOWN_SESSION_HEADERS so x-lore-session-id (always stable, deterministic) is checked before volatile headers like x-session-affinity
  • Tier 1a cross-header migration (packages/gateway/src/pipeline.ts): When a new higher-priority header appears (e.g. plugin upgrade starts sending x-lore-session-id), checks lower-priority headers for an existing session and re-indexes under the new header — prevents session orphaning on upgrade
  • Tier 1b rotation detection (packages/gateway/src/pipeline.ts, session.ts): When a known header name is present but its value is unrecognized, scans for exactly one recent non-subagent predecessor session with the same header name. If found, resumes it. Extracted as a pure findRotationPredecessor() function for testability
  • Remove sessions.has() gate: DB-only sessions (after gateway restart) are now found via the header index without requiring in-memory hydration first
  • Fix lastTurnAt=0 false staleness: Sessions where gradient never ran are treated as recently active, not infinitely stale
  • 12 new tests (packages/gateway/test/session.test.ts): Header priority, rotation happy path, concurrent sessions, sub-agent exclusion, stale session exclusion, boundary conditions

Safety Guards (Tier 1b)

  • Sub-agents excluded — they carry independent session affinity values
  • Multiple predecessors → ambiguous (concurrent sessions) → new session created
  • Stale sessions (>24h since last activity) → skipped
  • Works after gateway restart (uses DB fallback for session lookup)

@BYK BYK self-assigned this May 20, 2026
When an AI agent (OpenCode, etc.) restarts, it regenerates its session
header value (e.g. x-session-affinity nanoid). Previously, the gateway's
Tier 1 identification treated this as a brand-new session, orphaning all
prior distillations, gradient calibration, and cache warming state.

Four coordinated fixes:

1. OpenCode plugin injects stable x-lore-session-id using OpenCode's
   persistent DB session ID (survives restarts).

2. Reorder KNOWN_SESSION_HEADERS so x-lore-session-id (always stable)
   is checked before volatile headers like x-session-affinity.

3. Add Tier 1a cross-header migration: when a new higher-priority
   header appears (plugin upgrade), check lower-priority headers for
   an existing session and re-index under the new header.

4. Add Tier 1b rotation detection in the gateway: when a known header
   name is present but its value is unrecognized, scan for exactly one
   recent non-subagent predecessor session with the same header name.
   If found, resume it instead of creating a new session.

Also fixes:
- Remove sessions.has() gate in Tier 1 so DB-only sessions (after
  gateway restart) are found without requiring in-memory hydration.
- Treat lastTurnAt=0 as 'recently active' (gradient never ran yet)
  instead of infinitely stale in rotation candidate evaluation.
@BYK BYK force-pushed the fix/session-id-stability branch from 66a760b to 8574178 Compare May 20, 2026 13:27
@BYK BYK merged commit 9395526 into main May 20, 2026
10 checks passed
@BYK BYK deleted the fix/session-id-stability branch May 20, 2026 13:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant