@signalridge/pi-sessions1.3.0
Human-reviewed session navigation and summary handoffs for Pi.
Untested on omp
This is a pi package. No one has reported whether it works on omp yet. If you try it, add your result below.
Reports 0
No reports yet.
Readme
@signalridge/pi-sessions
Experimental, opt-in human-controlled session navigation and editable summary handoffs. Tested with Pi 1.0.4; host packages are peers, not bundled. MIT, independent implementation. This is not Plan mode's approved-plan implementation action.
Try explicitly with pi -e ./packages/pi-sessions/src/index.ts. This package is not enabled by default. Session mutations are human-command-only, never model-callable.
Commands
/sessions: list sessions whose native workspace matches the active workspace./sessions all: explicitly include other workspaces from Pi's default session store and the current configured session directory.- Filter by name, stable session ID or workspace; select to inspect bounded metadata and recent user/assistant text. Confirm before native switching. There is no delete or rename operation. The native selector includes deletion, so this package uses a bounded independent picker.
/handoff <goal>: optionally ask the currently selected model to synthesize a goal-oriented summary. An omitted goal opens human input.recoveras the complete argument is reserved for recovery, not a goal; write a descriptive goal such asrecover interrupted workinstead./handoff recover: explicitly inspect the approved summary saved on the current branch, review/edit it, then separately confirm replacing the current unsent draft. No automatic recovery overwrite, new session or model turn.
TUI and dialog-capable RPC are supported. Print/JSON commands are rejected before authentication, provider requests or session mutations. RPC clients must implement confirm/input/select/editor. Pi 1.0.4 exposes neither RPC draft epochs nor conditional editor writes: clients must reject stale consent and preserve client-local drafts. The latest destination Yes explicitly authorizes draft replacement; a newer client-local draft alone cannot revoke it on the server.
Sharing and handoff
Generation is opt-in for every invocation. Only at most 16 KiB UTF-8 of the most recent 12 user/assistant text messages is offered; each message is capped at 2 KiB. Tool results/arguments, images, thinking, system messages, custom entries, compaction summaries and credential objects are not copied. Common credential patterns are redacted, but prose may still contain secrets: inspect/redact the exact excerpt in the multiline editor before a second sharing confirmation. The goal (at most 2 KiB) is also sent to that selected model. No upload/share service is used.
Authentication/generation failures produce a generic message, never raw provider errors, and offer a manual summary editor. Declining generation also offers a manual editor, not a fake generated summary. Escape cancels live TUI loading/generation; requests time out after 60 seconds. Ownership retirement aborts our requests and closes only our overlays. RPC pending-editor results are fenced when retired (the host has no editor cancellation API).
Review/edit the summary in a multiline editor. TUI text and complete bracketed-paste payloads are sanitized before native insertion, including split paste markers and native-supported CSI-u pasted controls: sanitization does not move the insertion cursor or add dirty Undo snapshots. Native cursor movement, Kitty printable keys, CJK/IME and atomic paste Undo are retained. Large pastes are immediately expanded into the reviewable document, never hidden behind paste markers; Undo restores the pre-paste document and earlier editing history. Approval preserves exact leading/trailing whitespace, not Pi 1.0.4's trimmed submit callback. Choice/picker controls honor configured tui.select.* actions and show their bindings. Approved text must be nonempty, terminal-safe and at most 16 KiB UTF-8; oversized approved text is rejected, never truncated. Explicit draft-replacement consent and final creation confirmation precede native newSession({ parentSession, setup, withSession }).
The destination saves pi-sessions:handoff version 1 as a non-model custom entry with the approved summary, goal and parent identity. Its optional prefill intent stores the source model identity and, for TUI only, the SHA256 hash of the explicitly consented source unsent draft—never the raw unsent draft. RPC cannot read that draft and stores no draft hash. Older records without intent remain explicitly recoverable, but never auto-prefill.
After native setup, the destination controller's session_start with reason new owns prefill under the same interaction lock and lifecycle fences as commands. The source withSession callback only reports setup/model warnings, without asynchronous dialogs or editor writes. The destination first vets its current file: the exact custom entry ID/data and native parent link must be durably present, not just in memory after failed setup. It revalidates before writing the editor. RPC requires fresh destination consent; TUI only replaces an empty editor or the consented source draft matching its saved hash. Later TUI drafts are preserved. A missing/different destination model is reported, not submitted to. Nothing sends a message, starts a turn or invokes implementation; you decide whether and when to send the draft.
Native storage and recovery
The native session manager remains authoritative; no parallel session-history database is kept. Pi 1.0.4 defers custom-only file persistence until the first user/assistant message. To make the reviewed handoff durable before that first turn, setup writes the public native header and entries to a unique, exclusive 0600 JSONL file, then reloads it using public setSessionFile. It never adds a synthetic model-context message.
An existing saved source file is reused as the linked parent only when every exact active-branch record is present and reopening it selects that same leaf; a native tree-selected ancestor or sibling branch receives its own snapshot instead. If a nonempty source has no saved file (including an allocated-but-unwritten path), or its otherwise valid file is stale, its active native branch and native parent link are cloned into a unique private 0600 snapshot with a new ID in a private temporary directory. The old file is never overwritten; malformed existing storage is rejected, not silently bypassed. A cancelled/vetoed/failed pre-replacement creation removes this snapshot. Once native replacement begins it is retained, even if later setup/rebinding/prefill fails, so the source remains resumable by the parent path. In-memory destinations also receive a native recovery file; their later conversation remains subject to the host's no-session policy. Retained temporary parent/recovery files survive reload, but OS temporary-directory cleanup can eventually remove them; retain important source sessions in normal persistent storage.
This record/leaf comparison is a preflight check, not a promise that a reused native parent is immutable. Later native source appends can advance its history while replacement hooks are pending or after it is resumed. Observable source changes during preflight revoke editor-prefill authorization; native replacement and its live parent link may still proceed with recovery-only data. A private snapshot records the captured branch when created, rather than reusing a stale or differently selected source file.
Setup/prefill errors never start a model turn. Missing, unreadable or mismatched durable handoff data prevents automatic prefill. If source approval is revoked during a later asynchronous before-switch handler, native replacement may still proceed: setup retains the summary/parent for explicit recovery but strips prefill intent. Only a still-current source owner can carry approval across expected replacement shutdown. The initiated replacement's expected before-switch exemption is single-use: any subsequent delivered attempt revokes approval, including another new-session or same-target resume attempt later vetoed by another extension. Independent human attempts are not blocked by this revocation. If setup failed, resume the native parent and retry. If the summary was saved but prefill failed, /handoff recover can inspect it after reload. Startup, reload, resume and fork never consume prefill intent or automatically modify the editor; recovery remains explicit.
Workspaces and limits
Actual Pi 1.0.4 runtime switching opens the session header workspace and recreates cwd-bound services there; it does not change the process's global cwd. Cross-workspace selection requires a separate explicit warning/confirmation. After switching we report both history workspace and the actual fresh context's tool/resource workspace. A host retaining its execution workspace is reported as restoring history only; this package never patches private cwd state. Missing workspaces are rejected before switching rather than invoking a private fallback.
Every candidate is revalidated immediately before native switching: path, native header ID/cwd, JSONL tree and original-byte content digest must still match the preview. Preflight checks native restoration payloads, including usage/cost numbers, system sections/tool deltas and role-appropriate persisted content, then runs public nonmutating context projection, system replay and token estimation before source teardown. Supported v2 entries (including historical hookMessage) are migrated on an in-memory clone only. Reads stop at 32 MiB plus one oversize probe byte even if a file grows, and check cancellation between chunks. Detected unreadable/malformed data is rejected without opening or repairing its native manager. Validation accepts supported native v2/v3 payloads with entries up to 4 MiB; unsupported/older/oversized files can still be opened with Pi's own facilities. Arbitrary extension-owned custom data remains opaque; preflight is not a proof that every third-party renderer or external filesystem writer is safe. Invalid discovery metadata is skipped per row rather than hiding the valid collection. Preview text is inert and excludes non-user/assistant content. Preview is capped at 6 KiB, retained rows at 200, and visible rows adapt to the terminal while reserving controls. Undersized terminals require resizing before approval. Terminal controls/bidi instructions are stripped; CJK and narrow widths are supported in regular/fullscreen UI.
Pi's SDK list/listAll may load full session bodies and return all results. These calls do not promise bounded memory. Limits above bound this package's retained display data, not SDK memory or disk scan work. Abort signals are passed to SDK list operations.
Ownership captures the manager/session identity, full native active-branch fingerprint (including latest entry data), model identity and TUI draft/editor-factory identity. Observable changes retire the operation permanently; switching back does not revive approval. All await boundaries are checked, including after authentication and destination consent. While destination RPC consent is pending, /sessions and /handoff report the existing interaction warning. Fences cover delivered lifecycle events and observable state, not every attempted host action. Delivered native switch/tree/fork/compact attempts (including vetoes after our observer), shutdown, agent start or model selection retire that consent; a late Yes cannot revive retired ownership. Pi 1.0.4 short-circuits on an earlier extension's veto, so our observer may never receive that attempt. An unchanged branch/model and an invisible RPC draft provide no substitute signal. RPC clients must reject stale consent and preserve local drafts; the latest Yes explicitly authorizes replacement. Stronger guarantees require host-level non-short-circuiting attempt observation and draft epoch/conditional-write support. Source and destination ownership are runtime-local and do not rely on shared event buses. Async TUI generation completion also requires its owned overlay to remain focused; a newer foreign dialog retires continuation instead of losing focus. This package does not install a custom main editor/footer or restore stale editor snapshots.
Development
bun run --cwd packages/pi-sessions check runs lint, typecheck and native-SDK/unit tests. Tests do not require provider credentials and assert no destination model turn.