orchestrata_ultimate.factory.dor_procedure.models
Reference › orchestrata_ultimate › factory › dor_procedure › models
models is the data model of the Definition-of-Ready construction procedure (SPEC-033 row B23, REQ-033-C5, ADR-0028). There is one frozen dataclass per construction step, so a step's output either has the required fields filled in or validate can name exactly what is missing. Enums are StrEnum so JSON round trips keep plain strings.
- Step 1,
Step1Inputs: the inputs of a criterion asInputSpecrecords (name, whether specified, where, whether used), plus the unused inputs. - Step 2,
Step2Classes: per input, a list ofEquivalenceClassrecords whoseClassKindisVALID,INVALID_BELOW,INVALID_ABOVEorCOMPLEMENT, with an optional boundary. - Step 3,
Step3Behaviors: expected behaviour for each class. - Step 4,
Step4StateWalk: states, inputs, transitions and the no-input case. - Step 5,
Step5FailureEnvelope: per dependency, a response to eachFailureMode(DOWN,SLOW,PARTIAL,RETRY,RESTART), or a stated reason for having no dependencies. - Step 6,
Step6Limits: one entry for eachLimitKind(RATE,SIZE,COUNT,TIME). - Step 7,
Step7Residual: oneAxisAnswerper catalogued axis, each of kindSPECIFIED,NOT_APPLICABLEorGAP(AxisAnswerKind).
RulingsChecklist (built from RulingChecklistEntry records, or a reason that none apply) records which project rulings apply. ConstructionArtifact, which carries @traces for REQ-033-C5, gathers all steps with the requirement id, author identity, creation time and schema version. artifact saves it, anchors_export projects it, and the decision package consumes it.
At a glance
| Source | src/orchestrata_ultimate/factory/dor_procedure/models.py |
| Lines of code | 239 |
| Classes | 17 |
| Functions | 0 |
| Imports (internal) | orchestrata_ultimate.core.base.traces |
| Imported by | orchestrata_ultimate.factory.decision.authority, orchestrata_ultimate.factory.decision.phase, orchestrata_ultimate.factory.dor_procedure.anchors_export, orchestrata_ultimate.factory.dor_procedure.artifact, orchestrata_ultimate.factory.dor_procedure.validate, scripts.factory_decision, scripts.factory_dor_procedure |
| Tests that import it | tests/factory/test_anchor_intake.py, tests/factory/test_decision_phase.py, tests/factory/test_design_authority.py, tests/factory/test_dor_anchors_export.py, tests/factory/test_dor_artifact.py, tests/factory/test_dor_models.py, tests/factory/test_dor_validate.py, tests/scripts/test_factory_anchors_cli.py, tests/scripts/test_factory_decision_cli.py, tests/scripts/test_factory_dor_procedure_cli.py |
Class diagram
Dependency diagram
API
Classes
InputSpec (dataclass)
Decorators: dataclass(frozen=True) · Line 19
One input enumerated in step 1.
| Attribute | Type | Default |
|---|---|---|
name |
str |
|
specified |
bool |
|
where |
str |
|
used |
bool |
Step1Inputs (dataclass)
Decorators: dataclass(frozen=True) · Line 33
Step 1 — enumerate the inputs; are they all specified/used?
| Attribute | Type | Default |
|---|---|---|
inputs |
list[InputSpec] |
field(default_factory=list) |
unused_inputs |
list[str] |
field(default_factory=list) |
ClassKind (enum)
Bases: StrEnum · Line 40
Kinds of equivalence class an input's classes can carry (step 2).
| Member | Value |
|---|---|
VALID |
'valid' |
INVALID_BELOW |
'invalid_below' |
INVALID_ABOVE |
'invalid_above' |
COMPLEMENT |
'complement' |
EquivalenceClass (dataclass)
Decorators: dataclass(frozen=True) · Line 50
One equivalence class for one input (step 2).
| Attribute | Type | Default |
|---|---|---|
label |
str |
|
kind |
ClassKind |
|
description |
str |
|
boundary |
str |
'' |
Step2Classes (dataclass)
Decorators: dataclass(frozen=True) · Line 65
Step 2 — equivalence classes and boundaries, per input.
| Attribute | Type | Default |
|---|---|---|
per_input |
dict[str, list[EquivalenceClass]] |
field(default_factory=dict) |
Step3Behaviors (dataclass)
Decorators: dataclass(frozen=True) · Line 78
Step 3 — expected behaviour for every class from step 2.
| Attribute | Type | Default |
|---|---|---|
behaviors |
dict[str, str] |
field(default_factory=dict) |
Step4StateWalk (dataclass)
Decorators: dataclass(frozen=True) · Line 89
Step 4 — walk the state machine: every state x every input.
| Attribute | Type | Default |
|---|---|---|
states |
list[str] |
field(default_factory=list) |
inputs |
list[str] |
field(default_factory=list) |
transitions |
dict[str, str] |
field(default_factory=dict) |
no_input_case |
str |
'' |
FailureMode (enum)
Bases: StrEnum · Line 104
The five failure-envelope modes walked in step 5.
| Member | Value |
|---|---|
DOWN |
'down' |
SLOW |
'slow' |
PARTIAL |
'partial' |
RETRY |
'retry' |
RESTART |
'restart' |
Step5FailureEnvelope (dataclass)
Decorators: dataclass(frozen=True) · Line 115
Step 5 — walk the failure envelope for every dependency.
| Attribute | Type | Default |
|---|---|---|
dependencies |
list[str] |
field(default_factory=list) |
responses |
dict[str, str] |
field(default_factory=dict) |
no_dependencies_reason |
str |
'' |
LimitKind (enum)
Bases: StrEnum · Line 129
The four limit dimensions walked in step 6.
| Member | Value |
|---|---|
RATE |
'rate' |
SIZE |
'size' |
COUNT |
'count' |
TIME |
'time' |
Step6Limits (dataclass)
Decorators: dataclass(frozen=True) · Line 139
Step 6 — walk the limits.
| Attribute | Type | Default |
|---|---|---|
limits |
dict[str, str] |
field(default_factory=dict) |
AxisAnswerKind (enum)
Bases: StrEnum · Line 146
The three forced-choice answers to a step-7 residual axis.
| Member | Value |
|---|---|
SPECIFIED |
'specified' |
NOT_APPLICABLE |
'not_applicable' |
GAP |
'gap' |
AxisAnswer (dataclass)
Decorators: dataclass(frozen=True) · Line 155
One forced-choice answer to a residual axis (step 7).
| Attribute | Type | Default |
|---|---|---|
axis_id |
str |
|
kind |
AxisAnswerKind |
|
where |
str |
'' |
reason |
str |
'' |
Step7Residual (dataclass)
Decorators: dataclass(frozen=True) · Line 169
Step 7 — answer every catalogued residual axis as forced choice.
| Attribute | Type | Default |
|---|---|---|
answers |
list[AxisAnswer] |
field(default_factory=list) |
RulingChecklistEntry (dataclass)
Decorators: dataclass(frozen=True) · Line 181
One project ruling declared applicable to the requirement being dispatched (workflow-improvements-plan.md Step 6.3).
| Attribute | Type | Default |
|---|---|---|
ruling_id |
str |
|
applies_because |
str |
RulingsChecklist (dataclass)
Decorators: dataclass(frozen=True) · Line 197
The rulings checklist (workflow-improvements-plan.md Step 6.3).
| Attribute | Type | Default |
|---|---|---|
entries |
list[RulingChecklistEntry] |
field(default_factory=list) |
none_apply_reason |
str |
'' |
ConstructionArtifact (dataclass)
Decorators: traces(spec='033', reqs=['REQ-033-C5']), dataclass(frozen=True) · Line 218
The retained evidence artifact of one requirement's DoR construction procedure (ADR-0028) — not a set of ticks.
| Attribute | Type | Default |
|---|---|---|
requirement_id |
str |
|
author_identity |
str |
|
created_at |
str |
|
step1 |
Step1Inputs |
|
step2 |
Step2Classes |
|
step3 |
Step3Behaviors |
|
step4 |
Step4StateWalk |
|
step5 |
Step5FailureEnvelope |
|
step6 |
Step6Limits |
|
step7 |
Step7Residual |
|
rulings_checklist |
RulingsChecklist |
|
schema_version |
int |
1 |
Source
"""Data model for the SPEC-033 DoR construction procedure (B23, REQ-033-C5).
One frozen dataclass per construction step (ADR-0028) — shapes are
machine-checkable *by construction*: a step's output either has the required
fields filled in or :func:`~.validate.validate_artifact` can name exactly
what is missing. Enums are ``StrEnum`` so JSON round-trips
(:mod:`~.artifact`) keep plain string values.
"""
from __future__ import annotations
from dataclasses import dataclass, field
from enum import StrEnum
from orchestrata_ultimate.core.base.traces import traces
@dataclass(frozen=True)
class InputSpec:
"""One input enumerated in step 1.
``where`` is the citation for the input's specification (e.g. a spec
section) when ``specified`` is true; conventionally empty otherwise.
"""
name: str
specified: bool
where: str
used: bool
@dataclass(frozen=True)
class Step1Inputs:
"""Step 1 — enumerate the inputs; are they all specified/used?"""
inputs: list[InputSpec] = field(default_factory=list)
unused_inputs: list[str] = field(default_factory=list)
class ClassKind(StrEnum):
"""Kinds of equivalence class an input's classes can carry (step 2)."""
VALID = "valid"
INVALID_BELOW = "invalid_below"
INVALID_ABOVE = "invalid_above"
COMPLEMENT = "complement"
@dataclass(frozen=True)
class EquivalenceClass:
"""One equivalence class for one input (step 2).
``boundary`` is the boundary value/edge this class pins (e.g. ``"100"``
for a page-size upper bound); conventionally empty for ``COMPLEMENT``,
which has no single pinned edge.
"""
label: str
kind: ClassKind
description: str
boundary: str = ""
@dataclass(frozen=True)
class Step2Classes:
"""Step 2 — equivalence classes and boundaries, per input.
Keyed by input name (matching :class:`InputSpec.name`). For each input:
at least one ``VALID`` class and either two invalid classes
(``INVALID_BELOW`` + ``INVALID_ABOVE``) or, for set-membership inputs, at
least one ``COMPLEMENT`` class.
"""
per_input: dict[str, list[EquivalenceClass]] = field(default_factory=dict)
@dataclass(frozen=True)
class Step3Behaviors:
"""Step 3 — expected behaviour for every class from step 2.
Keyed ``f"{input}:{class_label}"``. Every class enumerated in step 2
(valid *and* invalid) must have a non-empty expected behaviour here.
"""
behaviors: dict[str, str] = field(default_factory=dict)
@dataclass(frozen=True)
class Step4StateWalk:
"""Step 4 — walk the state machine: every state x every input.
``transitions`` is keyed ``f"{state}|{input}"``; the value is the
expected behaviour, or the literal ``"N/A: <reason>"`` when the
combination does not apply. ``no_input_case`` is the timeout/idle
behaviour (or a stated N/A) for receiving no input at all.
"""
states: list[str] = field(default_factory=list)
inputs: list[str] = field(default_factory=list)
transitions: dict[str, str] = field(default_factory=dict)
no_input_case: str = ""
class FailureMode(StrEnum):
"""The five failure-envelope modes walked in step 5."""
DOWN = "down"
SLOW = "slow"
PARTIAL = "partial"
RETRY = "retry"
RESTART = "restart"
@dataclass(frozen=True)
class Step5FailureEnvelope:
"""Step 5 — walk the failure envelope for every dependency.
``responses`` is keyed ``f"{dependency}|{mode}"`` for every
:class:`FailureMode`. An empty ``dependencies`` list requires
``no_dependencies_reason`` to be stated explicitly — "none" must be
said, never implied by omission.
"""
dependencies: list[str] = field(default_factory=list)
responses: dict[str, str] = field(default_factory=dict)
no_dependencies_reason: str = ""
class LimitKind(StrEnum):
"""The four limit dimensions walked in step 6."""
RATE = "rate"
SIZE = "size"
COUNT = "count"
TIME = "time"
@dataclass(frozen=True)
class Step6Limits:
"""Step 6 — walk the limits. Keyed by :class:`LimitKind` value; all four
required (N/A-with-reason allowed)."""
limits: dict[str, str] = field(default_factory=dict)
class AxisAnswerKind(StrEnum):
"""The three forced-choice answers to a step-7 residual axis."""
SPECIFIED = "specified"
NOT_APPLICABLE = "not_applicable"
GAP = "gap"
@dataclass(frozen=True)
class AxisAnswer:
"""One forced-choice answer to a residual axis (step 7).
``where`` is required (non-empty) when ``kind`` is ``SPECIFIED``;
``reason`` is required (non-empty) when ``kind`` is ``NOT_APPLICABLE``.
"""
axis_id: str
kind: AxisAnswerKind
where: str = ""
reason: str = ""
@dataclass(frozen=True)
class Step7Residual:
"""Step 7 — answer every catalogued residual axis as forced choice.
Exactly one answer per axis in
:data:`~orchestrata_ultimate.factory.dor_procedure.axes.RESIDUAL_AXES` —
no extras, no omissions. Silence is not an allowed answer.
"""
answers: list[AxisAnswer] = field(default_factory=list)
@dataclass(frozen=True)
class RulingChecklistEntry:
"""One project ruling declared applicable to the requirement being
dispatched (workflow-improvements-plan.md Step 6.3).
``ruling_id`` is checked at validate time against ids DERIVED from the
rulings canon directory (see
:mod:`~orchestrata_ultimate.factory.dor_procedure.rulings`) — never a
hardcoded whitelist. ``applies_because`` states, in the author's own
words, why the ruling bears on this requirement.
"""
ruling_id: str
applies_because: str
@dataclass(frozen=True)
class RulingsChecklist:
"""The rulings checklist (workflow-improvements-plan.md Step 6.3).
Layered onto :class:`ConstructionArtifact` alongside ADR-0028's seven
numbered construction steps — it is not one of them, and does not
belong to REQ-033-C5's procedure. Its purpose: catch a project-ruling
violation (no mocks, env-from-dotenv, no xdist, ...) at DISPATCH time,
before the work is done, rather than rejecting it after (Step 6.1/6.2
gated post-hoc; this is cheaper).
At least one entry is required, or an explicit ``none_apply_reason`` —
silence is not an allowed answer (mirrors :class:`Step5FailureEnvelope`'s
empty-dependencies rule).
"""
entries: list[RulingChecklistEntry] = field(default_factory=list)
none_apply_reason: str = ""
@traces(spec="033", reqs=["REQ-033-C5"])
@dataclass(frozen=True)
class ConstructionArtifact:
"""The retained evidence artifact of one requirement's DoR construction
procedure (ADR-0028) — not a set of ticks.
Steps 2-3 double as the example/boundary anchors ADR-0012 requires (see
:mod:`~orchestrata_ultimate.factory.dor_procedure.anchors_export`).
``rulings_checklist`` is the Step 6.3 addition — see
:class:`RulingsChecklist`.
"""
requirement_id: str
author_identity: str
created_at: str
step1: Step1Inputs
step2: Step2Classes
step3: Step3Behaviors
step4: Step4StateWalk
step5: Step5FailureEnvelope
step6: Step6Limits
step7: Step7Residual
rulings_checklist: RulingsChecklist
schema_version: int = 1