/**
 * Shared fact-row scaffolding (D0091 / W-fact-table-registry-v1).
 *
 * Every v1 fact table carries the same identity spine, the join keys back to
 * the existing `reports` / `area_scores` views, the DAY-partition value, a
 * `gs_uri` for drill-through to the full artifact in GCS, and a `_loaded_at`
 * audit column. This module owns that spine once so each descriptor declares
 * only its own analytic columns.
 *
 * ## The `_loaded_at` audit column is schema-only
 *
 * `_loaded_at` records *when the loader wrote the row*, which is neither
 * available to a pure extractor (it has no clock) nor stable across re-runs
 * (idempotent MERGE re-derives the same natural key repeatedly). So it lives
 * in each descriptor's `schema` (the DDL the store provisions) but **not** in
 * the row type or `rowSchema`, the store adapter stamps it at MERGE time
 * (W-bigquery-fact-store-adapter). The schema-sync guard treats it as the one
 * column allowed to exist in `schema` without a matching row field.
 *
 * @see docs/decisions/D0091-bigquery-analytics-fact-loader.md
 * @see docs/design-docs/bigquery-analytics-fact-loader.md
 */
import { z } from "zod";
import type { BigQueryColumn, RunExtractionContext } from "../descriptor.js";
/**
 * The identity + drill-through fields every fact row carries. Concrete row
 * types intersect this with their own analytic columns.
 *
 * Authored as a `type` alias (not an `interface`) intentionally: fact rows
 * must satisfy the engine's `FactRow` bound (`Record<string, unknown>`), and
 * TypeScript infers the required implicit index signature for object-type
 * aliases and their intersections but not for interfaces. Each row type is
 * therefore `RunFactBase & { ... }`.
 */
export type RunFactBase = {
    /** Run join key (`RunId` value). */
    readonly run_id: string;
    /** Report join key to `reports` / `area_scores`; null for report-less runs. */
    readonly report_id: string | null;
    /** DAY-partition value (run completion time, ISO 8601). */
    readonly completed_at: string;
    /** Fully-qualified GCS URI of the source artifact this row was derived from. */
    readonly gs_uri: string;
};
/**
 * The name of the load-audit column. Present in every table's `schema`,
 * absent from every row type, see the module doc.
 */
export declare const LOADED_AT_COLUMN_NAME = "_loaded_at";
/** The load-audit column, appended to every fact table's schema. */
export declare const LOADED_AT_COLUMN: BigQueryColumn;
/**
 * The `BigQueryColumn`s for {@link RunFactBase}, in row order. Spread at the
 * front of each descriptor's `schema`; `LOADED_AT_COLUMN` goes at the end.
 */
export declare const RUN_FACT_BASE_COLUMNS: readonly BigQueryColumn[];
/** The zod fields for {@link RunFactBase}. Spread into each table's `rowSchema`. */
export declare const runFactBaseShape: {
    readonly run_id: z.ZodString;
    readonly report_id: z.ZodNullable<z.ZodString>;
    readonly completed_at: z.ZodString;
    readonly gs_uri: z.ZodString;
};
/**
 * Build the {@link RunFactBase} portion of a row from the extraction context
 * and the drill-through URI of the specific artifact the row came from.
 */
export declare function runFactBase(ctx: RunExtractionContext, sourceUri: string): RunFactBase;
/**
 * Coerce an {@link AssociationValues} axis value (`string | number | undefined`)
 * to a string, defaulting to `fallback` when the axis is absent. Association
 * axes on the read side arrive as the values the writer stamped; a missing axis
 * means the artifact did not carry it, which we surface as a stable default
 * rather than `undefined` leaking into a row.
 */
export declare function axisString(value: string | number | undefined, fallback?: string): string;
/** A finite number, or null. */
export declare function numOrNull(v: unknown): number | null;
/** A finite, non-negative integer, or null (truncates fractional inputs). */
export declare function nonNegIntOrNull(v: unknown): number | null;
/** A boolean, or null. */
export declare function boolOrNull(v: unknown): boolean | null;
/** A non-empty string, or null. */
export declare function strOrNull(v: unknown): string | null;
