/**
 * upload-test-outputs.ts — shared helper for the testOutputs artifact upload.
 *
 * CalculateScoresStep calls this once its score-summary.json is complete.
 * Each {taskId, modelId} pair becomes one GCS object under
 * `runs/{runId}/test-outputs/{taskId}--{modelId}.json` carrying the full
 * response output and truncation flag. The returned ArtifactRef's
 * `entries[]` catalog lists every uploaded entry so Studio can render
 * drill-down state without a second listing call.
 *
 * PublishReportStep later strips responseOutput from the inline
 * testResults[] when this upload succeeds, so the Content Lake document
 * stays slim — the full output lives in GCS and is fetched per-entry
 * on click.
 *
 * @see docs/decisions/D0032-run-anchored-artifact-store.md
 */
import { type ArtifactRef, type ArtifactWriter, type RunId, type StoredTestResult } from "../_vendor/ailf-core/index.d.ts";
/**
 * Upload testOutputs as per-entry GCS objects under
 * `runs/{runId}/test-outputs/`, one per `(mode, task, model)` triple.
 *
 * D0033 axis convention: literacy-mode taskIds carry a `(gold)` / `(baseline)`
 * suffix whose value is the `mode` axis on the artifact — stripped via
 * `resolveVariantMode`. This aligns the on-disk key with what the Studio
 * hover-prefetch (`testOutputsKeyFor`) and slim-report readers compute; the
 * legacy 2-segment form produced by the pre-D0033 writer 404'd on the new
 * 3-segment read path.
 *
 * Returns the first non-null `ArtifactRef` emitted, or `null` when upload is
 * skipped / every emit fails (P5: non-blocking).
 */
export declare function uploadTestOutputs(writer: ArtifactWriter, runId: RunId, testResults: StoredTestResult[], defaultMode: string): Promise<ArtifactRef | null>;
