import type { DurableJournal } from "@claudexor/journal"; import type { Attachment, ContinuityDisclosure, LaneCheckpoint, Session, Thread, ThreadTurn, TurnEnqueueProblem, WorkspaceMode } from "@claudexor/schema"; export interface CreateThreadInput { title?: string; repoRoot?: string | null; mode?: Thread["mode"]; /** in_place (default) mutates the live tree; isolated keeps a thread worktree. */ workspace?: WorkspaceMode; authPreference?: Thread["auth_preference"]; credentialProfileId?: string | null; /** Sticky write scope for write turns (null/omit = repo trust default). */ access?: Thread["access"]; primaryHarness?: string | null; /** Sticky eligible harness pool for the thread (turns inherit when unset). */ eligibleHarnesses?: string[]; idempotency?: { key: string; client: string; request: unknown; }; } export interface CreateTurnInput { kind?: ThreadTurn["kind"]; parentRunId?: string | null; answersPlanRunId?: string | null; planRunId?: string | null; /** Freeze-on-implement provenance (D17): sha256 of the implemented plan. */ planHash?: string | null; planOverridden?: boolean; /** Files/images attached to this turn, already resolved to scoped on-disk paths. */ attachments?: Attachment[]; idempotency?: { key: string; client: string; request: unknown; }; } export interface UpdateThreadInput { title?: string; state?: "active" | "closed"; /** Switch the sticky primary harness (null => clear back to auto). */ primaryHarness?: string | null; /** Switch the thread's sticky credential profile (null => engine default). */ credentialProfileId?: string | null; /** Replace the sticky eligible harness pool. */ eligibleHarnesses?: string[]; /** Switch the sticky write scope (null => repo trust default). */ access?: Thread["access"]; } /** * Sink for the content-free `thread.head.updated` invalidation ping (W12). * Bound at composition time to the GLOBAL-partition emitter, so a mutation in * a project partition still reaches the app's single global stream. */ export type ThreadHeadPingSink = (ping: { threadId: string; projectId: string | null; }) => void; /** Journal-backed thread/session projection. Returned mutations are fsynced. */ export declare class ThreadStore { private readonly journal; private readonly headPing?; private state; private readonly turnIdByKey; private readonly threadIdByKey; constructor(journal: DurableJournal, headPing?: ThreadHeadPingSink | undefined); validateProjection(): void; private replay; private commit; /** * Emit the content-free head-invalidation ping for one thread. The owning * partition name is this store's journal partition — the single source of * the thread->project mapping. */ pingHead(threadId: string): void; private apply; createThread(input: CreateThreadInput): Thread; /** Rename and/or open/close (archive) a thread. */ updateThread(id: string, patch: UpdateThreadInput): Thread; trashThread(id: string): Thread; restoreThread(id: string): Thread; purgeThread(id: string): Thread; private changeLifecycle; /** Persist the resolved isolated worktree path + base sha for a thread. */ setThreadWorktree(id: string, worktreePath: string, baseSha: string, deliveredThroughRunId?: string): void; listThreads(): Thread[]; getThread(id: string): Thread | undefined; turnsFor(threadId: string): ThreadTurn[]; getTurn(turnId: string): ThreadTurn | undefined; /** * Fail-loud prologue for the daemon runner: control-api validates thread/turn * ids at the HTTP boundary, but a direct socket caller can pass bogus ids — * a silent unbind would orphan the run from its conversation. A typed throw * settles the job `failed` instead. Returns the normalized ids. */ assertKnownIds(rawThreadId: unknown, rawTurnId: unknown): { threadId?: string; turnId?: string; }; sessionsForThread(threadId: string): Session[]; /** Native resume map for a thread: harnessId -> native session id (live sessions only). */ resumeMap(threadId: string, profileId?: string | null): Record; createTurn(threadId: string, prompt: string, input?: CreateTurnInput): ThreadTurn; findTurnByIdempotency(threadId: string, input: NonNullable): ThreadTurn | undefined; /** Bind a started run to its turn and advance the thread head (runner-owned). */ bindTurnRun(turnId: string, runId: string): void; /** * Persist the reason a turn's run could NOT be enqueued/started (trust * refusal, preflight validation, enqueue throw). Only meaningful for a * RUNLESS turn: once a run is bound the turn's honesty lives on the run's * own terminal artifacts, so a late failure report is ignored. One typed * object carries code, retryability, recovery actions, and bounded context; * adding a field cannot silently fall out of a positional callback chain. */ setTurnEnqueueError(turnId: string, problem: TurnEnqueueProblem): void; /** Record/refresh a harness's native session; see `makeSessionRecord` (INV-135). */ recordSession(threadId: string, harnessId: string, nativeSessionId: string, observedModel?: string | null, profileId?: string | null): void; /** Advance a lane's checkpoint to `turnId` (INV-137): the lane * (thread, harness, profile) has now SEEN that turn. Same (harness, profile) * key as `resumeMap`, so the next turn's packet math is exact. */ recordLaneCheckpoint(threadId: string, harnessId: string, profileId: string | null, turnId: string): void; /** The last turn a lane has seen, or null when the lane never ran. */ laneCheckpoint(threadId: string, harnessId: string, profileId: string | null): string | null; /** All lane checkpoints of a thread (used to identify the prior head's lane). */ laneCheckpointsForThread(threadId: string): LaneCheckpoint[]; /** Stamp how a turn's lane was continued (INV-137); last-writer-wins. */ setTurnContinuity(turnId: string, disclosure: ContinuityDisclosure): void; relinkProjectRoot(root: string): void; /** D-U1 order 2 / INV-137 unified-accounts readers and mutations — the * derivation contracts live in thread-lane-checkpoints.ts. */ accountBindings(threadId: string): Record; resumeMapAuto(threadId: string): Record; migrateNullProfileContinuity(harnessId: string, rowId: string): { sessions: number; checkpoints: number; }; rollbackProfileContinuity(harnessId: string, rowId: string): { sessions: number; checkpoints: number; }; private applyContinuityMutation; invalidateCredentialProfile(harnessId: string, profileId: string): { clearedThreads: number; invalidatedSessions: number; }; } export declare function threadProjection(headPing?: ThreadHeadPingSink): { name: string; create: (journal: DurableJournal) => ThreadStore; validate: (store: ThreadStore) => void; }; //# sourceMappingURL=threads.d.ts.map