bayesmith.artifacts.tasks
Source-derived signatures and contracts. See the reference index for coverage and conventions.
Module contract
The five questions a caller can ask, as data (§0.4). A Task is the QUESTION, not the machinery that answers it. §0 ruling 1 fixes five of them and §0 ruling 4 fixes what they may hold: a reference, a fingerprint, a budget and a bounded option table -- never a Graph, a callable, a compiled executable or a backend handle. That is why a predictive task carries the *fingerprint* of its conditioning data rather than the data, and why a simulation task's fixed parameters are :class:``NamedArray``s whose bytes are copied in. **A task's identity is what it asks, not when or by whom.** :func:``task_fingerprint`` digests the kind and every statistical field, and excludes ``meta`` entirely -- the id is minted, the timestamp is a clock, the label is for a human, and the schema version is the envelope's own business rather than one of the §0.3 task-slot contents. Renaming a task must not invalidate a cached result; changing its tolerance must. **Two kinds of collection, two rules, stated once.** A list of SITE NAMES keeps the order it was declared in, because that order is what a caller reads back; a collection keyed by name -- a parameter source's fixed values -- is sorted, because the same values in two orders are one value and a digest that disagreed would depend on the order somebody typed keywords in. Duplicates are refused in both: one of the two would be dropped and nothing would say which. The small validators are :mod:``bayesmith.artifacts.base``'s own, imported rather than restated. A second ``_count`` here would be a second answer to "is a negative budget legal", and this package has already paid for one measurement living in six places. Layering: ``_codec ← identity ← base ← tasks``. Nothing of the Graph, the dispatch layer, JAX, Equinox or NumPyro (§0 ruling 5).
TaskKind
Defined in bayesmith.artifacts.tasks, line 90.
class TaskKind(StrEnum)The five questions of §0 ruling 1, and no sixth. The kind is a member of the tagged union rather than a free string because it is what every dispatch, every gate and every result pairing branches on.
POSTERIOR = 'posterior'
EVIDENCE = 'evidence'
PREDICTIVE = 'predictive'
POINT_ESTIMATE = 'point_estimate'
SIMULATION = 'simulation'TaskMeta
Defined in bayesmith.artifacts.tasks, line 267.
class TaskMeta
task_id: str
schema_version: int
created_at: str
label: str = ''Who asked, and when. None of it is part of the task's fingerprint.
new_task_meta
Defined in bayesmith.artifacts.tasks, line 290.
new_task_meta(*, label: str='', task_id: str | None=None, created_at: str | None=None, schema_version: int=SCHEMA_VERSION) -> TaskMetaA fresh task envelope, minting the id and the time unless given them.
Estimand
Defined in bayesmith.artifacts.tasks, line 105.
class Estimand(StrEnum)Which point of the posterior a point estimate is of (§0.4). Two members, and they are not interchangeable: a posterior mean is an integral, a MAP is an argmax, and they coincide only for a symmetric unimodal posterior. A single "point estimate" with a free-text method would let the difference be lost in a string.
POSTERIOR_MEAN = 'posterior_mean'
MAP = 'map'ParameterSourceKind
Defined in bayesmith.artifacts.tasks, line 119.
class ParameterSourceKind(StrEnum)Where a simulation's parameters come from (§0.4).
PRIOR = 'prior'
FIXED = 'fixed'
POSTERIOR_RESULT = 'posterior_result'ParameterSource
Defined in bayesmith.artifacts.tasks, line 308.
class ParameterSource
kind: ParameterSourceKind
values: tuple[NamedArray, ...] = ()
posterior_ref: ArtifactRef | None = NoneWhere a simulation's parameters come from: a three-armed tagged value. Exactly one arm carries a payload, and the other two must be empty. A single class with an unconstrained pair of optional fields would admit "fixed values AND a posterior reference", which is two answers to one question -- and whichever one the executor read first would become the silent rule.
ParameterSource.prior
prior(cls) -> ParameterSourceParameterSource.fixed
fixed(cls, values: tuple[NamedArray, ...]) -> ParameterSourceParameterSource.from_posterior_result
from_posterior_result(cls, ref: ArtifactRef) -> ParameterSourcePosteriorTask
Defined in bayesmith.artifacts.tasks, line 370.
class PosteriorTask
meta: TaskMeta
backend: str = 'auto'
budget: ComputeBudget = _NO_BUDGET
chain_method: str | None = None
solver_tolerance: float | None = None
solver_maxiter: int | None = None
require_convergence: bool = True
ess_floor: float | None = None
nuts_on_collapse: bool = True
backend_options: tuple[tuple[str, CanonicalValue], ...] = ()
quality_gate: str | None = None
diagnostics: DiagnosticPolicy = dataclasses.field(default_factory=DiagnosticPolicy)
initialization: InitializationPolicy | None = dataclasses.field(default_factory=InitializationPolicy)
stopping: StoppingPolicy = dataclasses.field(default_factory=StoppingPolicy)
block_order: tuple[tuple[str, ...], ...] | None = NoneDraw, or represent, the posterior over the model's latents. ``nuts_on_collapse`` is a fallback POLICY rather than a fallback: the task says whether the caller consents to being moved onto NUTS when an exact route collapses, and the run record says whether it happened.
PosteriorTask.proposals
proposals(self) -> tuple[ProposalBlockPolicy, ...]Explicit proposal blocks encoded in the existing backend options.
EvidenceTask
Defined in bayesmith.artifacts.tasks, line 436.
class EvidenceTask
meta: TaskMeta
backend: str = 'auto'
budget: ComputeBudget = _NO_BUDGET
reconstruct_posterior: bool = False
repeat_count: int | None = None
backend_options: tuple[tuple[str, CanonicalValue], ...] = ()
quality_gate: str | None = NoneThe marginal likelihood, and whether a posterior falls out of it. ``repeat_count`` is how many independent runs the caller wants for a consistency check. ``None`` is a single run; zero is refused, because repeating a run no times is not a second spelling of running it once.
PredictiveTask
Defined in bayesmith.artifacts.tasks, line 474.
class PredictiveTask
meta: TaskMeta
source_posterior_ref: ArtifactRef
conditioning_data: Fingerprint | None = None
prediction_design: Fingerprint | None = None
conditioned_sites: tuple[str, ...] = ()
replicated_sites: tuple[str, ...] = ()
latent_sites: tuple[str, ...] = ()
budget: ComputeBudget = _NO_BUDGET
backend: str = 'auto'
backend_options: tuple[tuple[str, CanonicalValue], ...] = ()
quality_gate: str | None = NonePush an existing posterior forward onto new or replicated observations. What separates this from :class:``SimulationTask`` is stated in the fields rather than in prose (§0.4): a predictive task conditions on data, names the posterior it came from, and distinguishes the sites it replicates from the latents it carries forward. A simulation has none of those.
PointEstimateTask
Defined in bayesmith.artifacts.tasks, line 520.
class PointEstimateTask
meta: TaskMeta
estimand: Estimand
names: tuple[str, ...] | None = None
backend: str = 'auto'
budget: ComputeBudget = _NO_BUDGET
optimizer_options: tuple[tuple[str, CanonicalValue], ...] = ()
quality_gate: str | None = NoneOne point of the posterior, for named latents or for all of them. ``names=None`` is "every latent" and an empty tuple is refused: an empty request and an unrestricted one are different questions, and a field that could mean either would make the answer depend on how the caller spelled "I do not care".
SimulationTask
Defined in bayesmith.artifacts.tasks, line 553.
class SimulationTask
meta: TaskMeta
parameter_source: ParameterSource
prediction_design: Fingerprint | None = None
latent_sites: tuple[str, ...] = ()
observed_sites: tuple[str, ...] = ()
budget: ComputeBudget = _NO_BUDGET
backend: str = 'auto'
backend_options: tuple[tuple[str, CanonicalValue], ...] = ()Generate forward from a parameter source. No conditioning, no gate. §0.4 gives the other four tasks a ``quality_gate`` and this one none, and the omission is deliberate rather than an oversight to be tidied up: a simulation makes no statistical claim to check -- it produced what the model says, and whether that is a good model is what the OTHER four ask.
Task
Defined in bayesmith.artifacts.tasks, line 591.
Task = PosteriorTask | EvidenceTask | PredictiveTask | PointEstimateTask | SimulationTaskTASK_CLASSES
Defined in bayesmith.artifacts.tasks, line 596.
TASK_CLASSES: dict[TaskKind, type] = {TaskKind.POSTERIOR: PosteriorTask, TaskKind.EVIDENCE: EvidenceTask, TaskKind.PREDICTIVE: PredictiveTask, TaskKind.POINT_ESTIMATE: PointEstimateTask, TaskKind.SIMULATION: SimulationTask}task_kind
Defined in bayesmith.artifacts.tasks, line 607.
task_kind(task: Task) -> TaskKindWhich of the five ``task`` is. By exact type, not ``isinstance``: a subclass of one task carrying extra state would be reported as the base kind and executed as it, which is the quiet half of §0 ruling 4.
task_fingerprint
Defined in bayesmith.artifacts.tasks, line 623.
task_fingerprint(task: Task) -> FingerprintThe §0.3 task-slot digest of ``task``. The kind is IN the payload, so two tasks that agree field for field but ask different questions are different. ``meta`` is not: its id is minted, its time is a clock and its label is for a human, and §0.3 keeps all three out of the task slot so that renaming a task cannot invalidate a cached result.
site_names
Defined in bayesmith.artifacts.tasks, line 171.
site_names(label: str, value: object) -> tuple[str, ...]Unique, non-empty site names IN THE ORDER THEY WERE DECLARED. Not sorted: a caller reads these back and the order they wrote is the order they mean. Duplicates are refused rather than collapsed -- a repeated site would silently shorten a collection whose length a caller may be checking.