Skip to content
Developer Preview

Durability profiles

A host is either durable or ephemeral, for its whole lifetime, for every session it loads and every connection it accepts. Durability is a property of the host, fixed by the party that spawns it — never requested, granted, or negotiated on the wire. A durable host writes each session to a durable log; an ephemeral host writes nothing to the filesystem at all — no log, no lock, no index entry — while every altitude above the log behaves the same way, because the fold was always reading an in-memory log.

The handshake says which profile you got, once, before anything else happens: an optional sessionDurability member on the initialize result. Three reading rules, each load-bearing:

  • Absent means durable. The member is optional because that is what makes the addition additive under the evolution rule; no server that omits it has this profile, so the absent reading is safe rather than fabricated.
  • An unrecognized value is NOT durable. The enum is open, and a client that does not know the value must not infer any durability guarantee from it and must not fall through to the absent-means-durable rule — that rule keys on the member being missing, not on its value being unfamiliar; the conservative read is that nothing survives this host.
  • It is not a capability. Durability is not requestable and not withholdable, so it does not live in the capability vocabulary.

The enum is open so a further value can be added without breaking clients; the field is the additive room, not the answer.

Under the ephemeral value, three methods do not exist on this host for the life of this host — resume, fork, and read — and each answers methodNotFound rather than a capability error, because no reconnection to this host will ever produce them. Listing stored sessions still works, but it is informational: an ephemeral host can page a user’s stored sessions for a picker yet can never open one, and the ephemeral session itself is never listed, because list means stored.

The Session object keeps its shape with one exception: the path is the empty string, meaning no durable log exists — the one value a client must never hand to a filesystem call, unambiguous because no absolute path is empty. The writer lease is never taken, so sessionInUse is unreachable for the ephemeral session.

The profile keeps every in-lifetime guarantee and drops exactly the cross-death ones:

  • Command intake. The intake pair is still written before the ack and is still the idempotency ledger, so every idempotency property holds unchanged within the host’s lifetime; what drops is the durability qualifier — a commandId replayed after host death is not deduplicated, and no client should be replaying one. See commands and idempotency.
  • Item terminals under host death. The terminal guarantee’s host-death exception is normally repaired on the next load; with no next load the exception is permanent, and the repair becomes a client obligation: on abnormal host death, treat every still-open item as terminal-unknown and discard the session.
  • Approval recovery is unreachable. Restart recovery is a load-time replay of durable streams that no longer exist, so pending approvals and user-input prompts end with the host; clients must not implement recovery against the restart contract for an ephemeral host — the recovery they need is the discard above.

Memory is bounded, and the wire already says so

Section titled “Memory is bounded, and the wire already says so”

A long ephemeral session accumulates its log in memory, so an ephemeral host must bound it. When it evicts a prefix, a read anchored inside the evicted range answers with the existing viewTruncated error carrying the earliest cursor — the same typed error a retention-pruned durable session produces, with no new vocabulary. One thing changes: with resume withheld, that truncation is terminal, the earliest cursor is the hard floor of the observable transcript, and the client should surface the truncation rather than presenting a transcript that silently begins in the middle.

session/setApprovalMode stays available, bounded by a ceiling: the sealed startup snapshot, compared under a partial authority order — a process sealed at allowAll may move anywhere and back; one sealed at promptUnmatched may narrow to denyUnmatched and nothing else; onRequest is permanently incomparable with both prompt modes. The same ceiling binds the starting-mode field on session/start: starting in a mode is not a weaker gate than switching to it. Every accepted change still appends a reconfigure audit fact — to the in-memory log — so the session/approvalModeChanged event still arrives and the folded mode still reads correctly.

Turns, steering, interrupts, cancellation, compaction, model selection, the whole view altitude, approvals and user-input prompts within the host’s life, backpressure and gap handling, and the exit-code set all behave identically under either profile. The profile exists for callers that require nothing be written at all; ordinary short-lived work is still just a normal durable session.