RFD D62: Session as a Cross-Client Concept
- Status: Draft
- Category: Design
- Authors: Jean Mertz git@jeanmertz.com
- Date: 2026-08-17
Summary
The word "session" currently fuses two concepts: how a client derives an identity for itself, and a durable cursor from that identity to an active conversation and workspace. The first is terminal-specific; the second appears in every client JP is growing. This RFD proposes defining the cursor as the cross-client concept, treating the CLI's PID-derived identity as its weakest instance rather than its definition.
Motivation
JP is acquiring clients: a web UI in active development, and a macOS client with an iOS counterpart following. Each one has the same requirement the CLI has — this view was working on conversation X in workspace Y, put it back — and each one has a different way of naming a view.
Two things make this worth settling now rather than later.
The term is undefined. docs/architecture/ubiquitous-language.md has entries for Attachment, Conversation, Event, Thread, and Turn. It has no entry for Session, despite sessions being implemented since RFD 020. Three clients are about to need the word at once, with nothing written down.
The CLI's model does not generalize, and it is the weakest of the four. A session identity today is getsid(0) on Unix or GetConsoleWindow() on Windows. Both die with the process. Meanwhile UISceneSession.persistentIdentifier on iOS and window restoration identifiers on macOS survive app relaunch by construction, and a browser tab can mint an identifier and persist it itself. If the concept is defined by the CLI's constraints, the other clients inherit a PID-shaped model that fits none of them — and the one client that cannot restore its own identity sets the ceiling for the ones that can.
Design
Two axes, currently one enum
SessionSource answers "how was this identity derived", and cleanup pattern-matches it to answer two independent questions:
| Source | Liveness checkable | Survives client restart |
|---|---|---|
Getsid | yes | no |
Hwnd | yes | no |
Env | no | depends on the exporter |
| client-supplied (proposed) | no | yes |
Liveness and durability are orthogonal, and policy needs both: whether a record can be reclaimed depends on liveness, whether it is worth keeping depends on durability. A durable-but-unverifiable identity is the exact combination the current enum cannot express, and it is the combination every non-CLI client has.
The concept
A session is an independent client context that tracks its own active conversation and workspace. The client supplies the identity; JP stores the cursor and never tries to derive a durable identity of its own.
Under that definition the terminal-specific derivation in jp_cli::session is one client's implementation of an interface, not the meaning of the term. The CLI keeps its three-layer resolution; a web or Apple client supplies its native scene identifier and gets restoration for free.
Addressing another session
Scoping a command to a session it is not running in mirrors the existing workspace flag: jp -s <key> c use <id>, alongside jp -w.
This has a deliberate tension with RFD 087, which makes jp w use interactive-only on the grounds that scripts should never depend on hidden per-session state. The distinction to argue: 087 objects to implicit resolution, where a script's behavior changes because some terminal picked a different workspace. A key named in argv is the opposite — nothing is ambient. That argument needs to be made explicitly and accepted, not assumed.
Drawbacks
Widening the term commits every client to a shared model before two of the three clients have shipped anything. The model may turn out to fit the web UI's navigation poorly, and by then it is in the glossary.
A client-supplied identity source is unverifiable by construction. JP cannot distinguish a live scene from an abandoned one, so those records rely entirely on retention policy rather than liveness.
Alternatives
Leave session CLI-only, let each client invent its own concept. Cheapest now. The cost is three implementations of the same cursor and three names for it in the glossary, which is the drift the glossary exists to prevent.
Define the concept around the CLI's model and have other clients emulate it. Requires the web and Apple clients to synthesize something PID-shaped, discarding durable identifiers they already have.
Non-Goals
Implementing any client's session handling.
Session record retention and collection. That policy stands on its own and is not blocked on this definition.
Deciding how the web client mints or scopes identities.
Risks and Open Questions
The name. "Session" collides with HTTP and auth sessions the moment the web UI grows a login, which is precisely the one-word-one-concept hazard the glossary guards against. context is free again — it was the earlier user-facing name for what is now a workspace — but it carries two costs: a reader of older material reads "context" as "workspace", and in an LLM tool the word competes with "context window". Neither problem exists for a fresh word.
Does sticky generalize? RFD 087 adds a per-session sticky flag for workspace selection. Whether that concept means anything in a client whose views are already workspace-scoped is unknown.
Do non-CLI clients want history, or only the active pointer? The CLI's most-recent-first history exists to support jp c use - and ?session. A client with visible navigation may have no use for it.
Who owns identity minting for the web client? A tab-scoped identifier in browser storage is durable but trivially forgeable, which matters if a hosted web UI ever serves more than one user.
Implementation Plan
Phase 1 — write the glossary entry. Settle the name and the definition in docs/architecture/ubiquitous-language.md. No code. This is the phase that unblocks the other clients, and it is the phase most likely to change the rest.
Phase 2 — split the source axes. Represent liveness-checkability and durability separately, and derive cleanup policy from both. Behavior-preserving for the three existing sources.
Phase 3 — a client-supplied identity source. Accept a durable opaque identifier from a client, with unknown liveness. Depends on phase 2.
Phase 4 — -s scoping. Only if the argument against RFD 087's stance is accepted.