import { type ExecutionLocations, type StatePaths } from '../../core/execution/locations.js'; import type { WorkflowRestartPoint, WorkflowResumePoint } from '../../core/models/index.js'; import { type ProcessIdentity } from './process.js'; import { type DirectoryFingerprint } from '../config/global/projectRegistry.js'; declare const STATE_VERSION = 1; export type CentralTaskStatus = 'pending' | 'starting' | 'running' | 'completed' | 'failed'; export type CentralTaskOrigin = 'web'; export type CentralWorktreeRequest = false | true | string; /** Validated execution intent for the next central run. * * This is deliberately persisted with the task rather than inferred from the * task text. The worker can therefore consume exactly the option selected by * the conversation, even after a process restart. */ export interface CentralExecutionRequest { readonly resumeMode: 'requeue' | 'retry' | 'instruct'; readonly sourceRunSlug?: string; readonly startStep?: string; readonly resumePoint?: WorkflowResumePoint; readonly restartPoint?: WorkflowRestartPoint; readonly retryNote?: string; } export interface CentralStateRecord { readonly version: typeof STATE_VERSION; readonly stateId: string; readonly locationId: string; readonly canonicalDirectory: string; readonly fingerprint?: DirectoryFingerprint; /** The central runs directory is an inode-pinned trust boundary. */ readonly runsRootFingerprint: DirectoryFingerprint; readonly displayName: string; readonly createdAt: string; readonly updatedAt: string; } export interface CentralActiveExecution { readonly executionId: string; readonly runId: string; readonly ownerTokenHash: string; readonly pid: number; readonly processIdentity?: ProcessIdentity; readonly startTime: string; readonly startedAt: string; } /** * A worker that was force-failed is still allowed to finish its process. The * ledger keeps this lease separate from the task status until that worker * acknowledges its terminal state. */ export interface CentralDrainingExecution extends CentralActiveExecution { readonly generation: number; readonly markedAt: string; } /** A requeue requested while the previous worker is still draining. */ export interface CentralRequeueAfterDrain { readonly task: string; readonly requestedAt: string; readonly executionRequest?: CentralExecutionRequest; } export interface CentralTaskFailure { readonly code: string; readonly message: string; readonly at: string; } export interface CentralTaskRecord { readonly taskId: string; readonly generation: number; readonly status: CentralTaskStatus; readonly origin: CentralTaskOrigin; readonly attempt: number; readonly task: string; readonly workflow: string; readonly worktree: CentralWorktreeRequest; /** Exact worktree path owned by this central task after worker setup. */ readonly worktreePath?: string; readonly branch?: string; readonly baseBranch?: string; readonly autoPr?: boolean; readonly draftPr?: boolean; readonly createdAt: string; readonly updatedAt: string; readonly activeExecution?: CentralActiveExecution; readonly drainingExecution?: CentralDrainingExecution; readonly requeueAfterDrain?: CentralRequeueAfterDrain; /** Request consumed by the next claimed run. */ readonly executionRequest?: CentralExecutionRequest; readonly failure?: CentralTaskFailure; /** Latest run pointer retained so workers started before run history support can finish safely. */ readonly runId?: string; readonly runIds: readonly string[]; readonly prUrl?: string; } export interface CentralTaskHandle { readonly task: CentralTaskRecord; /** Raw owner token is kept in memory and may only be handed to the worker through env/private IPC. */ readonly ownerToken: string; readonly executionId: string; readonly runId: string; } export interface CentralTaskLaunchDecision { readonly kind: 'started' | 'reused'; readonly task: CentralTaskRecord; readonly ownerToken?: string; readonly executionId?: string; readonly runId?: string; readonly active?: CentralActiveExecution; } export declare class CentralTaskBusyError extends Error { readonly code = "CENTRAL_TASK_BUSY"; constructor(); } export declare class CentralTaskRequeueError extends Error { readonly code = "CENTRAL_TASK_REQUEUE_INVALID"; } export declare class CentralTaskCasError extends Error { readonly code = "CENTRAL_TASK_CAS_FAILED"; constructor(message?: string); } /** Parse the ledger without creating or repairing any central-state files. */ export declare function parseCentralTasks(value: unknown): readonly CentralTaskRecord[]; export declare class CentralTaskRepository { readonly paths: StatePaths; readonly locations: ExecutionLocations; readonly state: CentralStateRecord; readonly globalConfigDirectory: string; private constructor(); private verifyProjectIdentityUnlocked; /** * Read the persisted state while the ownership lock is held. The repository * snapshot is only an attach-time observation; task CAS must never proceed * if state.json was atomically replaced since that observation. */ private readAndVerifyPersistedIdentityUnlocked; /** Verify the fixed location before starting any central execution work. */ verifyProjectIdentity(): Promise; static open(options: { readonly globalConfigDirectory: string; readonly stateId: string; readonly locationId: string; readonly canonicalDirectory: string; readonly displayName: string; readonly fingerprint?: DirectoryFingerprint; readonly executionDirectory?: string; }): Promise; static openByState(options: { readonly globalConfigDirectory: string; readonly stateId: string; readonly executionDirectory?: string; }): Promise; readTasks(): Promise; readTask(taskId: string): Promise; /** Repair terminal tasks created before worktree context was persisted. */ recoverLegacyWorktreeContexts(): Promise; private writeTasks; /** Enqueue and claim in one state-lock transaction. */ enqueueAndClaim(input: { readonly task: string; readonly workflow: string; readonly worktree: CentralWorktreeRequest; readonly branch?: string; readonly baseBranch?: string; readonly autoPr?: boolean; readonly draftPr?: boolean; readonly origin?: CentralTaskOrigin; }): Promise; /** * Queue a UI task or reuse the currently active UI worker. The decision and * task append share the state lock, so two HTTP requests cannot both spawn. */ enqueueOrReuse(input: { readonly task: string; readonly workflow: string; readonly worktree: CentralWorktreeRequest; readonly branch?: string; readonly baseBranch?: string; readonly autoPr?: boolean; readonly draftPr?: boolean; }): Promise; /** Start another run for one failed task while preserving its execution settings. */ requeueFailedTask(taskId: string): Promise; /** Persist a failed task as pending without claiming it for a worker. */ resetFailedTaskToPending(taskId: string, options?: { readonly task?: string; readonly executionRequest?: CentralExecutionRequest; }): Promise; /** * Start another run for an existing terminal task. The task id and central * run history remain stable; an optional instruction is persisted as the * next run's task text instead of creating a project-local tasks.yaml entry. */ requeueTask(taskId: string, options?: { readonly task?: string; readonly executionRequest?: CentralExecutionRequest; }): Promise; /** Claim exactly one oldest pending task while no active worker exists. */ claimNextPending(): Promise; setStartingPid(input: { readonly taskId: string; readonly generation: number; readonly executionId: string; readonly ownerToken: string; readonly pid: number; readonly runId?: string; }): Promise; /** Persist the worktree/branch selected by the central worker. */ updateExecutionContext(input: { readonly taskId: string; readonly generation: number; readonly executionId: string; readonly ownerToken: string; readonly worktreePath?: string; readonly branch?: string; }): Promise; /** Mark a central task failed from a control-plane action. */ forceFailTask(taskId: string, message?: string): Promise; /** Persist a PR URL without touching project-local task state. */ setPullRequestUrl(taskId: string, prUrl: string): Promise; /** Delete a terminal/pending task and its central run artifacts atomically. */ deleteTask(taskId: string, expectedGeneration?: number, options?: { readonly cleanup?: (task: CentralTaskRecord) => Promise; }): Promise; failStarting(input: { readonly taskId: string; readonly generation: number; readonly executionId: string; readonly ownerToken: string; readonly message: string; }): Promise; /** * Adopt only after the current project identity has been checked while the * state lock is held. An optional precondition hook is kept for callers that * already have an external identity observation; the repository check still * runs afterwards and is authoritative. */ adoptVerified(input: { readonly taskId: string; readonly generation: number; readonly executionId: string; readonly ownerToken: string; readonly pid?: number; }, precondition?: () => Promise): Promise; adopt(input: { readonly taskId: string; readonly generation: number; readonly executionId: string; readonly ownerToken: string; readonly pid?: number; }): Promise; terminal(input: { readonly taskId: string; readonly generation: number; readonly executionId: string; readonly ownerToken: string; readonly status: 'completed' | 'failed'; readonly failure?: { readonly code: string; readonly message: string; }; readonly prUrl?: string; }): Promise; /** Mark dead/reused processes failed; unknown identity is fail-closed and kept live. */ reconcile(): Promise; } export declare function openCentralTaskRepository(options: Parameters[0]): Promise; export {}; //# sourceMappingURL=centralStateRepository.d.ts.map