import type { WorkflowDefinition, WorkflowDefinitionSnapshot, WorkflowRunManifest, WorkflowRunState, WorkflowSessionBinding, WorkflowSessionCapture, WorkflowSessionEntryRecord, WorkflowSessionEventRecord, WorkflowTraceEvent, WorkflowTraceEventDraft } from "./types.js"; export declare const RUN_BUNDLE_SCHEMA: "pi-workflows.run-bundle.v1"; export declare const RUN_STATE_SCHEMA: "pi-workflows.run-state.v1"; export declare const TRACE_EVENT_SCHEMA: "pi-workflows.trace-event.v1"; export declare const DEFINITION_SNAPSHOT_SCHEMA: "pi-workflows.definition-snapshot.v1"; export declare const SESSION_BINDING_SCHEMA: "pi-workflows.session-binding.v1"; export declare const SESSION_EVENT_SCHEMA: "pi-workflows.session-event.v1"; export declare const SESSION_CAPTURE_SCHEMA: "pi-workflows.session-capture.v1"; export declare const SESSION_EVENT_MAX_BYTES: number; /** Runs directory: `$PI_WORKFLOWS_RUNS_DIR` or `~/.pi/agent/workflows/runs`. */ export declare function workflowRunsBaseDir(homeDir?: string): string; export declare function createRunId(workflowName: string, now?: Date): string; /** * Persists run bundles (see docs/run-bundles.md). `trace.ndjson` is the * append-only source of truth; every transition appends the trace event * first, then atomically replaces `state.json` (carrying `traceSeq`) and * `manifest.json`. Large string leaves in persisted values are externalized * into content-addressed `artifacts/`. Bundles are private: directories are * 0700 and files 0600. */ /** * A fence proves the writer still owns the run. It is checked before every * locked write; it throws (ClaimLostError) when the queue claim was lost, so * a stalled runner can never interleave writes with the new claim holder. */ export type RunFence = () => void; export type WorkflowRunStoreOptions = { fenceProvider?: (runDir: string) => RunFence | undefined; }; export declare class WorkflowRunStore { readonly outputRoot: string; private readonly fenceProvider; private readonly contexts; constructor(outputRoot?: string, options?: WorkflowRunStoreOptions); runDirFor(runId: string): string; quarantineIncompleteRun(runId: string): Promise; private contextFor; private streamFor; /** * Run `task` exclusively for this bundle. Sequence numbers are assigned * inside the lock, so physical file order always matches logical order. */ private withRunLock; private withSessionEventLock; initializeRunBundle(workflow: WorkflowDefinition, state: WorkflowRunState): Promise; /** * Prepare an interrupted bundle for resume. Repairs a torn trace tail, * drops trace events the state projection never recorded, and seeds the * in-process context so new events continue the sequence. The caller must * hold the run's queue claim; the fence is verified before any write. */ prepareRunResume(runId: string): Promise; /** * Finalize captures left "recording" by a session that is gone, so they * report failed with the reason instead of dangling forever. */ private finalizeRecordingCaptures; /** Mark a nonterminal bundle failed and append an interruption event. */ markRunInterrupted(runId: string, reason?: string): Promise; /** * Persist one transition: append the trace event, then rewrite the * projections reflecting it. */ writeSnapshot(runDir: string, state: WorkflowRunState, event: WorkflowTraceEventDraft): Promise; /** * Bind the run to a Pi conversation: write `session/binding.json` once and * append a `session_bound` trace event. Projections catch up on the next * snapshot. */ /** True when a session binding already exists for this bundle. */ hasSessionBinding(runDir: string): Promise; /** List capture segment attempt ids under `session/segments/`. */ listSessionSegments(runDir: string): Promise; writeSessionBinding(runDir: string, binding: WorkflowSessionBinding, attemptId?: string): Promise; /** Append one verbatim Pi session entry to `session/entries.ndjson`. */ appendSessionEntry(runDir: string, entry: Record, attemptId?: string): Promise; /** Append a fully stamped ordered batch to `session/events.ndjson`. */ appendSessionEventBatch(runDir: string, records: WorkflowSessionEventRecord[], attemptId?: string): Promise; /** Atomically replace the temporal capture integrity projection. */ writeSessionCapture(runDir: string, capture: WorkflowSessionCapture, attemptId?: string): Promise; /** Count complete durable session records after both writers have drained. */ sessionCounts(runDir: string, attemptId?: string): Promise<{ eventCount: number; entryCount: number; lastEventSeq: number; }>; private appendTraceEvent; private writeProjections; private writeLoadedProjections; } export type SessionCaptureIntegrity = { status: "unavailable" | "recording" | "complete" | "failed" | "invalid"; diagnostics: string[]; }; /** One capture attempt: the session data a single recorder wrote. */ export type SessionCaptureSegment = { attemptId: string; binding: WorkflowSessionBinding | null; entries: WorkflowSessionEntryRecord[]; events: WorkflowSessionEventRecord[]; capture: WorkflowSessionCapture | null; integrity: SessionCaptureIntegrity; }; export type LoadedRunBundle = { runDir: string; manifest: WorkflowRunManifest; state: WorkflowRunState; snapshot: WorkflowDefinitionSnapshot | null; sessionBinding: WorkflowSessionBinding | null; sessionEntries: WorkflowSessionEntryRecord[]; sessionEvents: WorkflowSessionEventRecord[]; sessionCapture: WorkflowSessionCapture | null; sessionIntegrity: SessionCaptureIntegrity; /** Per-attempt captures written after a handoff or resume. */ sessionSegments: SessionCaptureSegment[]; }; /** Read the final trace record without loading the rest of a run bundle. */ export declare function readLastTraceEvent(runDir: string, tracePath?: string): Promise; /** Read a run bundle from disk. Returns null when the bundle is unreadable. */ export declare function readRunBundle(runDir: string): Promise; /** List run bundles under `outputRoot`, most recently started first. */ export declare function listRunBundles(outputRoot: string): Promise; export declare function createDefinitionSnapshot(workflow: WorkflowDefinition): WorkflowDefinitionSnapshot;