/**
 * `FileWatcher` — chokidar-backed file-change trigger source (AUTO.5).
 *
 * Authoritative source: `docs/tasks/automation.md` AUTO.5. Watches the glob
 * paths a skill declares in `triggers: [{kind: 'file_changed', paths: [...]}]`
 * and emits `FileChangedEvent` into the runtime evaluator.
 *
 * Per-skill granularity (mirrors `ScheduleEntry`): one watcher per skill
 * that declares a `file_changed` trigger. 50 packs × 5 watchers ≈ 250
 * instances; acceptable for v1 per spec risk callout.
 *
 * Locked behaviors (spec):
 *   - Debounce 200ms per `(changeKind, path)` — collapses editor write
 *     bursts WITHOUT merging unlink+add (rename) into one event.
 *   - `awaitWriteFinish` {stabilityThreshold: 100, pollInterval: 50} —
 *     suppresses partial-write events (atomic save / IDE auto-save).
 *   - Default `ignored`: `['**\/node_modules/**', '**\/.git/**']`.
 *   - Rate-limit gate (AUTO.2): `rateLimiter.check(pack, 'file_changed',
 *     path)` runs BEFORE every dispatch; denial drops + audits.
 *     `release()` is the evaluator's job (out of scope for AUTO.5).
 *
 * Fail-closed (constraint C10): `dispatch` errors + chokidar backend
 * errors audit as `file_changed_error`. No silent swallows.
 *
 * Lifecycle:
 *   - `start()` opens chokidar with `ignoreInitial: true` so existing
 *     files don't generate startup `add` events. Listeners attach for
 *     `add` / `change` / `unlink` / `error`.
 *   - `stop()` awaits `watcher.close()` and clears every pending debounce
 *     timer. After `stop()` resolves, no further dispatch can race in.
 *     Idempotent; restart after stop throws (programmer error).
 *
 * Engine-vocabulary: returns `(pack, skill, path)` + `FileChangedEvent`.
 * No consumer-product names leak into this module.
 *
 * Imports from: chokidar, ../event.js, ../rate_limit.js.
 * Imported by: ./index.ts (registry barrel) + the daemon.
 */
import type { FileChangedEvent } from '../event.js';
import type { RateLimiter } from '../rate_limit.js';
export interface FileWatcherConfig {
    /** Pack identifier — passed to the rate limiter + audit sink. */
    pack: string;
    /** Skill identifier — included in audit entries for provenance. */
    skill: string;
    /** Glob paths from `skill.triggers[].paths`. */
    paths: string[];
    /** Glob paths to exclude. Defaults to node_modules + .git below. */
    ignored?: string[];
    /** Per-`(kind, path)` debounce window. Defaults to 200ms (spec). */
    debounceMs?: number;
    /** Test seam — usePolling forces chokidar's polling backend (CI / Docker). */
    usePolling?: boolean;
}
type ChangeKind = 'add' | 'change' | 'unlink';
interface AuditCommon {
    pack: string;
    skill: string;
    path: string;
}
export type FileWatcherAuditEntry = (AuditCommon & {
    event: 'file_changed_dispatched';
    changeKind: ChangeKind;
}) | (AuditCommon & {
    event: 'file_changed_rate_limited';
    changeKind: ChangeKind;
    reason?: string;
}) | (AuditCommon & {
    event: 'file_changed_error';
    reason: string;
});
export type FileWatcherAuditSink = (entry: FileWatcherAuditEntry) => void;
export declare class FileWatcher {
    private readonly cfg;
    private readonly dispatch;
    private readonly rateLimiter;
    private watcher;
    private readonly debounceTimers;
    private readonly auditLog;
    private readonly debounceMs;
    private readonly nowFn;
    private stopped;
    constructor(cfg: FileWatcherConfig, dispatch: (event: FileChangedEvent) => Promise<void>, rateLimiter: RateLimiter, opts?: {
        auditLog?: FileWatcherAuditSink;
        now?: () => number;
    });
    /** Open the chokidar watcher. Second `start()` or restart-after-stop
     *  throws — the daemon owns lifecycle, so a re-call indicates a bug. */
    start(): void;
    /**
     * Tear down the chokidar instance and clear every pending debounce
     * timer. Safe to call multiple times — second call is a no-op.
     */
    stop(): Promise<void>;
    /** Debounce per `(kind, path)`. Public for test introspection only. */
    private debounceEmit;
    private fireAfterDebounce;
}
export {};
//# sourceMappingURL=file_watcher.d.ts.map