import type { EnvelopeVerify } from './documents/envelope.js'; import type { OrgDef, OrgRole } from './types.js'; /** Key for everything a role receives outside a task (and for role scope). */ export declare const ROLE_SESSION_KEY = "_role"; /** Warm state is bounded (Paperclip caps every warm store); so is this history. */ export declare const MAX_SESSION_RUNS = 500; /** 'cold' (ADR-O001 D6): a new model session per message, never resumed. */ export type SessionScope = 'role' | 'task' | 'cold'; export type SessionStartReason = 'resumed' | 'fresh-no-record' | 'fresh-cwd-changed' | 'fresh-prompt-changed' | 'fresh-after-stale-resume' | 'fresh-after-turn-limit' | 'fresh-cold' | 'fresh-rotation'; interface RecordKey { role: string; runtime: string; taskKey: string; } export interface SessionRecord extends RecordKey { sessionId: string; cwd: string; /** Hash of the system prompt the session was built with; '*' matches any. */ promptHash: string; updatedAt?: number; /** Set on every record this build writes: its `runtime` is the resolved * runtime (#562). A record without it predates that and may sit under * 'claude' for a role that runs elsewhere. */ runtimeResolved?: true; } export interface SessionRun extends RecordKey { sessionIdBefore?: string; sessionIdAfter?: string; /** True only when the session id survived the run — the audit's point. */ resumed: boolean; reason: SessionStartReason; startedAt: number; endedAt: number; error?: string; } /** The leading `[task:]` tag decisions.ts puts on every task dispatch. */ export declare function taskKeyOf(text: string): string | undefined; /** The task session a message belongs to, or undefined for "whichever is * current". A dispatch leads with `[task:]`; mail arrives as * `[message from ] subject: ` and is routed by a * `[task:]` in its subject line (task-scoped senders add one), else by * the task whose session last wrote to that sender. The body is never read: * a quoted tag there says nothing about where the message belongs. */ export declare function mailRouteKey(text: string, correspondents: ReadonlyMap, verify?: EnvelopeVerify): string | undefined; /** Every task a message names, in order, once each: the leading `[task:]` * of each dispatch paragraph, and the `[task:]` in a mail's subject line. * Once a mail's head has been seen, what follows is its body until the next * mail head, and a body is never read: a quoted tag says nothing about where * the message belongs. So dispatch paragraphs are read only ahead of any mail, * which is the order dag-dispatch.ts delivers a batch in. */ export declare function messageTaskIds(text: string, verify?: EnvelopeVerify): string[]; /** 'role' (one session for the role's life — the pre-D3 behaviour) unless the * org or the role opts into 'task'. The coordinator's work spans tasks, so an * org-wide 'task' does not apply to it; it can still opt in itself. */ export declare function resolveSessionScope(role: Pick & { session_scope?: SessionScope; review_input?: string; }, def: Pick | undefined): SessionScope; export declare class SessionLedger { private readonly file?; private records; private history; /** `file` omitted = in-memory only (tests, or a daemon with no run dir). */ constructor(file?: string | undefined); /** Which session to resume for this key, or why none can be. * `legacyRuntime`: the runtime an older build filed this key under (#562); * a record found only there, and written by that older build, is moved to * `q.runtime` and used. One this build wrote under `legacyRuntime` belongs * to that runtime's runner (the role's provider or MONOMIND_RUNTIME * changed since) and is never handed to another. */ resumeFor(q: RecordKey & { cwd: string; promptHash: string; legacyRuntime?: string; }): { sessionId?: string; reason: SessionStartReason; }; set(r: SessionRecord): void; drop(k: RecordKey): void; recordRun(run: Omit): SessionRun; runs(): SessionRun[]; private save; } export {}; //# sourceMappingURL=session-ledger.d.ts.map