From eae8565c74baf473184d1b7d96986af61c27abc3 Mon Sep 17 00:00:00 2001 From: opento-suggestions Date: Wed, 30 Sep 2026 09:59:30 -0600 Subject: [PATCH] feat: export CitationCheck and check_citations from the package root verify_record() returns one VerificationResult carrying both a RevocationCheck and a mapping of CitationCheck, so the two are the same kind of thing to a caller reading a result. They were not reachable the same way: agentrust_trace.RevocationCheck resolved and agentrust_trace.CitationCheck raised AttributeError, leaving the citation half to be reached by module path. The description of the change that added citations said the export was a follow-up kept out of that diff; this is it. The two names sit beside their revocation counterparts in __all__, classes before functions, as the rest of the list is ordered. Nothing else changes. agentrust_trace.citation was already reachable, because revocation.py imports CitationCheck at module level, so no import behaviour moves and no signature, outcome or default is touched. The test asserts the revocation names beside the citation ones rather than the citation half alone, so it fails if either side moves. Run against the tree with the export removed it reports CitationCheck is not in __all__, and five mutants over __all__ and the import block, including one that binds the exported name to RevocationCheck, are each caught. Refs #190. Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: opento-suggestions --- CHANGELOG.md | 11 +++++++++++ src/agentrust_trace/__init__.py | 6 ++++++ tests/test_citation_resolution.py | 23 +++++++++++++++++++++++ 3 files changed, 40 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ddb9985..493148b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,17 @@ Format: [Semantic Versioning](https://semver.org/). Spec versions follow `MAJOR. acceptance behavior. Based on the maintainer ruling and producer feedback from @chernistry and @lywinged in #247. +- **`CitationCheck` and `check_citations` are exported from the package root + (#190).** `verify_record()` returns one `VerificationResult` carrying both a + `RevocationCheck` and a mapping of `CitationCheck`, and until now the revocation + half was reachable as `agentrust_trace.RevocationCheck` while the citation half + raised `AttributeError` and had to be reached by module path. The two names now + sit beside their revocation counterparts in `__all__`, which the description of + the change that added `citations` said would follow it. Nothing else changes: + the same objects stay reachable at `agentrust_trace.citation` as before, and no + behaviour, signature or outcome is affected. Informative only: no schema, + wire-format or normative change. + ## [0.11.0] - 2026-09-25 - **Breaking:** `TraceSandboxAdapter` and `TraceAGTAdapter` require `enforcement_mode`; diff --git a/src/agentrust_trace/__init__.py b/src/agentrust_trace/__init__.py index fad4fea6..c33116f6 100644 --- a/src/agentrust_trace/__init__.py +++ b/src/agentrust_trace/__init__.py @@ -38,6 +38,10 @@ sign_record, verify_record, ) +from agentrust_trace.citation import ( + CitationCheck, + check_citations, +) from agentrust_trace.revocation import ( RevocationCheck, VerificationResult, @@ -83,10 +87,12 @@ "RuntimeInfo", "ToolTranscript", "TrustRecord", + "CitationCheck", "RevocationCheck", "RevocationStore", "VerificationResult", "check_bundle", + "check_citations", "DEFAULT_ACCEPTED_PROFILES", "TRACE_PROFILE_V0_2", "SCHEMA", diff --git a/tests/test_citation_resolution.py b/tests/test_citation_resolution.py index 005602a0..d1c9e955 100644 --- a/tests/test_citation_resolution.py +++ b/tests/test_citation_resolution.py @@ -468,6 +468,29 @@ def resolver(uri: str) -> bytes: assert calls == expected_calls +# ---- the package surface ------------------------------------------------------------- + + +def test_the_citation_surface_is_exported_beside_the_revocation_surface() -> None: + """One `VerificationResult` carries a `RevocationCheck` and a mapping of + `CitationCheck`, so a caller who can name one at the package root and has to reach + the other by module path is told the two are different kinds of thing. They are not. + + The revocation names are asserted here beside the citation ones on purpose: this + fails if either side moves, rather than pinning the citation half alone. + """ + import agentrust_trace + from agentrust_trace import citation, revocation + + for module, names in ( + (citation, ("CitationCheck", "check_citations")), + (revocation, ("RevocationCheck", "check_bundle")), + ): + for name in names: + assert name in agentrust_trace.__all__, f"{name} is not in __all__" + assert getattr(agentrust_trace, name) is getattr(module, name), name + + # ---- the generator -------------------------------------------------------------------