latent.gates.publish¶
Publish a statistical report: gate-fill, sampled stamp, renderings, payload.
The engine behind the stats.Report / agent_studio.Report dataset types
(which own the file IO) and the public escape for non-catalog contexts —
scripts, notebooks, orchestrators. Catalog-declared flows never call it: they
return the report and let the catalog publish it.
One call produces the artifact contract the rest of the machinery reads: a
gates array, a sampled stamp, a run_id stamp when a flow is active,
and a mode="json" payload (latent.gates.thresholds.discover_reports,
flow-teardown enforcement, LT013). analyze's analysis knobs (rubrics,
comparison_scores, n_resamples, confidence_level, seed, …) stay
on analyze — call it yourself and pass report=.
Publishing records verdicts; it never raises on a failed gate.
latent.gates.gating.enforce_gates owns the raise.
Classes¶
PublishedReport¶
A published report: the gated, stamped model plus its renderings.
Frozen — post-hoc payload surgery is what extra= replaces. The freeze
is shallow: report and payload are themselves mutable objects, so
treat them as read-only.
Functions¶
publish_report¶
publish_report(scores: dict[str, np.ndarray] | None = None, report: StatisticalReport | None = None, score_types: str | dict[str, str] | None = None, gates: dict[str, float | GateSpec] | None = None, extra: dict[str, Any] | None = None, sampled: bool | None = None) -> PublishedReport
Analyze or adopt a report, gate it, stamp it, render it, log it.
Args:
scores: Metric name -> 1D score array. Mutually exclusive with
report; this branch calls :func:~latent.stats.report.analyze.
report: An already-analyzed report (from analyze,
build_gated_report, or a pre-built flow's result["report"]).
Published on a deep copy — the caller's object is never mutated.
score_types: "binary"/"ordinal"/"continuous" broadcast to
every metric, or a per-metric dict. Scores mode only.
gates: Explicit thresholds; they win over thresholds.yaml
verbatim. None resolves the active flow's lockfile section
(:func:~latent.gates.thresholds.resolve_gates). {} publishes
ungated and records gates_disabled on the artifact. Direction
comes from an explicit GateSpec.lower_is_better only — this
function forwards no metric_directions, so bare-float
thresholds gate as floors.
extra: Extra top-level payload keys (offender lists, dataset ids, ...),
JSON-normalized before merging. A key colliding with a
StatisticalReport field raises — set it on the report instead.
run_id is reserved inside a flow: the active run's id is
stamped over it (see below).
sampled: Override the smoke-run stamp. None (default) reads
latent.prefect.sampling.effective_truncation() — True only when
apply_sampling actually truncated this run — and ORs it with an
incoming report's own stamp, so the flag only ever goes on by
default: republishing a sampled report cannot launder it into an
enforceable one. sampled=False is the explicit escape hatch.
Returns:
A frozen :class:PublishedReport.
Raises: ValueError: Neither or both of scores/report; score_types in report mode; gates against a report that already carries gates; a gated metric name appearing more than once in the report; an extra key colliding with a report field or not JSON-serializable.
Methods¶
PublishedReport.all_passed¶
True when every recorded gate passed.
Vacuously True when the report carries no gates (never gated, or
gates={}): it means "nothing failed", not "everything was
checked". Coverage is latent thresholds check's question;
enforcement is :func:~latent.gates.gating.enforce_gates'.