import type { AgentSlotId } from '../../core/types/thread-types.js'; export type LeaseState = 'parent-writable' | 'draining' | 'thread-owned' | 'answer-frozen' | 'released'; /** Where a given step's backend process is placed. Closed set. */ export type WorkspacePlacement = 'shared-writable' | 'disposable-snapshot'; /** The two coder-review variants whose (variant, slot) pair fixes placement. */ export type CoderReviewVariant = 'audit-retry' | 'reviewer-fix'; export interface WriterIdentity { agentSlotId: AgentSlotId; stepIndex: number; } export interface LeaseView { state: LeaseState; /** null in every state except `thread-owned` while a writer grant is outstanding. */ writer: WriterIdentity | null; /** The one shared writable root. Constant for the trial's lifetime. */ sharedRoot: string; /** Monotonic, incremented on every state change; a stale grant is detected by epoch mismatch. */ epoch: number; } export interface WriterGrant { readonly identity: WriterIdentity; readonly epoch: number; release(): void; } export type WorkspaceLeaseErrorDetail = 'not_thread_owned' | 'writer_already_held' | 'writer_not_held' | 'cwd_outside_grant' | 'drain_precondition_failed' | 'transition_not_implemented'; export declare class WorkspaceLeaseError extends Error { readonly detail: WorkspaceLeaseErrorDetail; constructor(detail: WorkspaceLeaseErrorDetail, message: string); } export interface WorkspaceLease { /** Pure: no filesystem and no name lookup, so a policy guard can read it. */ read(): LeaseView; beginDrain(): void; completeDrain(): void; abortDrain(detail: string): never; /** Arms the next step: fixes its placement and returns the cwd it must run in. Idempotent per * (agentSlotId, stepIndex). Takes a writer grant iff placement is `shared-writable`. */ armStep(input: WriterIdentity & { placement: WorkspacePlacement; }): { cwd: string; grant: WriterGrant | null; }; /** Throws rather than returning false: this runs at a process boundary. */ assertAdmissible(cwd: string): void; freeze(): never; thaw(): never; release(): void; } /** The trial roots a disposable snapshot is placed under. */ export interface TrialSnapshotPaths { root: string; tempDir: string; } /** * Publish the run's lease for the duration of its steps. The per-step trial adapter is built by the * caller that admits the run, which is strictly before the lease exists, so the selector cannot be * handed down as a value — it is read back out of this scope at each spawn-config build * (design section 16 (16.1) LS3). */ export declare function withActiveWorkspaceLease(lease: WorkspaceLease, action: () => Promise): Promise; /** The live lease state. Pure — `read()` performs no filesystem and no name lookup — and total: a * step reached outside a lease scope has no state to select and fails closed. */ export declare function readActiveLeaseState(): LeaseState; export interface WorkspaceLeaseInput { sharedRoot: string; threadId: string; /** null when the run has no trial root — a disposable snapshot is then refused. */ trialPaths: TrialSnapshotPaths | null; /** Live orchestrator counters: processes admitted and supervisor sessions held. */ admission: () => { admitted: number; sessions: number; }; } /** Placement is a function of (variant, slot) and of nothing else — never of a prompt, a template * field or an environment variable. A pair no variant declares has no placement. */ export declare function resolveWorkspacePlacement(variant: CoderReviewVariant, agentSlotId: AgentSlotId): WorkspacePlacement; export declare function assertRecursiveCopySupported(nodeVersion: string): void; export declare function createWorkspaceLease(input: WorkspaceLeaseInput): WorkspaceLease; export interface StepSettlement extends WriterIdentity { stage: string | null; /** The step's terminal assistant message, or null when the step produced none. */ terminalText: string | null; } export interface WorkspaceStepBoundary { /** The cwd this step's backend process must run in. */ resolveStepWorkspace(identity: WriterIdentity): string; /** Runs once per armed step, after its process exited and before the next transition is * evaluated — including on the error path. */ settleStepWorkspace(input: StepSettlement): void; } export interface WorkspaceStepBoundaryInput { lease: WorkspaceLease; placement: (agentSlotId: AgentSlotId) => WorkspacePlacement; /** The thread artifact a snapshot-placed step's terminal message is appended to. */ artifactPath: string; } export declare function createWorkspaceStepBoundary(input: WorkspaceStepBoundaryInput): WorkspaceStepBoundary;