import type { IBridge } from "./bridge.js"; /** * The lock owner ids, re-exported for callers that still import them here. * They live in `lock-owner.ts`, a leaf, for the same reason the verb lexicon * does: this module now imports the tool graph. */ export { SESSION_ID, newLockOwnerId } from "./lock-owner.js"; export interface LockingConfig { enabled: boolean; ttlSeconds: number; } export declare function resolveLockingConfig(cfg?: { enabled?: boolean; ttlSeconds?: number; }): LockingConfig; /** * The verb lexicon this module used to own, re-exported for the callers that * still import it from here. * * It moved to `action-verbs.ts` when locking started reading an action's * DECLARED effect: a lexicon underneath `locking.ts` closes an import cycle the * moment locking imports the tool graph. */ export { READ_PREFIXES, MUTATE_PREFIXES } from "./action-verbs.js"; export interface ActionClassification { mutates: boolean; /** Distinct asset paths this call would mutate (may be empty even when mutating). */ paths: string[]; } /** * Decide whether a task mutates an asset and which asset path(s) it touches. * * The mutation half is the action's DECLARED effect, and `unknown` counts: an * action whose effect its parameters decide may well write the asset it names, * and being wrong costs one serialised call rather than two agents writing the * same package. * * This module used to answer from a verb list of its own and fail OPEN, so an * unrecognised verb ran unlocked. That was the right call while the answer was * a guess, and it is why `unwrap_uvs` and `fixup_redirectors` never took a * lock: neither verb was in the list, and nothing said so out loud. The answer * is not a guess any more, so there is nothing left to fail open about, and a * name this server does not carry gets the same `mutate` default every other * gate gives it. * * An unextractable path still yields an empty list, so a declared mutation that * names no asset runs unlocked exactly as before. That is what keeps this from * locking the world: the path, not the verdict, is the narrow part. */ export declare function classifyAction(taskName: string, params: Record): ActionClassification; /** * Run `run` while holding exclusive locks on every asset path the task would * mutate. On a busy asset, throws a retryable ASSET_LOCKED error. If the lock * subsystem is unreachable (older plugin without the handlers, bridge down), * fails open and runs unlocked. */ export declare function withAssetLocks(bridge: IBridge, cfg: LockingConfig, taskName: string, params: Record, run: () => Promise, /** Who holds the locks. The addressed editor's id; omitted means this process. */ ownerId?: string): Promise;