/**
 * accumulating-artifact-writer.ts
 *
 * Decorator that wraps any `ArtifactWriter` and accumulates every
 * successful `emit()` / `appendNdjson()` return into a run-scoped
 * manifest slice. FinalizeRunStep reads the accumulator at the end of
 * a pipeline and writes a `runs/{runId}/manifest.json` populated with
 * one entry per produced artifact type.
 *
 * Before W0051 revisit: only `calculate-scores-step` registered its
 * ref (for `testOutputs`) into `state.artifactRefs`; every other
 * producer discarded the returned ref. The result was empty
 * `Report.artifactManifest` fields and no per-entry preview lookup
 * for Studio hooks. Wrapping the writer at the composition-root level
 * closes that gap without per-producer bookkeeping.
 *
 * Merging rules (per type):
 *   - `bulk`: last-writer-wins. A pipeline that emits the same bulk
 *     artifact twice overwrites — matches GCS semantics.
 *   - `per-entry`: entries accumulate into a keyed map. A later emit
 *     at the same `entries[].key` replaces the earlier one.
 *
 * The decorator holds no disk state; the `_resetAccumulated()` hook is
 * for unit tests that rerun emit sequences within a single writer.
 *
 * @see docs/decisions/D0033-unified-run-anchored-artifact-capture.md (§ M5)
 */
import type { ArtifactEntry, ArtifactManifest, ArtifactRef, ArtifactType, ArtifactWriter, AssociationValues, RunId, RunManifest } from "../_vendor/ailf-core/index.d.ts";
export declare class AccumulatingArtifactWriter implements ArtifactWriter {
    /**
     * Exposed so composition-root tests can assert on the underlying backend
     * (LocalFilesystemArtifactWriter, FanoutArtifactWriter, etc.) without
     * plumbing a separate accessor. Treat as read-only.
     */
    readonly inner: ArtifactWriter;
    private readonly accumulated;
    constructor(inner: ArtifactWriter);
    /** Snapshot of every ref produced this far, keyed by artifact type. */
    getAccumulatedArtifactRefs(): ArtifactManifest;
    /** Test-only. Clears accumulated refs without touching the inner writer. */
    _resetAccumulated(): void;
    /**
     * Merge externally-supplied refs into the accumulator without touching
     * the inner backend. Used by `RunEvalStep`'s cache-hit branch (D0040 /
     * W0135) to restore a cached report's `Report.artifactManifest` so the
     * new run's `RunManifest` advertises the cached artifacts via cross-run
     * paths instead of skipping them entirely.
     *
     * The injected refs already carry `path`, `bucket`, `entries`, etc. as
     * the source run wrote them — we don't synthesize new paths, we copy.
     * Refs typically carry `sourceRunId` (set by `remapToCacheHitRefs`) so
     * downstream tooling can follow the lineage.
     */
    injectAccumulated(refs: ArtifactManifest): void;
    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 — forwarded to the inner writer without accumulation. */
    writeBulk(type: ArtifactType, runId: RunId, data: unknown): Promise<ArtifactRef | null>;
    /** @deprecated — forwarded to the inner writer without accumulation. */
    writePerEntry(type: ArtifactType, runId: RunId, entries: readonly ArtifactEntry[]): Promise<ArtifactRef | null>;
    private mergeRef;
}
