ADR-0021 v1 schema land. epistemic_status is a position in the revision
graph, not a source-trust tier — coherence is the only admission signal.
Surfaces:
- teaching/epistemic.py: EpistemicStatus enum (COHERENT, CONTESTED,
SPECULATIVE, FALSIFIED); ADMISSIBLE_AS_EVIDENCE = {COHERENT}.
- PackMutationProposal.epistemic_status (default SPECULATIVE) + immutable
with_status() updater.
- ReviewedTeachingExample.epistemic_status (default SPECULATIVE);
orthogonal to acceptance per ADR §Schema impact.
- LexicalEntry.epistemic_status (default "coherent" for seed; absent in
JSONL is treated as the seed default — no retroactive tagging).
- compute_trace_hash + trace_hash_from_result + pipeline.py fold the
load-bearing proposal's epistemic_status into the trace hash so
replay detects different epistemic frames.
Non-hardening invariant (ADR-0021 §2): tests/test_epistemic_invariants.py
asserts no final/frozen/axiom/permanent flag on PackMutationProposal or
ReviewedTeachingExample, and EpistemicStatus contains no source-trust
tier names.
Docs: docs/runtime_contracts.md gains an Epistemic surface section.
Lanes green: smoke 27/27, teaching 10/10, packs 6/6, runtime 19/19,
cognition eval 100%.
144 lines
4.7 KiB
Python
144 lines
4.7 KiB
Python
"""ADR-0021 non-hardening invariant tests.
|
|
|
|
The Epistemic Grade Policy commits to:
|
|
|
|
1. `epistemic_status` is a position in the revision graph, not a trust
|
|
tier.
|
|
2. No reviewed claim, relation, or proposition-graph edge ever becomes
|
|
unrevisable — no `final`, `frozen`, `axiom`, or `permanent` flag may
|
|
exist or be added on the runtime data model.
|
|
3. Coherence is the only admission signal — source-trust labels must not
|
|
be part of the schema.
|
|
|
|
These tests are the structural checks behind those commitments. They
|
|
are intentionally simple and read like contract assertions, not
|
|
behaviour tests.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import dataclasses
|
|
|
|
from teaching import EpistemicStatus, PackMutationProposal, ReviewedTeachingExample
|
|
from teaching.correction import CorrectionCandidate
|
|
from teaching.review import ReviewOutcome
|
|
|
|
|
|
_FORBIDDEN_HARDENING_NAMES: frozenset[str] = frozenset({
|
|
"final",
|
|
"frozen",
|
|
"axiom",
|
|
"permanent",
|
|
"immutable_truth",
|
|
"sealed",
|
|
})
|
|
|
|
# Source-trust tier names that ADR-0021 §3 forbids in the schema.
|
|
_FORBIDDEN_TRUST_TIER_NAMES: frozenset[str] = frozenset({
|
|
"peer_consensus",
|
|
"outsider_empirical",
|
|
"established",
|
|
"unauthoritative",
|
|
"credentialed",
|
|
"source_trust",
|
|
"authority",
|
|
"trust_tier",
|
|
})
|
|
|
|
|
|
def _field_names(cls: type) -> set[str]:
|
|
return {f.name for f in dataclasses.fields(cls)}
|
|
|
|
|
|
def _enum_value_strings(enum_cls) -> set[str]:
|
|
return {member.value for member in enum_cls}
|
|
|
|
|
|
def test_pack_mutation_proposal_has_no_hardening_flag():
|
|
"""PackMutationProposal must not expose any name implying permanence."""
|
|
names = _field_names(PackMutationProposal)
|
|
forbidden = names & _FORBIDDEN_HARDENING_NAMES
|
|
assert forbidden == set(), (
|
|
f"PackMutationProposal exposes hardening flag(s) {forbidden}; "
|
|
"ADR-0021 §2 forbids non-revisable state on the runtime data model."
|
|
)
|
|
|
|
|
|
def test_reviewed_teaching_example_has_no_hardening_flag():
|
|
"""ReviewedTeachingExample must not expose any name implying permanence."""
|
|
names = _field_names(ReviewedTeachingExample)
|
|
forbidden = names & _FORBIDDEN_HARDENING_NAMES
|
|
assert forbidden == set(), (
|
|
f"ReviewedTeachingExample exposes hardening flag(s) {forbidden}; "
|
|
"ADR-0021 §2 forbids non-revisable state on the runtime data model."
|
|
)
|
|
|
|
|
|
def test_epistemic_status_enum_carries_no_trust_tier_names():
|
|
"""EpistemicStatus must describe revision-graph position, not source trust."""
|
|
values = _enum_value_strings(EpistemicStatus)
|
|
forbidden = values & _FORBIDDEN_TRUST_TIER_NAMES
|
|
assert forbidden == set(), (
|
|
f"EpistemicStatus enum contains source-trust tier value(s) {forbidden}; "
|
|
"ADR-0021 §3 forbids credentialing the schema."
|
|
)
|
|
|
|
|
|
def test_epistemic_status_enum_has_exactly_the_four_positions():
|
|
"""ADR-0021 §1 names the enum members precisely; no silent additions."""
|
|
assert _enum_value_strings(EpistemicStatus) == {
|
|
"coherent",
|
|
"contested",
|
|
"speculative",
|
|
"falsified",
|
|
}
|
|
|
|
|
|
def test_proposal_default_is_speculative():
|
|
"""ADR-0021 §Schema impact: proposals start SPECULATIVE; promotion is
|
|
a separate, review-mediated transition."""
|
|
proposal = PackMutationProposal(
|
|
proposal_id="x",
|
|
candidate_id="y",
|
|
subject="z",
|
|
correction_text="a knows b",
|
|
prior_surface="",
|
|
)
|
|
assert proposal.epistemic_status is EpistemicStatus.SPECULATIVE
|
|
|
|
|
|
def test_proposal_with_status_returns_new_immutable_proposal():
|
|
"""Immutable update — the original is never mutated."""
|
|
original = PackMutationProposal(
|
|
proposal_id="x",
|
|
candidate_id="y",
|
|
subject="z",
|
|
correction_text="a knows b",
|
|
prior_surface="",
|
|
)
|
|
promoted = original.with_status(EpistemicStatus.COHERENT)
|
|
|
|
assert promoted.epistemic_status is EpistemicStatus.COHERENT
|
|
assert original.epistemic_status is EpistemicStatus.SPECULATIVE
|
|
assert promoted is not original
|
|
|
|
|
|
def test_reviewed_example_default_is_speculative_for_accepted_outcome():
|
|
"""Acceptance is orthogonal to coherence ratification per ADR-0021
|
|
§Schema impact: 'Accepting a proposal is not the same as ratifying
|
|
it as COHERENT.'"""
|
|
from generate.intent import DialogueIntent, IntentTag
|
|
|
|
intent = DialogueIntent(tag=IntentTag.DEFINITION, subject="a")
|
|
candidate = CorrectionCandidate(
|
|
candidate_id="c1",
|
|
intent=intent,
|
|
correction_text="a is b",
|
|
prior_surface="",
|
|
prior_turn=0,
|
|
)
|
|
from teaching import review_correction
|
|
|
|
reviewed = review_correction(candidate)
|
|
assert reviewed.outcome is ReviewOutcome.ACCEPTED
|
|
assert reviewed.epistemic_status is EpistemicStatus.SPECULATIVE
|