origin-lang 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,15 @@
1
+ Metadata-Version: 2.4
2
+ Name: origin-lang
3
+ Version: 0.1.0
4
+ Summary: Every value is either in the interior or at a boundary. The runtime knows which.
5
+ License-Expression: MIT
6
+ Project-URL: Homepage, https://github.com/knoxvilledatabase/origin
7
+ Keywords: ai,safety,boundary,inference,type-system
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Topic :: Software Development :: Libraries
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Requires-Python: >=3.10
@@ -0,0 +1,13 @@
1
+ """
2
+ Origin: every value is either in the interior or at a boundary.
3
+
4
+ from origin_lang import Value, boundary
5
+
6
+ This is the pure Python version. Runtime enforcement, same concept.
7
+ For compile-time enforcement, see the Rust crate.
8
+ """
9
+
10
+ from origin_lang.value import Value
11
+ from origin_lang.boundary import boundary, BoundaryKind
12
+
13
+ __all__ = ["Value", "boundary", "BoundaryKind"]
@@ -0,0 +1,41 @@
1
+ """
2
+ The @boundary decorator: mark a class as a boundary kind.
3
+
4
+ @boundary
5
+ class LowConfidence:
6
+ confidence: float
7
+ threshold: float
8
+
9
+ This turns the class into a frozen dataclass that can be used
10
+ as the reason field in Value.boundary().
11
+ """
12
+
13
+ from dataclasses import dataclass
14
+
15
+
16
+ class BoundaryKind:
17
+ """Base class for boundary kinds. Optional — @boundary is simpler."""
18
+ pass
19
+
20
+
21
+ def boundary(cls):
22
+ """Decorator that turns a class into a boundary kind.
23
+
24
+ Wraps it as a dataclass and marks it as a BoundaryKind.
25
+
26
+ @boundary
27
+ class LowConfidence:
28
+ confidence: float
29
+ threshold: float
30
+
31
+ Value.boundary(LowConfidence(confidence=0.61, threshold=0.85), last=diagnosis)
32
+ """
33
+ # Make it a dataclass if it isn't already
34
+ cls = dataclass(frozen=True)(cls)
35
+
36
+ # Register as a BoundaryKind
37
+ if BoundaryKind not in cls.__mro__:
38
+ # Can't modify __bases__ on a dataclass, so register it differently
39
+ cls._is_boundary_kind = True
40
+
41
+ return cls
@@ -0,0 +1,147 @@
1
+ """
2
+ The core type. Interior or Boundary. One distinction. Every domain.
3
+
4
+ Value<T, B> in Rust. Value[T, B] in Python. Same idea:
5
+ - Interior(value): the value is in safe territory.
6
+ - Boundary(reason, last): the value crossed the edge.
7
+ reason says which boundary. last says what the computation knew.
8
+
9
+ The `last` field is what neither exceptions nor Result carry.
10
+ It's always here. You can't drop it.
11
+ """
12
+
13
+ from __future__ import annotations
14
+ from typing import TypeVar, Generic, Callable
15
+
16
+ T = TypeVar("T")
17
+ U = TypeVar("U")
18
+ B = TypeVar("B")
19
+
20
+
21
+ class Value(Generic[T, B]):
22
+ """A value that is either interior or at a boundary."""
23
+
24
+ __slots__ = ("_interior", "_reason", "_last", "_is_interior")
25
+
26
+ def __init__(self, *, _interior=None, _reason=None, _last=None, _is_interior=True):
27
+ self._interior = _interior
28
+ self._reason = _reason
29
+ self._last = _last
30
+ self._is_interior = _is_interior
31
+
32
+ @staticmethod
33
+ def interior(value: T) -> Value[T, B]:
34
+ """Construct an interior value."""
35
+ return Value(_interior=value, _is_interior=True)
36
+
37
+ @staticmethod
38
+ def boundary(reason: B, *, last: T) -> Value[T, B]:
39
+ """Construct a boundary value with a reason and last known value."""
40
+ if last is None:
41
+ raise ValueError(
42
+ "boundary() requires last= — the whole point is preserving "
43
+ "what the computation knew before it hit the boundary"
44
+ )
45
+ return Value(_reason=reason, _last=last, _is_interior=False)
46
+
47
+ @property
48
+ def is_interior(self) -> bool:
49
+ return self._is_interior
50
+
51
+ @property
52
+ def is_boundary(self) -> bool:
53
+ return not self._is_interior
54
+
55
+ def unwrap(self) -> T:
56
+ """Get the interior value, or raise if boundary.
57
+
58
+ In boundary-checked code, prefer match instead.
59
+ """
60
+ if self._is_interior:
61
+ return self._interior
62
+ raise BoundaryError(self._reason, self._last)
63
+
64
+ def or_default(self, fallback: T) -> T:
65
+ """Get the interior value, or return a fallback."""
66
+ if self._is_interior:
67
+ return self._interior
68
+ return fallback
69
+
70
+ def map(self, f: Callable[[T], U]) -> Value[U, B]:
71
+ """Map over the value. Boundaries propagate with mapped last."""
72
+ if self._is_interior:
73
+ return Value.interior(f(self._interior))
74
+ return Value.boundary(self._reason, last=f(self._last))
75
+
76
+ def __repr__(self):
77
+ if self._is_interior:
78
+ return f"Value.Interior({self._interior!r})"
79
+ return f"Value.Boundary({self._reason!r}, last={self._last!r})"
80
+
81
+ # -- Pattern matching support (Python 3.10+) --
82
+
83
+ class Interior:
84
+ """Match pattern for interior values.
85
+
86
+ case Value.Interior(diagnosis):
87
+ treat(diagnosis)
88
+ """
89
+ __match_args__ = ("value",)
90
+
91
+ def __init__(self, value):
92
+ self.value = value
93
+
94
+ class Boundary:
95
+ """Match pattern for boundary values.
96
+
97
+ case Value.Boundary(LowConfidence(confidence=c), last=diagnosis):
98
+ refer_to_specialist(diagnosis, c)
99
+ """
100
+ __match_args__ = ("reason", "last")
101
+
102
+ def __init__(self, reason, last):
103
+ self.reason = reason
104
+ self.last = last
105
+
106
+ # Enable generic subscript: Value[T, B]
107
+ def __class_getitem__(cls, params):
108
+ return cls
109
+
110
+
111
+ def match(value: Value[T, B]):
112
+ """Unpack a Value for pattern matching.
113
+
114
+ With Python 3.10+ match/case:
115
+
116
+ match match(result):
117
+ case Value.Interior(diagnosis):
118
+ treat(diagnosis)
119
+ case Value.Boundary(LowConfidence(confidence=c), last=diagnosis):
120
+ refer_to_specialist(diagnosis, c)
121
+
122
+ Or with isinstance:
123
+
124
+ m = match(result)
125
+ if isinstance(m, Value.Interior):
126
+ treat(m.value)
127
+ elif isinstance(m, Value.Boundary):
128
+ handle(m.reason, m.last)
129
+ """
130
+ if value.is_interior:
131
+ return Value.Interior(value._interior)
132
+ return Value.Boundary(value._reason, value._last)
133
+
134
+
135
+ class BoundaryError(Exception):
136
+ """Raised when unwrap() is called on a boundary value.
137
+
138
+ Carries the reason and the last known value, because even
139
+ in an exception, the information shouldn't be lost.
140
+ """
141
+
142
+ def __init__(self, reason, last):
143
+ self.reason = reason
144
+ self.last = last
145
+ super().__init__(
146
+ f"called unwrap() on a Boundary: {reason!r} (last={last!r})"
147
+ )
@@ -0,0 +1,15 @@
1
+ Metadata-Version: 2.4
2
+ Name: origin-lang
3
+ Version: 0.1.0
4
+ Summary: Every value is either in the interior or at a boundary. The runtime knows which.
5
+ License-Expression: MIT
6
+ Project-URL: Homepage, https://github.com/knoxvilledatabase/origin
7
+ Keywords: ai,safety,boundary,inference,type-system
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Topic :: Software Development :: Libraries
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Requires-Python: >=3.10
@@ -0,0 +1,9 @@
1
+ pyproject.toml
2
+ origin_lang/__init__.py
3
+ origin_lang/boundary.py
4
+ origin_lang/value.py
5
+ origin_lang.egg-info/PKG-INFO
6
+ origin_lang.egg-info/SOURCES.txt
7
+ origin_lang.egg-info/dependency_links.txt
8
+ origin_lang.egg-info/top_level.txt
9
+ tests/test_value.py
@@ -0,0 +1 @@
1
+ origin_lang
@@ -0,0 +1,23 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "origin-lang"
7
+ version = "0.1.0"
8
+ description = "Every value is either in the interior or at a boundary. The runtime knows which."
9
+ requires-python = ">=3.10"
10
+ license = "MIT"
11
+ keywords = ["ai", "safety", "boundary", "inference", "type-system"]
12
+ classifiers = [
13
+ "Development Status :: 3 - Alpha",
14
+ "Intended Audience :: Developers",
15
+ "Topic :: Software Development :: Libraries",
16
+ "Programming Language :: Python :: 3.10",
17
+ "Programming Language :: Python :: 3.11",
18
+ "Programming Language :: Python :: 3.12",
19
+ "Programming Language :: Python :: 3.13",
20
+ ]
21
+
22
+ [project.urls]
23
+ Homepage = "https://github.com/knoxvilledatabase/origin"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,242 @@
1
+ """Tests for Origin's Python implementation."""
2
+
3
+ import pytest
4
+ from dataclasses import dataclass
5
+ from origin_lang import Value, boundary
6
+ from origin_lang.value import match, BoundaryError
7
+
8
+
9
+ # -- Domain types --
10
+
11
+ @dataclass
12
+ class Diagnosis:
13
+ condition: str
14
+ icd_code: str
15
+ confidence: float
16
+
17
+
18
+ @boundary
19
+ class LowConfidence:
20
+ confidence: float
21
+ threshold: float
22
+
23
+
24
+ @boundary
25
+ class Hallucinated:
26
+ claim: str
27
+ evidence_score: float
28
+
29
+
30
+ @boundary
31
+ class OutOfDomain:
32
+ distance: float
33
+
34
+
35
+ # -- Construction --
36
+
37
+ class TestConstruction:
38
+ def test_interior(self):
39
+ v = Value.interior(42)
40
+ assert v.is_interior
41
+ assert not v.is_boundary
42
+
43
+ def test_boundary(self):
44
+ v = Value.boundary(LowConfidence(0.3, 0.85), last="partial result")
45
+ assert v.is_boundary
46
+ assert not v.is_interior
47
+
48
+ def test_boundary_requires_last(self):
49
+ with pytest.raises(ValueError, match="requires last"):
50
+ Value.boundary(LowConfidence(0.3, 0.85), last=None)
51
+
52
+
53
+ # -- The point: last is always preserved --
54
+
55
+ class TestLastPreserved:
56
+ def test_last_carries_diagnosis(self):
57
+ """The moment: 'I've never had this before. I always lost that value.'"""
58
+ diagnosis = Diagnosis("Pneumonia", "J18.9", 0.61)
59
+ v = Value.boundary(
60
+ LowConfidence(confidence=0.61, threshold=0.85),
61
+ last=diagnosis,
62
+ )
63
+
64
+ m = match(v)
65
+ assert isinstance(m, Value.Boundary)
66
+ assert m.last.condition == "Pneumonia"
67
+ assert m.last.confidence == 0.61
68
+ assert m.reason.confidence == 0.61
69
+
70
+ def test_last_carries_through_hallucination(self):
71
+ diagnosis = Diagnosis("Time travel syndrome", "Z99.99", 0.03)
72
+ v = Value.boundary(
73
+ Hallucinated(claim="Time travel syndrome", evidence_score=0.03),
74
+ last=diagnosis,
75
+ )
76
+
77
+ m = match(v)
78
+ assert isinstance(m, Value.Boundary)
79
+ assert m.last.condition == "Time travel syndrome"
80
+ assert m.reason.evidence_score == 0.03
81
+
82
+ def test_interior_has_value(self):
83
+ diagnosis = Diagnosis("ACS", "I21.9", 0.92)
84
+ v = Value.interior(diagnosis)
85
+
86
+ m = match(v)
87
+ assert isinstance(m, Value.Interior)
88
+ assert m.value.condition == "ACS"
89
+
90
+
91
+ # -- Pattern matching (Python 3.10+) --
92
+
93
+ class TestPatternMatching:
94
+ def test_match_interior(self):
95
+ v = Value.interior(Diagnosis("ACS", "I21.9", 0.92))
96
+
97
+ result = match(v)
98
+ match result:
99
+ case Value.Interior(d):
100
+ assert d.condition == "ACS"
101
+ case _:
102
+ pytest.fail("expected Interior")
103
+
104
+ def test_match_boundary_with_last(self):
105
+ diagnosis = Diagnosis("Pneumonia", "J18.9", 0.61)
106
+ v = Value.boundary(
107
+ LowConfidence(confidence=0.61, threshold=0.85),
108
+ last=diagnosis,
109
+ )
110
+
111
+ result = match(v)
112
+ match result:
113
+ case Value.Boundary(LowConfidence(confidence=c, threshold=t), last=d):
114
+ assert c == 0.61
115
+ assert t == 0.85
116
+ assert d.condition == "Pneumonia"
117
+ case _:
118
+ pytest.fail("expected Boundary with LowConfidence")
119
+
120
+ def test_match_different_boundary_kinds(self):
121
+ v1 = Value.boundary(
122
+ LowConfidence(0.3, 0.85),
123
+ last=Diagnosis("Unknown", "R69", 0.3),
124
+ )
125
+ v2 = Value.boundary(
126
+ Hallucinated("Temporal displacement", 0.03),
127
+ last=Diagnosis("Temporal displacement", "Z99.99", 0.03),
128
+ )
129
+
130
+ m1 = match(v1)
131
+ m2 = match(v2)
132
+
133
+ match m1:
134
+ case Value.Boundary(LowConfidence(), last=d):
135
+ assert d.condition == "Unknown"
136
+ case _:
137
+ pytest.fail("expected LowConfidence")
138
+
139
+ match m2:
140
+ case Value.Boundary(Hallucinated(claim=c), last=d):
141
+ assert c == "Temporal displacement"
142
+ assert d.condition == "Temporal displacement"
143
+ case _:
144
+ pytest.fail("expected Hallucinated")
145
+
146
+
147
+ # -- Unwrap --
148
+
149
+ class TestUnwrap:
150
+ def test_unwrap_interior(self):
151
+ v = Value.interior(42)
152
+ assert v.unwrap() == 42
153
+
154
+ def test_unwrap_boundary_raises(self):
155
+ v = Value.boundary(LowConfidence(0.3, 0.85), last="partial")
156
+ with pytest.raises(BoundaryError) as exc_info:
157
+ v.unwrap()
158
+ # Even the exception preserves the information
159
+ assert exc_info.value.last == "partial"
160
+ assert exc_info.value.reason == LowConfidence(0.3, 0.85)
161
+
162
+
163
+ # -- or_default --
164
+
165
+ class TestOrDefault:
166
+ def test_interior_ignores_fallback(self):
167
+ v = Value.interior(42)
168
+ assert v.or_default(0) == 42
169
+
170
+ def test_boundary_uses_fallback(self):
171
+ v = Value.boundary(LowConfidence(0.3, 0.85), last="partial")
172
+ assert v.or_default("fallback") == "fallback"
173
+
174
+
175
+ # -- Map --
176
+
177
+ class TestMap:
178
+ def test_map_interior(self):
179
+ v = Value.interior(5)
180
+ result = v.map(lambda x: x * 2)
181
+ assert result.is_interior
182
+ assert result.unwrap() == 10
183
+
184
+ def test_map_boundary_preserves_reason_and_maps_last(self):
185
+ v = Value.boundary(LowConfidence(0.3, 0.85), last=5)
186
+ result = v.map(lambda x: x * 2)
187
+ assert result.is_boundary
188
+ m = match(result)
189
+ assert m.reason == LowConfidence(0.3, 0.85)
190
+ assert m.last == 10
191
+
192
+
193
+ # -- Repr --
194
+
195
+ class TestRepr:
196
+ def test_interior_repr(self):
197
+ v = Value.interior(42)
198
+ assert repr(v) == "Value.Interior(42)"
199
+
200
+ def test_boundary_repr(self):
201
+ v = Value.boundary(LowConfidence(0.3, 0.85), last="partial")
202
+ assert "Boundary" in repr(v)
203
+ assert "last=" in repr(v)
204
+
205
+
206
+ # -- Pipeline demo --
207
+
208
+ class TestPipeline:
209
+ """Same scenario as the Rust comparison: 5-layer healthcare pipeline."""
210
+
211
+ def infer(self, symptoms: list[str]) -> Value[Diagnosis, LowConfidence]:
212
+ if not symptoms:
213
+ return Value.boundary(
214
+ OutOfDomain(distance=1.0),
215
+ last=Diagnosis("Unknown", "R69", 0.0),
216
+ )
217
+ if "chest pain" in symptoms:
218
+ return Value.interior(Diagnosis("ACS", "I21.9", 0.92))
219
+ return Value.boundary(
220
+ LowConfidence(confidence=0.30, threshold=0.50),
221
+ last=Diagnosis("Nonspecific", "R69", 0.30),
222
+ )
223
+
224
+ def test_interior_pipeline(self):
225
+ result = self.infer(["chest pain"])
226
+ assert result.is_interior
227
+ assert result.unwrap().condition == "ACS"
228
+
229
+ def test_boundary_preserves_last(self):
230
+ result = self.infer(["fatigue"])
231
+ assert result.is_boundary
232
+ m = match(result)
233
+ # This is the moment. The diagnosis is still here.
234
+ assert m.last.condition == "Nonspecific"
235
+ assert m.last.confidence == 0.30
236
+
237
+ def test_empty_symptoms_out_of_domain(self):
238
+ result = self.infer([])
239
+ assert result.is_boundary
240
+ m = match(result)
241
+ assert isinstance(m.reason, OutOfDomain)
242
+ assert m.last.condition == "Unknown"