commit 7b576ca84ff92bd65df1434ff5b3fc8912478985
parent dfc2a7accded8cb1e59242a9f3d03ef5815fb3e6
Author: triesap <tyson@radroots.org>
Date: Mon, 21 Sep 2026 12:54:12 +0000
core: add evidence reference types
Diffstat:
2 files changed, 117 insertions(+), 0 deletions(-)
diff --git a/src/hyf_core/domain/evidence.mojo b/src/hyf_core/domain/evidence.mojo
@@ -0,0 +1,80 @@
+from std.collections import Optional
+
+
+@fieldwise_init
+struct EvidenceRef(Copyable, Movable):
+ var source_id: String
+ var revision: String
+ var kind: String
+ var start: Int
+ var end: Int
+ var record_id: Optional[String]
+ var field: Optional[String]
+ var method: String
+
+
+def span_evidence(
+ source_id: String, revision: String, start: Int, end: Int, method: String
+) raises -> EvidenceRef:
+ if source_id.strip() == "":
+ raise Error("evidence source_id must not be empty")
+ if revision.strip() == "":
+ raise Error("evidence revision must not be empty")
+ if method.strip() == "":
+ raise Error("evidence method must not be empty")
+ if start < 0:
+ raise Error("evidence span start must be non-negative")
+ if end < start:
+ raise Error("evidence span end must not precede start")
+ return EvidenceRef(
+ source_id=String(source_id),
+ revision=String(revision),
+ kind="span",
+ start=start,
+ end=end,
+ record_id=None,
+ field=None,
+ method=String(method),
+ )
+
+
+def record_field_evidence(
+ source_id: String, revision: String, record_id: String, field: String
+) raises -> EvidenceRef:
+ if source_id.strip() == "" or revision.strip() == "":
+ raise Error("evidence source_id and revision must not be empty")
+ if record_id.strip() == "" or field.strip() == "":
+ raise Error("record_field evidence requires record_id and field")
+ return EvidenceRef(
+ source_id=String(source_id),
+ revision=String(revision),
+ kind="record_field",
+ start=0,
+ end=0,
+ record_id=Optional[String](String(record_id)),
+ field=Optional[String](String(field)),
+ method="trusted_record",
+ )
+
+
+def span_is_valid(text: String, evidence: EvidenceRef) raises -> Bool:
+ if evidence.kind != "span":
+ raise Error("span_is_valid requires span evidence")
+ return evidence.end <= text.byte_length()
+
+
+def validate_span_against_revision(
+ text: String, source_revision: String, evidence: EvidenceRef
+) raises:
+ if evidence.kind != "span":
+ raise Error("span evidence required")
+ if evidence.revision != source_revision:
+ raise Error("evidence revision does not match source revision")
+ if not span_is_valid(text, evidence):
+ raise Error("evidence span exceeds source byte length")
+
+
+def selected_text(text: String, evidence: EvidenceRef) raises -> String:
+ if evidence.kind != "span":
+ raise Error("selected_text requires span evidence")
+ return String(text[byte=evidence.start:evidence.end])
diff --git a/tests/test_domain.mojo b/tests/test_domain.mojo
@@ -1,5 +1,6 @@
from std.testing import TestSuite, assert_equal, assert_raises, assert_true
+from hyf_core.domain.evidence import EvidenceRef
from hyf_core.domain.source import (
actor_id,
farm_id,
@@ -36,3 +37,39 @@ def test_trusted_source_preserves_revision() raises:
def main() raises:
TestSuite.discover_tests[__functions_in_module()]().run()
+
+
+from hyf_core.domain.evidence import (
+ record_field_evidence,
+ selected_text,
+ span_evidence,
+ span_is_valid,
+ validate_span_against_revision,
+)
+
+
+def test_evidence_span_byte_offsets_and_revision() raises:
+ var text = "caf\u00e9: 80 lb"
+ var evidence = span_evidence("s1", "r1", 7, 12, "span")
+ assert_equal(evidence.kind, "span")
+ assert_equal(selected_text(text, evidence), "80 lb")
+ validate_span_against_revision(text, "r1", evidence)
+ assert_true(span_is_valid(text, evidence))
+
+ with assert_raises():
+ _ = span_evidence("s1", "r1", 5, 4, "span")
+
+
+def test_evidence_rejects_out_of_range_and_revision_mismatch() raises:
+ var text = "short"
+ with assert_raises():
+ _ = span_evidence("s1", "r1", -1, 2, "span")
+ var beyond = span_evidence("s1", "r1", 0, 99, "span")
+ with assert_raises():
+ validate_span_against_revision(text, "r1", beyond)
+ var good = span_evidence("s1", "r1", 0, 3, "span")
+ with assert_raises():
+ validate_span_against_revision(text, "r2", good)
+ var field = record_field_evidence("s1", "r1", "lot-1", "unreserved_quantity")
+ assert_equal(field.kind, "record_field")
+ assert_equal(field.record_id.value(), "lot-1")