/**
 * LocalFilesystemArtifactWriter — writes AILF run artifacts to the local
 * filesystem under `{rootDir}/runs/{runId}/…`.
 *
 * D0033 M4 inverts D0032's "GCS default, local fallback" stance: the local
 * writer is **always** attached, and GCS layers on top via a fanout writer
 * when credentials are present. The result — every run produces a usable
 * artifact bundle on disk even on airplanes, laptops, and CI without GCS
 * creds. Studio retrieval works uniformly; only `ArtifactRef.store`
 * differentiates.
 *
 * ## Path layout
 *
 * Paths mirror the GCS tree exactly, so the same descriptor's `objectPath`
 * is used verbatim:
 *   - bulk: `{rootDir}/runs/{runId}/{slug}.{ext}`
 *   - per-entry: `{rootDir}/runs/{runId}/{slug}/{sanitizedKey}.{ext}`
 *   - manifest: `{rootDir}/runs/{runId}/manifest.json`
 *
 * This keeps the L6 cross-reader contract test simple — a byte-compare of
 * every object at every path, modulo timestamped manifest fields.
 *
 * ## Design choices
 *
 * - **Redaction at emit boundary (AC10).** `redactArtifactData` runs per
 *   write, not post-hoc on a tarball. Same rules as the legacy collector.
 * - **Exclude list gating (Q3).** `--capture-exclude=LIST` passes through
 *   to the constructor; `emit()` returns null for excluded types before
 *   touching disk.
 * - **NDJSON uses plain `fs.appendFile`.** No compose rollover needed —
 *   unlike GCS, local fs appends are atomic and unbounded. A crash mid-
 *   append leaves a partial row visible; acceptable for dev runs.
 * - **Non-blocking per P5.** Any fs error returns null + warns, never
 *   throws. The pipeline must not fail because local disk is full.
 *
 * @see docs/decisions/D0033-unified-run-anchored-artifact-capture.md (§ M4)
 * @see packages/eval/src/artifact-capture/gcs-artifact-writer.ts (mirror)
 */
import { type ArtifactEntry, type ArtifactRef, type ArtifactType, type ArtifactWriter, type ArtifactWriterProgressOptions, type AssociationValues, type RunId, type RunManifest, type WriteSource } from "../_vendor/ailf-core/index.d.ts";
export interface LocalFilesystemArtifactWriterOptions {
    /**
     * Absolute or cwd-relative root directory under which `runs/{runId}/…`
     * is written. Defaults to `.ailf/results/captures/` at the composition
     * root; tests inject their own temp dirs.
     */
    rootDir: string;
    /**
     * Artifact types to skip. When `emit()` is called for an excluded
     * type, it returns null without touching disk. Driven by
     * `--capture-exclude=LIST` in W0050 Slice 4.
     */
    exclude?: readonly ArtifactType[];
    /**
     * Optional progress reporter + phaseId (W0053). When set, the writer
     * publishes `phaseProgress` on every successful write so the CLI can
     * render per-batch updates during long export phases.
     */
    progress?: ArtifactWriterProgressOptions;
    /**
     * Identifies what kind of execution context owns this writer instance.
     * The D0050 guard refuses to emit a descriptor whose `writePolicy` is
     * different from this value. `"pipeline"` (the default) is for writers
     * driven by an `ailf run` pipeline; `"post-hoc"` is for writers driven
     * by deferred commands like `ailf interpret` that emit descriptors
     * declared `writePolicy: "post-hoc"` (D0050).
     */
    writerSource?: WriteSource;
}
export declare class LocalFilesystemArtifactWriter implements ArtifactWriter {
    private readonly options;
    private readonly excludeSet;
    private readonly writerSource;
    constructor(options: LocalFilesystemArtifactWriterOptions);
    private reportProgress;
    emit<T extends ArtifactType>(type: T, association: AssociationValues, payload: unknown): Promise<ArtifactRef | null>;
    appendNdjson<T extends ArtifactType>(type: T, association: AssociationValues, rows: readonly unknown[]): Promise<ArtifactRef | null>;
    writeManifest(runId: RunId, manifest: RunManifest): Promise<ArtifactRef | null>;
    /** @deprecated Use `emit()` instead. */
    writeBulk(type: ArtifactType, runId: RunId, data: unknown): Promise<ArtifactRef | null>;
    /** @deprecated Use `emit()` per entry instead. */
    writePerEntry(type: ArtifactType, runId: RunId, entries: readonly ArtifactEntry[]): Promise<ArtifactRef | null>;
    private resolve;
    /**
     * Write the body to `absPath`, creating parent dirs as needed. Returns
     * false + warns on any fs error (P5 non-blocking).
     */
    private writeAtomic;
}
