import type { TopicPlacement } from './PlacementExecutor.js';
/** One persisted pin: the resolved target machine + when it was set. */
export interface TopicPin {
    preferredMachine: string;
    pinned: boolean;
    updatedAt: string;
}
export interface TopicPlacementPinStoreDeps {
    /** File the pins persist to (JSON). */
    filePath: string;
    /** Wall clock — injectable for tests. Defaults to `Date`. */
    now?: () => Date;
}
export declare class TopicPlacementPinStore {
    private readonly d;
    private pins;
    private loaded;
    constructor(deps: TopicPlacementPinStoreDeps);
    private load;
    private persist;
    /** Pin a topic to a machine (a hard pin). Idempotent; refreshes `updatedAt`. */
    set(sessionKey: string, preferredMachine: string, pinned?: boolean): void;
    /** The current pin for a topic, or null if unpinned. */
    get(sessionKey: string): TopicPin | null;
    /**
     * The pin as a `TopicPlacement` for `PlacementExecutor.decide({ topicMetadata })`,
     * or undefined if unpinned (so the caller passes `topicMetadata: undefined`).
     */
    asTopicMetadata(sessionKey: string): TopicPlacement | undefined;
    /** When the topic's pin was last set (ms epoch), or null if unpinned — feeds the transfer rate-limit guard. */
    lastUpdatedAtMs(sessionKey: string): number | null;
    /** Remove a topic's pin (e.g. the user unpins, or the target is decommissioned). */
    clear(sessionKey: string): void;
    /** All current pins (for diagnostics / GET surfaces). */
    all(): Record<string, TopicPin>;
}
//# sourceMappingURL=TopicPlacementPinStore.d.ts.map