Sessions
A session is the lifecycle container for one unit of agent work.
A session routes one agent task into an isolated workspace and records enough metadata to review, promote, discard, extend, or evict it.
Lifecycle
Section titled “Lifecycle”- Consumer creates
GitTrixwith one durable adapter and one ephemeral adapter. - Consumer calls
await gittrix.init(). - Consumer starts a session with
startSession({ task, durablePath?, durableRef?, durableBranch?, eviction? }). - Gittrix records the durable branch head as
baselineSha. - Gittrix initializes an ephemeral workspace from the baseline.
- The agent receives
session.forAgent(). - Agent reads, writes, deletes, lists, diffs, and commits inside the session API.
- User-facing app calls
session.diff()andsession.promote()with selected files or all touched files. - Gittrix checks durable drift against the baseline.
- If selected files overlap durable changes since baseline, promotion fails with
BASELINE_CONFLICT. - If promotion succeeds, Gittrix applies a synthetic durable commit and marks the session
promoted. - If
untilPromoteis enabled, Gittrix evicts the ephemeral workspace after promotion.
flowchart TD Start["startSession()"] --> Baseline["record durable baselineSha"] Baseline --> Workspace["initialize ephemeral workspace"] Workspace --> Agent["AgentSession\nno promote()"] Agent --> Touch["read / write / delete / list / diff / commit"] Touch --> Review["UserSession.diff()"] Review --> Promote["UserSession.promote()"] Promote --> Drift["check durable drift since baseline"] Drift -->|overlap| Conflict["BASELINE_CONFLICT"] Drift -->|no overlap| Commit["durable.applyCommit()"] Commit --> State["state = promoted"] State --> Evict["evict when policy says so"]
Store layout
Section titled “Store layout”Default session store:
~/.gittrix/sessionsSession files:
~/.gittrix/sessions/<session-id>/├── metadata.json├── .lock└── workspace/Mixed remote durable + remote ephemeral sessions may have no durablePath, but can still expose a local ephemeralPath for agent execution.
Metadata
Section titled “Metadata”interface SessionMetadata { metadataVersion: 1 id: string task: string durableRef: string durablePath?: string durableBranch?: string ephemeralRef: string ephemeralPath?: string baselineSha: string workspaceKind?: 'worktree' | 'clone' | 'copy' | 'remote' isGitBacked?: boolean state: 'active' | 'promoted' | 'discarded' | 'expired' createdAt: string updatedAt: string lastAccessAt: string evictionPolicy: { ttlIdleMs: number | null ttlAbsoluteMs: number | null untilPromote: boolean manual: boolean } touchedFiles: string[] promote: { strategy: 'auto' | 'commit' | 'branch' | 'pr' | 'patch' result: { sha: string; branch: string; prUrl?: string } | null }}Example GitHub durable + Cloudflare ephemeral metadata:
{ metadataVersion: 1, id: 'sess_abc123', task: 'update docs', durableRef: 'github://owner/repo#main', durableBranch: 'main', ephemeralRef: 'cloudflare://default/gittrix-eph-sess_abc123', ephemeralPath: '/Users/jack/.gittrix/cf-artifacts-ephemeral/sess_abc123', baselineSha: '<durable-head-sha>', workspaceKind: 'remote', isGitBacked: true, state: 'active', touchedFiles: [], promote: { strategy: 'auto', result: null }}States
Section titled “States”type SessionState = 'active' | 'promoted' | 'discarded' | 'expired'Eviction defaults
Section titled “Eviction defaults”{ ttlIdleMs: 4 * 60 * 60 * 1000, ttlAbsoluteMs: null, untilPromote: true, manual: false,}Default sweep interval:
5 * 60 * 1000AgentSession vs UserSession
Section titled “AgentSession vs UserSession”The user-facing app gets a UserSession, which can review, promote, discard, and extend the session.
The agent gets an AgentSession, which does not expose promote().
const agent = session.forAgent()