project-xox 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,37 @@
1
+ # Agent-internal workspace
2
+ .agents/
3
+
4
+ # Python virtual environments
5
+ .venv/
6
+ venv/
7
+
8
+ # Build outputs & packaging artifacts
9
+ target/
10
+ dist/
11
+ build/
12
+
13
+ # Python caches and test artifacts
14
+ __pycache__/
15
+ *.py[cod]
16
+ .pytest_cache/
17
+ .mypy_cache/
18
+ .ruff_cache/
19
+ .coverage
20
+ htmlcov/
21
+
22
+ # Editor and OS files
23
+ .idea/
24
+ .vscode/
25
+ .DS_Store
26
+ *.swp
27
+ *.swo
28
+ *.tmp
29
+ *.log
30
+
31
+ # Secrets and environment files
32
+ .env
33
+ .env.*
34
+ *.pem
35
+ *.key
36
+ *.p12
37
+ *.pfx
@@ -0,0 +1,132 @@
1
+ # This file is automatically @generated by Cargo.
2
+ # It is not intended for manual editing.
3
+ version = 4
4
+
5
+ [[package]]
6
+ name = "heck"
7
+ version = "0.5.0"
8
+ source = "registry+https://github.com/rust-lang/crates.io-index"
9
+ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
10
+
11
+ [[package]]
12
+ name = "libc"
13
+ version = "0.2.189"
14
+ source = "registry+https://github.com/rust-lang/crates.io-index"
15
+ checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
16
+
17
+ [[package]]
18
+ name = "once_cell"
19
+ version = "1.21.4"
20
+ source = "registry+https://github.com/rust-lang/crates.io-index"
21
+ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
22
+
23
+ [[package]]
24
+ name = "portable-atomic"
25
+ version = "1.15.0"
26
+ source = "registry+https://github.com/rust-lang/crates.io-index"
27
+ checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85"
28
+
29
+ [[package]]
30
+ name = "proc-macro2"
31
+ version = "1.0.107"
32
+ source = "registry+https://github.com/rust-lang/crates.io-index"
33
+ checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
34
+ dependencies = [
35
+ "unicode-ident",
36
+ ]
37
+
38
+ [[package]]
39
+ name = "pyo3"
40
+ version = "0.29.2"
41
+ source = "registry+https://github.com/rust-lang/crates.io-index"
42
+ checksum = "4688ddedf473e32662b9b067670129a8afb8c18e351482c70d62ba4a88171e8b"
43
+ dependencies = [
44
+ "libc",
45
+ "once_cell",
46
+ "portable-atomic",
47
+ "pyo3-build-config",
48
+ "pyo3-ffi",
49
+ "pyo3-macros",
50
+ ]
51
+
52
+ [[package]]
53
+ name = "pyo3-build-config"
54
+ version = "0.29.2"
55
+ source = "registry+https://github.com/rust-lang/crates.io-index"
56
+ checksum = "f41027e41b4bd03f6e60f9f417fe24a6341a6bb744edd62b6f709f2a52ea30e9"
57
+ dependencies = [
58
+ "target-lexicon",
59
+ ]
60
+
61
+ [[package]]
62
+ name = "pyo3-ffi"
63
+ version = "0.29.2"
64
+ source = "registry+https://github.com/rust-lang/crates.io-index"
65
+ checksum = "e591a95526fead067432c3b3a33fc74770b87b1e04e73671090d9c2055a2b327"
66
+ dependencies = [
67
+ "libc",
68
+ "pyo3-build-config",
69
+ ]
70
+
71
+ [[package]]
72
+ name = "pyo3-macros"
73
+ version = "0.29.2"
74
+ source = "registry+https://github.com/rust-lang/crates.io-index"
75
+ checksum = "73225868fc1cd84eef2c3c230ddb91273bf1de46aeb8a4248da76d32a0924a1c"
76
+ dependencies = [
77
+ "proc-macro2",
78
+ "pyo3-macros-backend",
79
+ "quote",
80
+ "syn",
81
+ ]
82
+
83
+ [[package]]
84
+ name = "pyo3-macros-backend"
85
+ version = "0.29.2"
86
+ source = "registry+https://github.com/rust-lang/crates.io-index"
87
+ checksum = "571575aa3749fa6216757dd47d2a3e7ef360f329a40f0666a9fbd14889024952"
88
+ dependencies = [
89
+ "heck",
90
+ "proc-macro2",
91
+ "quote",
92
+ "syn",
93
+ ]
94
+
95
+ [[package]]
96
+ name = "quote"
97
+ version = "1.0.47"
98
+ source = "registry+https://github.com/rust-lang/crates.io-index"
99
+ checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
100
+ dependencies = [
101
+ "proc-macro2",
102
+ ]
103
+
104
+ [[package]]
105
+ name = "syn"
106
+ version = "2.0.119"
107
+ source = "registry+https://github.com/rust-lang/crates.io-index"
108
+ checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
109
+ dependencies = [
110
+ "proc-macro2",
111
+ "quote",
112
+ "unicode-ident",
113
+ ]
114
+
115
+ [[package]]
116
+ name = "target-lexicon"
117
+ version = "0.13.5"
118
+ source = "registry+https://github.com/rust-lang/crates.io-index"
119
+ checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
120
+
121
+ [[package]]
122
+ name = "unicode-ident"
123
+ version = "1.0.24"
124
+ source = "registry+https://github.com/rust-lang/crates.io-index"
125
+ checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
126
+
127
+ [[package]]
128
+ name = "xox"
129
+ version = "0.1.0"
130
+ dependencies = [
131
+ "pyo3",
132
+ ]
@@ -0,0 +1,23 @@
1
+ [package]
2
+ name = "xox"
3
+ version = "0.1.0"
4
+ edition = "2021"
5
+ rust-version = "1.83"
6
+ exclude = [
7
+ ".agents",
8
+ ".git",
9
+ ".github",
10
+ ".venv",
11
+ ".pytest_cache",
12
+ "target",
13
+ "tests",
14
+ "docs",
15
+ ]
16
+ readme = "README.md"
17
+
18
+ [lib]
19
+ name = "xox"
20
+ crate-type = ["cdylib", "rlib"]
21
+
22
+ [dependencies]
23
+ pyo3 = { version = "0.29", features = ["extension-module"] }
@@ -0,0 +1,176 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriement of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
@@ -0,0 +1,273 @@
1
+ Metadata-Version: 2.4
2
+ Name: project-xox
3
+ Version: 0.1.0
4
+ Classifier: Programming Language :: Python :: 3
5
+ Classifier: Programming Language :: Python :: 3 :: Only
6
+ Classifier: Programming Language :: Python :: 3.12
7
+ Classifier: Programming Language :: Python :: 3.13
8
+ Classifier: Programming Language :: Python :: 3.14
9
+ Classifier: Programming Language :: Python :: Implementation :: CPython
10
+ Classifier: Programming Language :: Rust
11
+ Classifier: License :: OSI Approved :: Apache Software License
12
+ Classifier: Operating System :: POSIX :: Linux
13
+ License-File: LICENSE
14
+ Summary: Tri-state epistemic uncertainty engine preserving explicit True, False, and Unknown decision semantics
15
+ License-Expression: Apache-2.0
16
+ Requires-Python: >=3.12
17
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
18
+ Project-URL: Documentation, https://github.com/linuxx88/XoX/blob/main/docs/04_api/CORE_API.md
19
+ Project-URL: Homepage, https://github.com/linuxx88/XoX
20
+
21
+ # XoX
22
+
23
+ Tri-state epistemic uncertainty engine preserving explicit `True`, `False`, and `Unknown` decision semantics in Python.
24
+
25
+ ---
26
+
27
+ ## The Problem
28
+
29
+ Standard boolean logic provides only two states: `True` and `False`. When a system evaluates an assertion—such as whether an account is authorized, whether a remote record exists, or whether an external precondition holds—the state of that assertion is often indeterminate due to incomplete or unreachable information.
30
+
31
+ Coercing an unestablished proposition into `False` (or `True`) conflates **known falsity** with **absence of knowledge**. This silent collapse can introduce subtle defects, improper fallbacks, or security vulnerabilities where systems act on assumptions rather than established truth.
32
+
33
+ XoX provides a principled tri-state logical model where uncertainty is preserved across function boundaries, combined using Strong Kleene logic, and collapsed into Python booleans only when the application explicitly defines a fallback policy.
34
+
35
+ ---
36
+
37
+ ## Semantic Model
38
+
39
+ XoX represents three distinct, immutable logical states:
40
+
41
+ - **`xox.TRUE`**: The proposition is definitively established as true.
42
+ - **`xox.FALSE`**: The proposition is definitively refuted as false.
43
+ - **`xox.UNKNOWN`**: The proposition has not been established as true or false.
44
+
45
+ `Unknown` carries no intrinsic bias toward `True` or `False`.
46
+
47
+ ### What `UNKNOWN` Is Not
48
+
49
+ To prevent semantic confusion, `xox.UNKNOWN` has strict boundaries:
50
+ - **Not `None`**: It represents an unresolved proposition, not the absence of an object.
51
+ - **Not an exception**: Runtime errors, system failures, and contract violations remain standard Python exceptions.
52
+ - **Not a pending async state**: It is an evaluated outcome, not an incomplete future or promise.
53
+ - **Not a timeout**: A timeout is an execution event, whereas `UNKNOWN` is a state of knowledge.
54
+ - **Not probabilistic confidence**: It indicates that truth has not been established, not a probability score.
55
+ - **Not an action directive**: `UNKNOWN` does not intrinsically mean retry, deny, allow, wait, fail, or default. Any action taken in response to uncertainty is defined strictly by caller policy.
56
+
57
+ ---
58
+
59
+ ## Installation
60
+
61
+ ```bash
62
+ pip install project-xox
63
+ ```
64
+
65
+ > **Note**: The package distribution name on PyPI is `project-xox`, while the Python import name is `xox`.
66
+
67
+ ---
68
+
69
+ ## Basic Usage
70
+
71
+ ```python
72
+ import xox
73
+
74
+ # Canonical value constants
75
+ t = xox.TRUE
76
+ f = xox.FALSE
77
+ u = xox.UNKNOWN
78
+
79
+ # State inspection
80
+ if t.is_true():
81
+ print("Definitely True")
82
+
83
+ if f.is_false():
84
+ print("Definitely False")
85
+
86
+ if u.is_unknown():
87
+ print("State is indeterminate")
88
+ ```
89
+
90
+ ---
91
+
92
+ ## Strict Domain Separation & Truthiness Prohibition
93
+
94
+ Python `bool` and `xox.XoX` belong to strictly separated domains. Crossing between them requires explicit operations.
95
+
96
+ ### Truthiness is Prohibited
97
+
98
+ XoX values prohibit direct boolean coercion (`__bool__`). Evaluating an `XoX` instance in an `if`, `while`, `bool()`, `and`, `or`, or `not` context raises a `TypeError`:
99
+
100
+ ```python
101
+ val = xox.UNKNOWN
102
+
103
+ # Prohibited - raises TypeError:
104
+ # if val:
105
+ # ...
106
+ # bool(val)
107
+ ```
108
+
109
+ This prevents uncertainty from silently collapsing into boolean control flow.
110
+
111
+ ### Domain Equality Isolation
112
+
113
+ XoX values never compare equal to native Python booleans:
114
+
115
+ ```python
116
+ assert (xox.TRUE == True) is False
117
+ assert (xox.FALSE == False) is False
118
+ assert (xox.UNKNOWN == False) is False
119
+ ```
120
+
121
+ ---
122
+
123
+ ## Ingress: Bool to XoX
124
+
125
+ To bring a Python boolean into the XoX domain, use `xox.from_bool()`:
126
+
127
+ ```python
128
+ xox_val = xox.from_bool(True) # returns xox.TRUE
129
+ xox_val = xox.from_bool(False) # returns xox.FALSE
130
+ ```
131
+
132
+ `xox.from_bool()` accepts only exact Python `bool` instances (`True` or `False`). Non-boolean values (including `1`, `0`, `None`, or truthy objects) raise a `TypeError`.
133
+
134
+ ---
135
+
136
+ ## Strong Kleene Logic Operations
137
+
138
+ XoX implements standard Strong Kleene ($K_3$) logic with host-level short-circuiting.
139
+
140
+ ### Unary NOT (`~`)
141
+
142
+ The bitwise inversion operator `~` performs Strong Kleene negation:
143
+
144
+ ```python
145
+ assert ~xox.TRUE == xox.FALSE
146
+ assert ~xox.FALSE == xox.TRUE
147
+ assert ~xox.UNKNOWN == xox.UNKNOWN
148
+ ```
149
+
150
+ ### Lazy Conjunction (`lazy_and`) & Disjunction (`lazy_or`)
151
+
152
+ Python evaluates binary operator operands (`&`, `|`) eagerly. To guarantee real short-circuit evaluation without evaluating unneeded branches, conjunction and disjunction require zero-argument callables:
153
+
154
+ ```python
155
+ # Conjunction: FALSE short-circuits; RHS is never called
156
+ result = xox.FALSE.lazy_and(lambda: expensive_query()) # returns xox.FALSE
157
+
158
+ # Disjunction: TRUE short-circuits; RHS is never called
159
+ result = xox.TRUE.lazy_or(lambda: expensive_query()) # returns xox.TRUE
160
+
161
+ # When LHS cannot determine the outcome, RHS is executed exactly once:
162
+ result = xox.UNKNOWN.lazy_and(lambda: xox.TRUE) # returns xox.UNKNOWN
163
+ result = xox.UNKNOWN.lazy_or(lambda: xox.TRUE) # returns xox.TRUE
164
+ ```
165
+
166
+ - **Short-circuiting**: If the outcome is determined by the LHS, the RHS callable executes **zero** times.
167
+ - **Evaluation**: When needed, the RHS callable executes **exactly once** and must return an `XoX` instance.
168
+ - **Exceptions**: Exceptions raised inside evaluated RHS callables propagate normally as standard Python exceptions.
169
+
170
+ ---
171
+
172
+ ## Egress: Collapsing Uncertainty to Python Bool
173
+
174
+ When application code must interface with a native boolean API, collapse the `XoX` value using `collapse_or()` with an explicit fallback callable:
175
+
176
+ ```python
177
+ # TRUE and FALSE resolve directly without invoking fallback
178
+ assert xox.TRUE.collapse_or(lambda: False) is True
179
+ assert xox.FALSE.collapse_or(lambda: True) is False
180
+
181
+ # UNKNOWN executes the fallback callable exactly once
182
+ decision = xox.UNKNOWN.collapse_or(lambda: False) # returns False
183
+ ```
184
+
185
+ - **Caller-Owned Policy**: The fallback callable represents an application policy decision (such as fail-closed or optimistic pass), not newly discovered truth.
186
+ - **Lazy Execution**: The fallback callable is evaluated only when the value is `xox.UNKNOWN`.
187
+ - **Type Contract**: The fallback callable must return an exact Python `bool` (`True` or `False`). Returning any other type raises a `TypeError`.
188
+
189
+ ---
190
+
191
+ ## Realistic Example: External Verification Gate
192
+
193
+ ```python
194
+ import xox
195
+ import logging
196
+
197
+ def verify_remote_entitlement(user_id: str) -> xox.XoX:
198
+ """Queries an upstream service; returns UNKNOWN if indeterminate."""
199
+ try:
200
+ response = call_auth_service(user_id)
201
+ if response.status == "AUTHORIZED":
202
+ return xox.TRUE
203
+ elif response.status == "DENIED":
204
+ return xox.FALSE
205
+ else:
206
+ # Service responded, but entitlement status is indeterminate
207
+ return xox.UNKNOWN
208
+ except NetworkTimeoutError:
209
+ # Runtime transport failure is handled by application logic
210
+ return xox.UNKNOWN
211
+
212
+ def handle_user_request(user_id: str):
213
+ entitlement = verify_remote_entitlement(user_id)
214
+
215
+ # 1. Explicit three-way branch
216
+ if entitlement.is_true():
217
+ grant_access()
218
+ elif entitlement.is_false():
219
+ deny_access("Explicitly denied by auth policy")
220
+ else: # entitlement.is_unknown()
221
+ # The reaction to UNKNOWN is owned by the application:
222
+ queue_for_manual_review(user_id)
223
+
224
+ # 2. Or explicit policy collapse at a boolean boundary (e.g., fail-closed)
225
+ def fail_closed_policy() -> bool:
226
+ logging.warning("Entitlement indeterminate for %s; applying fail-closed default.", user_id)
227
+ return False
228
+
229
+ can_proceed = entitlement.collapse_or(fail_closed_policy)
230
+ if can_proceed:
231
+ execute_privileged_task()
232
+ ```
233
+
234
+ ---
235
+
236
+ ## Project Status: CORE 0.1.0
237
+
238
+ XoX `0.1.0` delivers the minimal public `CORE` semantic surface:
239
+ - Singleton constants: `xox.TRUE`, `xox.FALSE`, `xox.UNKNOWN`.
240
+ - Canonical ingress: `xox.from_bool()`.
241
+ - State inspection: `.is_true()`, `.is_false()`, `.is_unknown()`, and `==`.
242
+ - Strong Kleene logic: `~` (NOT), `.lazy_and()`, and `.lazy_or()`.
243
+ - Explicit egress: `.collapse_or()`.
244
+ - Strict domain separation and truthiness blocking.
245
+
246
+ Advanced capabilities (such as auditable policy tokens, evidence provenance tracking, and distributed consensus negotiation) are intentionally outside the scope of `CORE` and are not included in this release.
247
+
248
+ ---
249
+
250
+ ## Supported Platforms & Scope
251
+
252
+ - **Python Interpreters:** CPython 3.12, 3.13, and 3.14 (version-specific CPython extension wheels).
253
+ - **Supported Platform:** Linux x86_64.
254
+ - **Binary Compatibility Baseline:** `manylinux_2_34_x86_64` (glibc 2.34+).
255
+ - **Source Build MSRV:** Rust 1.83+.
256
+ - **Unclaimed / Unsupported:** macOS, Windows, Linux aarch64, musllinux, PyPy, GraalPy, and free-threaded CPython builds are not currently claimed or supported.
257
+
258
+ > **Note**: The binary compatibility baseline reflects the currently audited distribution artifact floor, not an intrinsic semantic limitation of XoX logic.
259
+
260
+ ---
261
+
262
+ ## Documentation
263
+
264
+ - [Normative Public CORE API Specification](docs/04_api/CORE_API.md)
265
+ - [Foundational Guarantees & Philosophy](docs/00_foundations/GUARANTEES.md)
266
+ - [Runtime & Portability Model](docs/03_runtime/PORTABILITY_MODEL.md)
267
+
268
+ ---
269
+
270
+ ## License
271
+
272
+ XoX is licensed under the [Apache-2.0 License](LICENSE).
273
+
@@ -0,0 +1,252 @@
1
+ # XoX
2
+
3
+ Tri-state epistemic uncertainty engine preserving explicit `True`, `False`, and `Unknown` decision semantics in Python.
4
+
5
+ ---
6
+
7
+ ## The Problem
8
+
9
+ Standard boolean logic provides only two states: `True` and `False`. When a system evaluates an assertion—such as whether an account is authorized, whether a remote record exists, or whether an external precondition holds—the state of that assertion is often indeterminate due to incomplete or unreachable information.
10
+
11
+ Coercing an unestablished proposition into `False` (or `True`) conflates **known falsity** with **absence of knowledge**. This silent collapse can introduce subtle defects, improper fallbacks, or security vulnerabilities where systems act on assumptions rather than established truth.
12
+
13
+ XoX provides a principled tri-state logical model where uncertainty is preserved across function boundaries, combined using Strong Kleene logic, and collapsed into Python booleans only when the application explicitly defines a fallback policy.
14
+
15
+ ---
16
+
17
+ ## Semantic Model
18
+
19
+ XoX represents three distinct, immutable logical states:
20
+
21
+ - **`xox.TRUE`**: The proposition is definitively established as true.
22
+ - **`xox.FALSE`**: The proposition is definitively refuted as false.
23
+ - **`xox.UNKNOWN`**: The proposition has not been established as true or false.
24
+
25
+ `Unknown` carries no intrinsic bias toward `True` or `False`.
26
+
27
+ ### What `UNKNOWN` Is Not
28
+
29
+ To prevent semantic confusion, `xox.UNKNOWN` has strict boundaries:
30
+ - **Not `None`**: It represents an unresolved proposition, not the absence of an object.
31
+ - **Not an exception**: Runtime errors, system failures, and contract violations remain standard Python exceptions.
32
+ - **Not a pending async state**: It is an evaluated outcome, not an incomplete future or promise.
33
+ - **Not a timeout**: A timeout is an execution event, whereas `UNKNOWN` is a state of knowledge.
34
+ - **Not probabilistic confidence**: It indicates that truth has not been established, not a probability score.
35
+ - **Not an action directive**: `UNKNOWN` does not intrinsically mean retry, deny, allow, wait, fail, or default. Any action taken in response to uncertainty is defined strictly by caller policy.
36
+
37
+ ---
38
+
39
+ ## Installation
40
+
41
+ ```bash
42
+ pip install project-xox
43
+ ```
44
+
45
+ > **Note**: The package distribution name on PyPI is `project-xox`, while the Python import name is `xox`.
46
+
47
+ ---
48
+
49
+ ## Basic Usage
50
+
51
+ ```python
52
+ import xox
53
+
54
+ # Canonical value constants
55
+ t = xox.TRUE
56
+ f = xox.FALSE
57
+ u = xox.UNKNOWN
58
+
59
+ # State inspection
60
+ if t.is_true():
61
+ print("Definitely True")
62
+
63
+ if f.is_false():
64
+ print("Definitely False")
65
+
66
+ if u.is_unknown():
67
+ print("State is indeterminate")
68
+ ```
69
+
70
+ ---
71
+
72
+ ## Strict Domain Separation & Truthiness Prohibition
73
+
74
+ Python `bool` and `xox.XoX` belong to strictly separated domains. Crossing between them requires explicit operations.
75
+
76
+ ### Truthiness is Prohibited
77
+
78
+ XoX values prohibit direct boolean coercion (`__bool__`). Evaluating an `XoX` instance in an `if`, `while`, `bool()`, `and`, `or`, or `not` context raises a `TypeError`:
79
+
80
+ ```python
81
+ val = xox.UNKNOWN
82
+
83
+ # Prohibited - raises TypeError:
84
+ # if val:
85
+ # ...
86
+ # bool(val)
87
+ ```
88
+
89
+ This prevents uncertainty from silently collapsing into boolean control flow.
90
+
91
+ ### Domain Equality Isolation
92
+
93
+ XoX values never compare equal to native Python booleans:
94
+
95
+ ```python
96
+ assert (xox.TRUE == True) is False
97
+ assert (xox.FALSE == False) is False
98
+ assert (xox.UNKNOWN == False) is False
99
+ ```
100
+
101
+ ---
102
+
103
+ ## Ingress: Bool to XoX
104
+
105
+ To bring a Python boolean into the XoX domain, use `xox.from_bool()`:
106
+
107
+ ```python
108
+ xox_val = xox.from_bool(True) # returns xox.TRUE
109
+ xox_val = xox.from_bool(False) # returns xox.FALSE
110
+ ```
111
+
112
+ `xox.from_bool()` accepts only exact Python `bool` instances (`True` or `False`). Non-boolean values (including `1`, `0`, `None`, or truthy objects) raise a `TypeError`.
113
+
114
+ ---
115
+
116
+ ## Strong Kleene Logic Operations
117
+
118
+ XoX implements standard Strong Kleene ($K_3$) logic with host-level short-circuiting.
119
+
120
+ ### Unary NOT (`~`)
121
+
122
+ The bitwise inversion operator `~` performs Strong Kleene negation:
123
+
124
+ ```python
125
+ assert ~xox.TRUE == xox.FALSE
126
+ assert ~xox.FALSE == xox.TRUE
127
+ assert ~xox.UNKNOWN == xox.UNKNOWN
128
+ ```
129
+
130
+ ### Lazy Conjunction (`lazy_and`) & Disjunction (`lazy_or`)
131
+
132
+ Python evaluates binary operator operands (`&`, `|`) eagerly. To guarantee real short-circuit evaluation without evaluating unneeded branches, conjunction and disjunction require zero-argument callables:
133
+
134
+ ```python
135
+ # Conjunction: FALSE short-circuits; RHS is never called
136
+ result = xox.FALSE.lazy_and(lambda: expensive_query()) # returns xox.FALSE
137
+
138
+ # Disjunction: TRUE short-circuits; RHS is never called
139
+ result = xox.TRUE.lazy_or(lambda: expensive_query()) # returns xox.TRUE
140
+
141
+ # When LHS cannot determine the outcome, RHS is executed exactly once:
142
+ result = xox.UNKNOWN.lazy_and(lambda: xox.TRUE) # returns xox.UNKNOWN
143
+ result = xox.UNKNOWN.lazy_or(lambda: xox.TRUE) # returns xox.TRUE
144
+ ```
145
+
146
+ - **Short-circuiting**: If the outcome is determined by the LHS, the RHS callable executes **zero** times.
147
+ - **Evaluation**: When needed, the RHS callable executes **exactly once** and must return an `XoX` instance.
148
+ - **Exceptions**: Exceptions raised inside evaluated RHS callables propagate normally as standard Python exceptions.
149
+
150
+ ---
151
+
152
+ ## Egress: Collapsing Uncertainty to Python Bool
153
+
154
+ When application code must interface with a native boolean API, collapse the `XoX` value using `collapse_or()` with an explicit fallback callable:
155
+
156
+ ```python
157
+ # TRUE and FALSE resolve directly without invoking fallback
158
+ assert xox.TRUE.collapse_or(lambda: False) is True
159
+ assert xox.FALSE.collapse_or(lambda: True) is False
160
+
161
+ # UNKNOWN executes the fallback callable exactly once
162
+ decision = xox.UNKNOWN.collapse_or(lambda: False) # returns False
163
+ ```
164
+
165
+ - **Caller-Owned Policy**: The fallback callable represents an application policy decision (such as fail-closed or optimistic pass), not newly discovered truth.
166
+ - **Lazy Execution**: The fallback callable is evaluated only when the value is `xox.UNKNOWN`.
167
+ - **Type Contract**: The fallback callable must return an exact Python `bool` (`True` or `False`). Returning any other type raises a `TypeError`.
168
+
169
+ ---
170
+
171
+ ## Realistic Example: External Verification Gate
172
+
173
+ ```python
174
+ import xox
175
+ import logging
176
+
177
+ def verify_remote_entitlement(user_id: str) -> xox.XoX:
178
+ """Queries an upstream service; returns UNKNOWN if indeterminate."""
179
+ try:
180
+ response = call_auth_service(user_id)
181
+ if response.status == "AUTHORIZED":
182
+ return xox.TRUE
183
+ elif response.status == "DENIED":
184
+ return xox.FALSE
185
+ else:
186
+ # Service responded, but entitlement status is indeterminate
187
+ return xox.UNKNOWN
188
+ except NetworkTimeoutError:
189
+ # Runtime transport failure is handled by application logic
190
+ return xox.UNKNOWN
191
+
192
+ def handle_user_request(user_id: str):
193
+ entitlement = verify_remote_entitlement(user_id)
194
+
195
+ # 1. Explicit three-way branch
196
+ if entitlement.is_true():
197
+ grant_access()
198
+ elif entitlement.is_false():
199
+ deny_access("Explicitly denied by auth policy")
200
+ else: # entitlement.is_unknown()
201
+ # The reaction to UNKNOWN is owned by the application:
202
+ queue_for_manual_review(user_id)
203
+
204
+ # 2. Or explicit policy collapse at a boolean boundary (e.g., fail-closed)
205
+ def fail_closed_policy() -> bool:
206
+ logging.warning("Entitlement indeterminate for %s; applying fail-closed default.", user_id)
207
+ return False
208
+
209
+ can_proceed = entitlement.collapse_or(fail_closed_policy)
210
+ if can_proceed:
211
+ execute_privileged_task()
212
+ ```
213
+
214
+ ---
215
+
216
+ ## Project Status: CORE 0.1.0
217
+
218
+ XoX `0.1.0` delivers the minimal public `CORE` semantic surface:
219
+ - Singleton constants: `xox.TRUE`, `xox.FALSE`, `xox.UNKNOWN`.
220
+ - Canonical ingress: `xox.from_bool()`.
221
+ - State inspection: `.is_true()`, `.is_false()`, `.is_unknown()`, and `==`.
222
+ - Strong Kleene logic: `~` (NOT), `.lazy_and()`, and `.lazy_or()`.
223
+ - Explicit egress: `.collapse_or()`.
224
+ - Strict domain separation and truthiness blocking.
225
+
226
+ Advanced capabilities (such as auditable policy tokens, evidence provenance tracking, and distributed consensus negotiation) are intentionally outside the scope of `CORE` and are not included in this release.
227
+
228
+ ---
229
+
230
+ ## Supported Platforms & Scope
231
+
232
+ - **Python Interpreters:** CPython 3.12, 3.13, and 3.14 (version-specific CPython extension wheels).
233
+ - **Supported Platform:** Linux x86_64.
234
+ - **Binary Compatibility Baseline:** `manylinux_2_34_x86_64` (glibc 2.34+).
235
+ - **Source Build MSRV:** Rust 1.83+.
236
+ - **Unclaimed / Unsupported:** macOS, Windows, Linux aarch64, musllinux, PyPy, GraalPy, and free-threaded CPython builds are not currently claimed or supported.
237
+
238
+ > **Note**: The binary compatibility baseline reflects the currently audited distribution artifact floor, not an intrinsic semantic limitation of XoX logic.
239
+
240
+ ---
241
+
242
+ ## Documentation
243
+
244
+ - [Normative Public CORE API Specification](docs/04_api/CORE_API.md)
245
+ - [Foundational Guarantees & Philosophy](docs/00_foundations/GUARANTEES.md)
246
+ - [Runtime & Portability Model](docs/03_runtime/PORTABILITY_MODEL.md)
247
+
248
+ ---
249
+
250
+ ## License
251
+
252
+ XoX is licensed under the [Apache-2.0 License](LICENSE).
@@ -0,0 +1,31 @@
1
+ [build-system]
2
+ requires = ["maturin>=1.5,<2.0"]
3
+ build-backend = "maturin"
4
+
5
+ [project]
6
+ name = "project-xox"
7
+ version = "0.1.0"
8
+ description = "Tri-state epistemic uncertainty engine preserving explicit True, False, and Unknown decision semantics"
9
+ readme = "README.md"
10
+ requires-python = ">=3.12"
11
+ license = "Apache-2.0"
12
+ license-files = ["LICENSE"]
13
+ classifiers = [
14
+ "Programming Language :: Python :: 3",
15
+ "Programming Language :: Python :: 3 :: Only",
16
+ "Programming Language :: Python :: 3.12",
17
+ "Programming Language :: Python :: 3.13",
18
+ "Programming Language :: Python :: 3.14",
19
+ "Programming Language :: Python :: Implementation :: CPython",
20
+ "Programming Language :: Rust",
21
+ "License :: OSI Approved :: Apache Software License",
22
+ "Operating System :: POSIX :: Linux",
23
+ ]
24
+
25
+ [project.urls]
26
+ Homepage = "https://github.com/linuxx88/XoX"
27
+ Documentation = "https://github.com/linuxx88/XoX/blob/main/docs/04_api/CORE_API.md"
28
+
29
+ [tool.maturin]
30
+ module-name = "xox"
31
+ features = ["pyo3/extension-module"]
@@ -0,0 +1,161 @@
1
+ //! PyO3 bindings exposing the XoX CORE API to Python.
2
+
3
+ use pyo3::exceptions::PyTypeError;
4
+ use pyo3::prelude::*;
5
+ use pyo3::types::PyBool;
6
+
7
+ use crate::core::XoXValue;
8
+
9
+ /// Python representation of an immutable XoX tri-state logical value.
10
+ #[pyclass(name = "XoX", frozen, from_py_object)]
11
+ #[derive(Clone, Copy, Debug)]
12
+ pub struct PyXoX(pub XoXValue);
13
+
14
+ #[pymethods]
15
+ impl PyXoX {
16
+ /// Inspect if the value is definitively True.
17
+ pub fn is_true(&self) -> bool {
18
+ self.0 == XoXValue::True
19
+ }
20
+
21
+ /// Inspect if the value is definitively False.
22
+ pub fn is_false(&self) -> bool {
23
+ self.0 == XoXValue::False
24
+ }
25
+
26
+ /// Inspect if the value is Unknown.
27
+ pub fn is_unknown(&self) -> bool {
28
+ self.0 == XoXValue::Unknown
29
+ }
30
+
31
+ /// Strong Kleene unary NOT (~).
32
+ pub fn __invert__(&self) -> Self {
33
+ PyXoX(self.0.not())
34
+ }
35
+
36
+ /// Strong Kleene lazy conjunction (AND).
37
+ pub fn lazy_and(&self, rhs: &Bound<'_, PyAny>) -> PyResult<Self> {
38
+ if !rhs.is_callable() {
39
+ return Err(PyTypeError::new_err(
40
+ "lazy_and() requires a zero-argument callable returning XoX.",
41
+ ));
42
+ }
43
+
44
+ if self.0.should_short_circuit_and() {
45
+ return Ok(PyXoX(XoXValue::False));
46
+ }
47
+
48
+ let res = rhs.call0()?;
49
+ let rhs_val = match res.extract::<PyRef<PyXoX>>() {
50
+ Ok(r) => r.0,
51
+ Err(_) => {
52
+ return Err(PyTypeError::new_err(
53
+ "RHS callable in lazy_and must return an XoX value (xox.TRUE, xox.FALSE, xox.UNKNOWN).",
54
+ ))
55
+ }
56
+ };
57
+
58
+ Ok(PyXoX(self.0.and(rhs_val)))
59
+ }
60
+
61
+ /// Strong Kleene lazy disjunction (OR).
62
+ pub fn lazy_or(&self, rhs: &Bound<'_, PyAny>) -> PyResult<Self> {
63
+ if !rhs.is_callable() {
64
+ return Err(PyTypeError::new_err(
65
+ "lazy_or() requires a zero-argument callable returning XoX.",
66
+ ));
67
+ }
68
+
69
+ if self.0.should_short_circuit_or() {
70
+ return Ok(PyXoX(XoXValue::True));
71
+ }
72
+
73
+ let res = rhs.call0()?;
74
+ let rhs_val = match res.extract::<PyRef<PyXoX>>() {
75
+ Ok(r) => r.0,
76
+ Err(_) => {
77
+ return Err(PyTypeError::new_err(
78
+ "RHS callable in lazy_or must return an XoX value (xox.TRUE, xox.FALSE, xox.UNKNOWN).",
79
+ ))
80
+ }
81
+ };
82
+
83
+ Ok(PyXoX(self.0.or(rhs_val)))
84
+ }
85
+
86
+ /// Explicit lazy collapse of uncertainty into Python bool.
87
+ pub fn collapse_or(&self, fallback: &Bound<'_, PyAny>) -> PyResult<bool> {
88
+ if !fallback.is_callable() {
89
+ return Err(PyTypeError::new_err(
90
+ "collapse_or() requires a zero-argument callable returning Python bool.",
91
+ ));
92
+ }
93
+
94
+ match self.0 {
95
+ XoXValue::True => Ok(true),
96
+ XoXValue::False => Ok(false),
97
+ XoXValue::Unknown => {
98
+ let res = fallback.call0()?;
99
+ if !res.is_exact_instance_of::<PyBool>() {
100
+ return Err(PyTypeError::new_err(
101
+ "Collapse fallback callable must return an exact Python bool (True or False).",
102
+ ));
103
+ }
104
+ res.extract::<bool>()
105
+ }
106
+ }
107
+ }
108
+
109
+ /// Explicitly block Python truthiness evaluation for all states.
110
+ pub fn __bool__(&self) -> PyResult<bool> {
111
+ Err(PyTypeError::new_err(
112
+ "Cannot use XoX value directly in boolean context. Use '.is_true()', pattern match, or '.collapse_or(lambda: fallback)' to resolve uncertainty explicitly.",
113
+ ))
114
+ }
115
+
116
+ /// State-identity equality. Comparing with Python bool evaluates to False.
117
+ pub fn __eq__(&self, other: &Bound<'_, PyAny>) -> PyResult<bool> {
118
+ if let Ok(other_xox) = other.extract::<PyRef<PyXoX>>() {
119
+ Ok(self.0 == other_xox.0)
120
+ } else {
121
+ Ok(false)
122
+ }
123
+ }
124
+
125
+ pub fn __ne__(&self, other: &Bound<'_, PyAny>) -> PyResult<bool> {
126
+ Ok(!self.__eq__(other)?)
127
+ }
128
+
129
+ /// Consistent hashing for dict/set collection isolation.
130
+ pub fn __hash__(&self) -> isize {
131
+ match self.0 {
132
+ XoXValue::True => 1_000_003,
133
+ XoXValue::False => 1_000_004,
134
+ XoXValue::Unknown => 1_000_005,
135
+ }
136
+ }
137
+
138
+ pub fn __repr__(&self) -> &'static str {
139
+ match self.0 {
140
+ XoXValue::True => "xox.TRUE",
141
+ XoXValue::False => "xox.FALSE",
142
+ XoXValue::Unknown => "xox.UNKNOWN",
143
+ }
144
+ }
145
+ }
146
+
147
+ /// Canonical single Bool-to-XoX ingress function.
148
+ #[pyfunction]
149
+ pub fn from_bool(value: &Bound<'_, PyAny>) -> PyResult<PyXoX> {
150
+ if !value.is_exact_instance_of::<PyBool>() {
151
+ return Err(PyTypeError::new_err(
152
+ "xox.from_bool() requires an exact Python bool (True or False).",
153
+ ));
154
+ }
155
+ let b: bool = value.extract()?;
156
+ if b {
157
+ Ok(PyXoX(XoXValue::True))
158
+ } else {
159
+ Ok(PyXoX(XoXValue::False))
160
+ }
161
+ }
@@ -0,0 +1,59 @@
1
+ //! Pure Rust semantic core for XoX tri-state epistemic logic.
2
+ //!
3
+ //! This module contains zero dependencies on Python, PyO3, or runtime execution environments.
4
+
5
+ /// Canonical tri-state logical value.
6
+ #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
7
+ pub enum XoXValue {
8
+ True,
9
+ False,
10
+ Unknown,
11
+ }
12
+
13
+ impl XoXValue {
14
+ /// Strong Kleene unary NOT (~).
15
+ #[inline]
16
+ pub const fn not(self) -> Self {
17
+ match self {
18
+ Self::True => Self::False,
19
+ Self::False => Self::True,
20
+ Self::Unknown => Self::Unknown,
21
+ }
22
+ }
23
+
24
+ /// Strong Kleene binary conjunction (AND) for already-evaluated operands.
25
+ #[inline]
26
+ pub const fn and(self, other: Self) -> Self {
27
+ match (self, other) {
28
+ (Self::False, _) | (_, Self::False) => Self::False,
29
+ (Self::True, Self::True) => Self::True,
30
+ (Self::True, Self::Unknown)
31
+ | (Self::Unknown, Self::True)
32
+ | (Self::Unknown, Self::Unknown) => Self::Unknown,
33
+ }
34
+ }
35
+
36
+ /// Strong Kleene binary disjunction (OR) for already-evaluated operands.
37
+ #[inline]
38
+ pub const fn or(self, other: Self) -> Self {
39
+ match (self, other) {
40
+ (Self::True, _) | (_, Self::True) => Self::True,
41
+ (Self::False, Self::False) => Self::False,
42
+ (Self::False, Self::Unknown)
43
+ | (Self::Unknown, Self::False)
44
+ | (Self::Unknown, Self::Unknown) => Self::Unknown,
45
+ }
46
+ }
47
+
48
+ /// Returns true if an AND expression with `self` as LHS short-circuits (i.e. self is False).
49
+ #[inline]
50
+ pub const fn should_short_circuit_and(self) -> bool {
51
+ matches!(self, Self::False)
52
+ }
53
+
54
+ /// Returns true if an OR expression with `self` as LHS short-circuits (i.e. self is True).
55
+ #[inline]
56
+ pub const fn should_short_circuit_or(self) -> bool {
57
+ matches!(self, Self::True)
58
+ }
59
+ }
@@ -0,0 +1,23 @@
1
+ //! XoX epistemic tri-state logic library and Python extension module.
2
+
3
+ pub mod binding;
4
+ pub mod core;
5
+
6
+ use pyo3::prelude::*;
7
+
8
+ use crate::binding::{from_bool, PyXoX};
9
+ use crate::core::XoXValue;
10
+
11
+ /// XoX core Python module.
12
+ #[pymodule]
13
+ fn xox(m: &Bound<'_, PyModule>) -> PyResult<()> {
14
+ m.add_class::<PyXoX>()?;
15
+ m.add_function(wrap_pyfunction!(from_bool, m)?)?;
16
+
17
+ // Canonical singleton constants
18
+ m.add("TRUE", PyXoX(XoXValue::True))?;
19
+ m.add("FALSE", PyXoX(XoXValue::False))?;
20
+ m.add("UNKNOWN", PyXoX(XoXValue::Unknown))?;
21
+
22
+ Ok(())
23
+ }