bayesmith.artifacts.gates
Source-derived signatures and contracts. See the reference index for coverage and conventions.
Module contract
Quality gates: several reports in, one status and one verdict out (§0.6). Two rulings do all the work here. **§0 ruling 7: status and verdict are different axes.** ``BLOCKED``, ``INVALIDATED`` and ``ERROR`` mean the gate never got to judge and carry no verdict at all; only ``EVALUATED`` carries ``PASS``, ``FAIL`` or ``ABSTAIN``. Flattening the two would make "we could not check" indistinguishable from "we checked and it failed", and those have different remedies. **The answer may not depend on the order the slots arrived in.** So :func:``aggregate_gate`` builds a mapping from requirement name to slot, verifies it against the schema, and then walks the DEFINITION's requirements -- never the caller's list. The bug this shape exists to prevent is the loop that keeps the last verdict it saw, which is correct exactly when the inputs happen to arrive in a helpful order and silently wrong otherwise. Findings and report references come out in definition order for the same reason: a result that compares unequal to itself under a permutation is not a record. The priority is §0.6's, in order: a missing prerequisite blocks; a stale input or a stale report invalidates; an attempted required error, or an optional error the schema says blocks, is an error; and only then is a verdict computed -- FAIL if any required applicable report failed, ABSTAIN if any required report is missing, inapplicable, unverifiable or undecided, and PASS only when every required applicable report passed. Layering: ``base``, ``refusal`` and ``reports`` (§0.1).
OperationalStatus AttemptStatus ReportRequirement ReportSlot GateDefinition GateResult aggregate_gate
OperationalStatus
Defined in bayesmith.artifacts.gates, line 73.
class OperationalStatus(StrEnum)Whether the gate got to judge at all (§0 ruling 7). Three of the four say it did not, and each names a different thing to fix: a missing prerequisite is upstream work, an invalidated input is a re-run, an error is a failure to investigate. Only ``EVALUATED`` carries a verdict.
BLOCKED = 'blocked'
INVALIDATED = 'invalidated'
ERROR = 'error'
EVALUATED = 'evaluated'AttemptStatus
Defined in bayesmith.artifacts.gates, line 88.
class AttemptStatus(StrEnum)Whether anybody tried to produce this report. The distinction the truth table turns on: a required report that was never attempted leaves the gate undecided (ABSTAIN), while one that was attempted and errored is an ERROR. Without this field the two look identical -- no report either way -- and the milder answer would win.
NOT_ATTEMPTED = 'not_attempted'
ATTEMPTED = 'attempted'ReportRequirement
Defined in bayesmith.artifacts.gates, line 103.
class ReportRequirement
name: str
required: bool = True
optional_error_blocks: bool = FalseOne check a gate asks for, and how much it matters. ``optional_error_blocks`` answers a question only an OPTIONAL requirement has: a required check that errored always blocks. Declaring it on a required requirement is refused rather than ignored -- a field that is silently ignored somewhere is a field somebody will set and rely on.
ReportSlot
Defined in bayesmith.artifacts.gates, line 130.
class ReportSlot
requirement: ReportRequirement
report: EvaluationReport | None = None
attempt_status: AttemptStatus = AttemptStatus.NOT_ATTEMPTED
invalidated: bool = False
error: ErrorRecord | None = NoneWhat became of one requirement on one subject. Exactly one outcome at a time: not attempted, a report, or an error. §0.6 refuses a slot holding a report AND an error at the boundary, because an aggregator reading whichever it checks first would produce a defensible answer from an impossible input.
GateDefinition
Defined in bayesmith.artifacts.gates, line 179.
class GateDefinition
name: str
version: int
requirements: tuple[ReportRequirement, ...]
blocked_actions: tuple[str, ...] = ()
remedies: tuple[Remedy, ...] = ()The schema of a gate: what it asks for, and what it governs. ``blocked_actions`` and ``remedies`` belong to the DEFINITION, not to any one run of it, which is why :func:``aggregate_gate`` copies them into the result unedited.
GateDefinition.identity
identity(self) -> str``name@version``: the spelling a task's ``quality_gate`` carries. One spelling, because a task asks for a gate by string and a result must be checkable against the gate that was asked for.
GateDefinition.requirement
requirement(self, name: str) -> ReportRequirementThe declared requirement called ``name``, or a refusal naming it.
GateResult
Defined in bayesmith.artifacts.gates, line 238.
class GateResult
meta: ArtifactMeta
definition: GateDefinition
status: OperationalStatus
verdict: Conclusion | None = None
report_refs: tuple[ArtifactRef, ...] = ()
findings: tuple[Finding, ...] = ()
blocked_actions: tuple[str, ...] = ()
remedies: tuple[Remedy, ...] = ()One gate's answer: a status always, a verdict only when it judged.
aggregate_gate
Defined in bayesmith.artifacts.gates, line 292.
aggregate_gate(definition: GateDefinition, *, meta: ArtifactMeta, prerequisites_ready: bool, inputs_current: bool, slots: tuple[ReportSlot, ...]) -> GateResult§0.6's priority, applied to a schema-checked mapping of slots. The slots are indexed by requirement name and then read in the order the DEFINITION declares, so the caller's ordering reaches nothing: not the status, not the verdict, not the findings, not the report references.