Declare the layer per GH-DEC-2026-012; close T02
Gate House ruled all three questions within a day, attributing the speed to the
request being filed before the architecture with candidate answers and their
costs.
R1 PEP-shaped, confirmed as proposed. The ruling settles the shape; the layer
stays ours to declare, so layer.yaml is written in this repository's voice
rather than transcribed from the reply.
R2 yes to a presentation claim, no second catalog row, under three limits now
declared in layer.yaml and tested. Limit 2 — the claim must never be an input to
the decision it presents for — is load-bearing: our self-dealing argument was
accepted because it holds, not despite it. Limit 3 drives architecture, since
here the actor being audited and the evidence source are the same component.
R3 (b) with the authority rule: binding digest authoritative for what the
request is, view_hash only for what was shown, neither substitutable, and a
disagreement between them is a finding against the presenting surface rather
than a fact about the request. Linkage is co-reference; nesting was refused
because it reproduces the GH-DEC-2026-008 hash cycle.
Built to v0.8 obligation 3 rather than migrating later: axis enumerated, unknown
resolves to fail_closed, absent distinguishable from unknown in the record, and
published-equals-shipped asserted by test rather than claimed. Every stance is
fail_closed, which is a conclusion not a shortcut — ops-warden can justify
fail_open on a continuity argument that does not exist here.
GH-DEC-2026-010 inherited as a declared gap in four documents: a decision cannot
today be proven to have come from access-engine. The decision path must not be
described as validated while FLEX-WP-0024 is open.
46 tests pass. T05 and T07 unblocked.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V3W1dQG7GFFM9d94jFx7iR
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 1565372@bnt-lap001
Assistant-Session: 16bb2f25-b34c-49ef-8e94-5fec3567a568
2026-09-09 22:25:35 +02:00
|
|
|
"""Layer and stance conformance.
|
|
|
|
|
|
|
|
|
|
GH-DEC-2026-012 confirmed this repository is PEP-shaped and told it to build to
|
|
|
|
|
v0.8 obligation 3 rather than migrate to it later. These tests pin the parts of
|
|
|
|
|
that obligation a test can actually hold:
|
|
|
|
|
|
|
|
|
|
- the published map equals the shipped map (obligation 3, a MUST);
|
|
|
|
|
- the axis is enumerated, not defaulted;
|
|
|
|
|
- ``unknown`` resolves to ``fail_closed``;
|
|
|
|
|
- an absent scope is distinguishable in the record from an unknown one;
|
|
|
|
|
- the inherited GH-DEC-2026-010 attributability gap is declared open rather
|
|
|
|
|
than described as satisfied.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
import pathlib
|
|
|
|
|
|
|
|
|
|
import pytest
|
|
|
|
|
|
|
|
|
|
yaml = pytest.importorskip("yaml")
|
|
|
|
|
|
|
|
|
|
from informed_decision.stance import AXIS, AXIS_VALUES, STANCE, BindingLevelState, resolve
|
|
|
|
|
|
|
|
|
|
ROOT = pathlib.Path(__file__).resolve().parents[1]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def load(name: str) -> dict:
|
|
|
|
|
return yaml.safe_load((ROOT / name).read_text(encoding="utf-8"))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
|
|
|
def stance_doc() -> dict:
|
|
|
|
|
return load("pep-stance.yaml")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
|
|
|
def layer_doc() -> dict:
|
|
|
|
|
return load("layer.yaml")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
|
|
|
# Obligation 3 — published equals shipped. This is the MUST.
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_published_stance_equals_shipped_stance(stance_doc):
|
|
|
|
|
assert stance_doc["stance"] == STANCE, (
|
|
|
|
|
"pep-stance.yaml has drifted from informed_decision/stance.py. "
|
|
|
|
|
"A published map that may differ from the code is worse than none."
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_published_axis_equals_shipped_axis(stance_doc):
|
|
|
|
|
assert stance_doc["axis"] == AXIS
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
|
|
|
# Obligation 3 — totality by enumeration, no catch-all, no implicit default.
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_every_axis_value_has_an_explicit_stance():
|
|
|
|
|
for value in AXIS_VALUES:
|
|
|
|
|
assert value in STANCE, f"{value} has no declared stance"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_stance_map_has_no_entries_beyond_the_axis_and_the_two_outcomes():
|
|
|
|
|
allowed = set(AXIS_VALUES) | {"unknown", "absent"}
|
|
|
|
|
assert set(STANCE) == allowed
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_unknown_resolves_to_fail_closed(stance_doc):
|
|
|
|
|
"""v0.8 obligation 3 makes this a MUST; v0.7 permitted fail_open."""
|
|
|
|
|
assert STANCE["unknown"] == "fail_closed"
|
|
|
|
|
assert stance_doc["stance"]["unknown"] == "fail_closed"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize("value", sorted(STANCE))
|
|
|
|
|
def test_no_stance_is_permissive(value):
|
|
|
|
|
"""Not required by the standard — required by this repository.
|
|
|
|
|
|
|
|
|
|
Binding an identity without an authorization decision is the failure this
|
|
|
|
|
surface exists to prevent, so there is no level at which proceeding is the
|
|
|
|
|
safer error. If this test is ever relaxed, the reasoning in pep-stance.yaml
|
|
|
|
|
must be rewritten first.
|
|
|
|
|
"""
|
|
|
|
|
assert STANCE[value] == "fail_closed"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
|
|
|
# Obligation 3 — absent must be distinguishable from unknown IN THE RECORD,
|
|
|
|
|
# even though both resolve to the same stance.
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_absent_and_unknown_resolve_the_same_but_record_differently():
|
|
|
|
|
absent_stance, absent_state = resolve(None)
|
|
|
|
|
unknown_stance, unknown_state = resolve("notalevel")
|
|
|
|
|
assert absent_stance == unknown_stance == "fail_closed"
|
|
|
|
|
assert absent_state is BindingLevelState.ABSENT
|
|
|
|
|
assert unknown_state is BindingLevelState.UNKNOWN
|
|
|
|
|
assert absent_state != unknown_state
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_empty_string_is_absent_not_unknown():
|
|
|
|
|
assert resolve("")[1] is BindingLevelState.ABSENT
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize("value", AXIS_VALUES)
|
|
|
|
|
def test_known_axis_values_record_as_present(value):
|
|
|
|
|
stance, state = resolve(value)
|
|
|
|
|
assert state is BindingLevelState.PRESENT
|
|
|
|
|
assert stance == "fail_closed"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_published_map_declares_the_two_states_distinguishable(stance_doc):
|
|
|
|
|
absence = stance_doc["scope_absence"]
|
|
|
|
|
assert absence["distinguishable"] is True
|
|
|
|
|
assert absence["recorded_as"]["absent"] != absence["recorded_as"]["unknown"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
|
|
|
# Inherited gap — GH-DEC-2026-010. Must be declared open, not glossed.
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_attributability_gap_is_declared_open_in_the_stance(stance_doc):
|
|
|
|
|
gap = stance_doc["inherited_gap"]
|
|
|
|
|
assert gap["decision_attributable_today"] is False
|
|
|
|
|
assert gap["tracked_by"] == "FLEX-WP-0024"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_attributability_gap_is_declared_open_in_the_layer(layer_doc):
|
|
|
|
|
gaps = {g["id"]: g for g in layer_doc["inherited_gaps"]}
|
|
|
|
|
gap = gaps["GH-DEC-2026-010-attributability"]
|
|
|
|
|
assert gap["status"] == "open"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_stance_records_whether_the_decision_was_attributable(stance_doc):
|
|
|
|
|
assert "decision_attributable" in stance_doc["on_apply"]["recorded_fields"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
|
|
|
# R1 / R2 / R3 — the ruling's limits are declared, not merely remembered.
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_layer_declares_pep_shaped_and_no_decision_surface(layer_doc):
|
|
|
|
|
assert layer_doc["role"] == "pep-shaped"
|
|
|
|
|
assert layer_doc["decision_surfaces_exposed"] == "none"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_presentation_claim_carries_all_three_limits(layer_doc):
|
|
|
|
|
limits = {limit["id"] for limit in layer_doc["presentation_claim"]["limits"]}
|
|
|
|
|
assert limits == {
|
|
|
|
|
"L1-presentation-only",
|
|
|
|
|
"L2-not-an-input",
|
|
|
|
|
"L3-independent-evidence-path",
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
Activate nesting per GH-DEC-2026-015: view_hash carries binding.digest
approval-engine met the condition. Verified here rather than taken on report:
their docs/approval-claim.md carries "Presentation exclusion — GH-DEC-2026-015
§4" in normative language, and I ran
tests/test_claim_contract.py::test_presentation_changes_cannot_change_the_approved_act
myself — 1 passed. That test pins the digest input set from BOTH sides, and the
narrowing half is what makes it real: without it a digest over four fields, or
over a constant, would pass the widening half perfectly.
view_hash now carries binding.digest and the act-scope is no longer
independently canonicalized here, so the act has exactly one canonicalization
computed by the layer that owns it. approval_binding_digest is validated for
shape and refused without its approval id — it is carried, never computed.
The three published vectors are unchanged: they do not carry the new key, so
pick omits it. Asserted, not assumed.
The cycle condition did not disappear, its protection moved — from refusing
nesting to approval-engine's normative exclusion. layer.yaml carries it as
cycle_condition with a test, so a future widening meets a rule rather than
silence.
One thing not assumed. Both gate-house and approval-engine said our binding
slice canonicalizes principal and target, two of their five fields. target
plainly is act material and is now dropped. But their principal is the party ON
WHOSE BEHALF the approval was issued, while ours is the person being BOUND — the
approver. Different roles, and dropping ours would remove who was shown this
from view_hash and gut the promise. Kept it, declared principal_role_overlap
open in layer.yaml, tested that changing the approver still moves view_hash, and
raised it rather than silently resolving it either way.
L0/L2 are unaffected: with no approval there is no digest to defer to, and
test_act_scope_still_binds_when_there_is_no_carried_digest pins that.
100 tests pass.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V3W1dQG7GFFM9d94jFx7iR
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 1565372@bnt-lap001
Assistant-Session: 16bb2f25-b34c-49ef-8e94-5fec3567a568
2026-09-10 20:58:22 +02:00
|
|
|
def test_binding_digest_relationship_is_nesting_and_declares_its_condition(layer_doc):
|
|
|
|
|
"""GH-DEC-2026-015, activated once approval-engine met the condition."""
|
Declare the layer per GH-DEC-2026-012; close T02
Gate House ruled all three questions within a day, attributing the speed to the
request being filed before the architecture with candidate answers and their
costs.
R1 PEP-shaped, confirmed as proposed. The ruling settles the shape; the layer
stays ours to declare, so layer.yaml is written in this repository's voice
rather than transcribed from the reply.
R2 yes to a presentation claim, no second catalog row, under three limits now
declared in layer.yaml and tested. Limit 2 — the claim must never be an input to
the decision it presents for — is load-bearing: our self-dealing argument was
accepted because it holds, not despite it. Limit 3 drives architecture, since
here the actor being audited and the evidence source are the same component.
R3 (b) with the authority rule: binding digest authoritative for what the
request is, view_hash only for what was shown, neither substitutable, and a
disagreement between them is a finding against the presenting surface rather
than a fact about the request. Linkage is co-reference; nesting was refused
because it reproduces the GH-DEC-2026-008 hash cycle.
Built to v0.8 obligation 3 rather than migrating later: axis enumerated, unknown
resolves to fail_closed, absent distinguishable from unknown in the record, and
published-equals-shipped asserted by test rather than claimed. Every stance is
fail_closed, which is a conclusion not a shortcut — ops-warden can justify
fail_open on a continuity argument that does not exist here.
GH-DEC-2026-010 inherited as a declared gap in four documents: a decision cannot
today be proven to have come from access-engine. The decision path must not be
described as validated while FLEX-WP-0024 is open.
46 tests pass. T05 and T07 unblocked.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V3W1dQG7GFFM9d94jFx7iR
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 1565372@bnt-lap001
Assistant-Session: 16bb2f25-b34c-49ef-8e94-5fec3567a568
2026-09-09 22:25:35 +02:00
|
|
|
rel = layer_doc["binding_digest_relationship"]
|
Activate nesting per GH-DEC-2026-015: view_hash carries binding.digest
approval-engine met the condition. Verified here rather than taken on report:
their docs/approval-claim.md carries "Presentation exclusion — GH-DEC-2026-015
§4" in normative language, and I ran
tests/test_claim_contract.py::test_presentation_changes_cannot_change_the_approved_act
myself — 1 passed. That test pins the digest input set from BOTH sides, and the
narrowing half is what makes it real: without it a digest over four fields, or
over a constant, would pass the widening half perfectly.
view_hash now carries binding.digest and the act-scope is no longer
independently canonicalized here, so the act has exactly one canonicalization
computed by the layer that owns it. approval_binding_digest is validated for
shape and refused without its approval id — it is carried, never computed.
The three published vectors are unchanged: they do not carry the new key, so
pick omits it. Asserted, not assumed.
The cycle condition did not disappear, its protection moved — from refusing
nesting to approval-engine's normative exclusion. layer.yaml carries it as
cycle_condition with a test, so a future widening meets a rule rather than
silence.
One thing not assumed. Both gate-house and approval-engine said our binding
slice canonicalizes principal and target, two of their five fields. target
plainly is act material and is now dropped. But their principal is the party ON
WHOSE BEHALF the approval was issued, while ours is the person being BOUND — the
approver. Different roles, and dropping ours would remove who was shown this
from view_hash and gut the promise. Kept it, declared principal_role_overlap
open in layer.yaml, tested that changing the approver still moves view_hash, and
raised it rather than silently resolving it either way.
L0/L2 are unaffected: with no approval there is no digest to defer to, and
test_act_scope_still_binds_when_there_is_no_carried_digest pins that.
100 tests pass.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V3W1dQG7GFFM9d94jFx7iR
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 1565372@bnt-lap001
Assistant-Session: 16bb2f25-b34c-49ef-8e94-5fec3567a568
2026-09-10 20:58:22 +02:00
|
|
|
assert rel["linkage"] == "nesting"
|
Declare the layer per GH-DEC-2026-012; close T02
Gate House ruled all three questions within a day, attributing the speed to the
request being filed before the architecture with candidate answers and their
costs.
R1 PEP-shaped, confirmed as proposed. The ruling settles the shape; the layer
stays ours to declare, so layer.yaml is written in this repository's voice
rather than transcribed from the reply.
R2 yes to a presentation claim, no second catalog row, under three limits now
declared in layer.yaml and tested. Limit 2 — the claim must never be an input to
the decision it presents for — is load-bearing: our self-dealing argument was
accepted because it holds, not despite it. Limit 3 drives architecture, since
here the actor being audited and the evidence source are the same component.
R3 (b) with the authority rule: binding digest authoritative for what the
request is, view_hash only for what was shown, neither substitutable, and a
disagreement between them is a finding against the presenting surface rather
than a fact about the request. Linkage is co-reference; nesting was refused
because it reproduces the GH-DEC-2026-008 hash cycle.
Built to v0.8 obligation 3 rather than migrating later: axis enumerated, unknown
resolves to fail_closed, absent distinguishable from unknown in the record, and
published-equals-shipped asserted by test rather than claimed. Every stance is
fail_closed, which is a conclusion not a shortcut — ops-warden can justify
fail_open on a continuity argument that does not exist here.
GH-DEC-2026-010 inherited as a declared gap in four documents: a decision cannot
today be proven to have come from access-engine. The decision path must not be
described as validated while FLEX-WP-0024 is open.
46 tests pass. T05 and T07 unblocked.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V3W1dQG7GFFM9d94jFx7iR
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 1565372@bnt-lap001
Assistant-Session: 16bb2f25-b34c-49ef-8e94-5fec3567a568
2026-09-09 22:25:35 +02:00
|
|
|
assert rel["substitutable"] is False
|
Activate nesting per GH-DEC-2026-015: view_hash carries binding.digest
approval-engine met the condition. Verified here rather than taken on report:
their docs/approval-claim.md carries "Presentation exclusion — GH-DEC-2026-015
§4" in normative language, and I ran
tests/test_claim_contract.py::test_presentation_changes_cannot_change_the_approved_act
myself — 1 passed. That test pins the digest input set from BOTH sides, and the
narrowing half is what makes it real: without it a digest over four fields, or
over a constant, would pass the widening half perfectly.
view_hash now carries binding.digest and the act-scope is no longer
independently canonicalized here, so the act has exactly one canonicalization
computed by the layer that owns it. approval_binding_digest is validated for
shape and refused without its approval id — it is carried, never computed.
The three published vectors are unchanged: they do not carry the new key, so
pick omits it. Asserted, not assumed.
The cycle condition did not disappear, its protection moved — from refusing
nesting to approval-engine's normative exclusion. layer.yaml carries it as
cycle_condition with a test, so a future widening meets a rule rather than
silence.
One thing not assumed. Both gate-house and approval-engine said our binding
slice canonicalizes principal and target, two of their five fields. target
plainly is act material and is now dropped. But their principal is the party ON
WHOSE BEHALF the approval was issued, while ours is the person being BOUND — the
approver. Different roles, and dropping ours would remove who was shown this
from view_hash and gut the promise. Kept it, declared principal_role_overlap
open in layer.yaml, tested that changing the approver still moves view_hash, and
raised it rather than silently resolving it either way.
L0/L2 are unaffected: with no approval there is no digest to defer to, and
test_act_scope_still_binds_when_there_is_no_carried_digest pins that.
100 tests pass.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V3W1dQG7GFFM9d94jFx7iR
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 1565372@bnt-lap001
Assistant-Session: 16bb2f25-b34c-49ef-8e94-5fec3567a568
2026-09-10 20:58:22 +02:00
|
|
|
assert rel["nesting_permission_active"] is True
|
|
|
|
|
assert rel["nesting_condition_evidence"]["test"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_the_cycle_condition_is_still_declared(layer_doc):
|
|
|
|
|
"""Nesting is safe only while binding.digest excludes presentation.
|
|
|
|
|
|
|
|
|
|
The protection moved from refusing nesting to approval-engine's normative
|
|
|
|
|
exclusion. The condition itself must stay written down, or a future
|
|
|
|
|
widening ships against a rule nobody can find.
|
|
|
|
|
"""
|
|
|
|
|
assert "cycle_condition" in layer_doc["binding_digest_relationship"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_the_principal_role_overlap_is_declared_open(layer_doc):
|
|
|
|
|
"""We kept our own principal in view_hash rather than assuming it is theirs."""
|
|
|
|
|
assert layer_doc["binding_digest_relationship"]["principal_role_overlap"] == "open"
|
Declare the layer per GH-DEC-2026-012; close T02
Gate House ruled all three questions within a day, attributing the speed to the
request being filed before the architecture with candidate answers and their
costs.
R1 PEP-shaped, confirmed as proposed. The ruling settles the shape; the layer
stays ours to declare, so layer.yaml is written in this repository's voice
rather than transcribed from the reply.
R2 yes to a presentation claim, no second catalog row, under three limits now
declared in layer.yaml and tested. Limit 2 — the claim must never be an input to
the decision it presents for — is load-bearing: our self-dealing argument was
accepted because it holds, not despite it. Limit 3 drives architecture, since
here the actor being audited and the evidence source are the same component.
R3 (b) with the authority rule: binding digest authoritative for what the
request is, view_hash only for what was shown, neither substitutable, and a
disagreement between them is a finding against the presenting surface rather
than a fact about the request. Linkage is co-reference; nesting was refused
because it reproduces the GH-DEC-2026-008 hash cycle.
Built to v0.8 obligation 3 rather than migrating later: axis enumerated, unknown
resolves to fail_closed, absent distinguishable from unknown in the record, and
published-equals-shipped asserted by test rather than claimed. Every stance is
fail_closed, which is a conclusion not a shortcut — ops-warden can justify
fail_open on a continuity argument that does not exist here.
GH-DEC-2026-010 inherited as a declared gap in four documents: a decision cannot
today be proven to have come from access-engine. The decision path must not be
described as validated while FLEX-WP-0024 is open.
46 tests pass. T05 and T07 unblocked.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V3W1dQG7GFFM9d94jFx7iR
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 1565372@bnt-lap001
Assistant-Session: 16bb2f25-b34c-49ef-8e94-5fec3567a568
2026-09-09 22:25:35 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_residual_is_declared_not_closed(layer_doc):
|
|
|
|
|
assert layer_doc["evidence"]["residual_closed"] is False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
|
|
|
# §13.1 / GH-DEC-2026-011 — a dated coverage figure beside the stance.
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_classification_coverage_is_dated_and_complete_against_the_axis(stance_doc):
|
|
|
|
|
cov = stance_doc["classification_coverage"]
|
|
|
|
|
assert cov["as_of"]
|
|
|
|
|
assert cov["axis_values_enumerated"] == cov["axis_values_in_schema"] == len(AXIS_VALUES)
|