k3c 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.
- k3c-0.1.0/LICENSE +21 -0
- k3c-0.1.0/PKG-INFO +268 -0
- k3c-0.1.0/README.md +236 -0
- k3c-0.1.0/k3c/__init__.py +331 -0
- k3c-0.1.0/k3c/cache.py +125 -0
- k3c-0.1.0/k3c/cli/__init__.py +1 -0
- k3c-0.1.0/k3c/emit/__init__.py +5 -0
- k3c-0.1.0/k3c/emit/sql.py +268 -0
- k3c-0.1.0/k3c/emit/ts.py +172 -0
- k3c-0.1.0/k3c/engine/__init__.py +41 -0
- k3c-0.1.0/k3c/engine/ctx.py +127 -0
- k3c-0.1.0/k3c/engine/explain.py +474 -0
- k3c-0.1.0/k3c/engine/result.py +175 -0
- k3c-0.1.0/k3c/engine/step.py +520 -0
- k3c-0.1.0/k3c/errors.py +123 -0
- k3c-0.1.0/k3c/ir/__init__.py +181 -0
- k3c-0.1.0/k3c/ir/eval.py +586 -0
- k3c-0.1.0/k3c/ir/expr.py +497 -0
- k3c-0.1.0/k3c/ir/serde.py +662 -0
- k3c-0.1.0/k3c/ir/types.py +134 -0
- k3c-0.1.0/k3c/ir/value.py +127 -0
- k3c-0.1.0/k3c/json.py +75 -0
- k3c-0.1.0/k3c/runtime/__init__.py +52 -0
- k3c-0.1.0/k3c/runtime/bridge.py +254 -0
- k3c-0.1.0/k3c/runtime/compose.py +115 -0
- k3c-0.1.0/k3c/runtime/embedded.py +289 -0
- k3c-0.1.0/k3c/runtime/isolate.py +106 -0
- k3c-0.1.0/k3c/runtime/parallel.py +229 -0
- k3c-0.1.0/k3c/runtime/samsara.py +351 -0
- k3c-0.1.0/k3c/runtime/universe.py +321 -0
- k3c-0.1.0/k3c/spec/__init__.py +86 -0
- k3c-0.1.0/k3c/spec/compile.py +186 -0
- k3c-0.1.0/k3c/spec/extract.py +301 -0
- k3c-0.1.0/k3c/spec/model.py +216 -0
- k3c-0.1.0/k3c/testing/__init__.py +4 -0
- k3c-0.1.0/k3c/testing/fuzz.py +209 -0
- k3c-0.1.0/k3c/testing/strategies.py +80 -0
- k3c-0.1.0/k3c.egg-info/PKG-INFO +268 -0
- k3c-0.1.0/k3c.egg-info/SOURCES.txt +42 -0
- k3c-0.1.0/k3c.egg-info/dependency_links.txt +1 -0
- k3c-0.1.0/k3c.egg-info/requires.txt +7 -0
- k3c-0.1.0/k3c.egg-info/top_level.txt +1 -0
- k3c-0.1.0/pyproject.toml +66 -0
- k3c-0.1.0/setup.cfg +4 -0
k3c-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 [K3 Calculus]
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
k3c-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: k3c
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Kulkarni Calculus (K3) — Design causality, and the system emerges.
|
|
5
|
+
Author: Anil Kulkarni
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://k3c.dev
|
|
8
|
+
Project-URL: Repository, https://github.com/K3Calculus/k3c
|
|
9
|
+
Project-URL: Documentation, https://k3c.dev
|
|
10
|
+
Keywords: k3,calculus,causal,specification,verification,invariant
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
19
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
20
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
21
|
+
Classifier: Topic :: Software Development :: Testing
|
|
22
|
+
Classifier: Typing :: Typed
|
|
23
|
+
Requires-Python: >=3.12
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Requires-Dist: blake3>=1.0.8
|
|
27
|
+
Provides-Extra: blake3
|
|
28
|
+
Requires-Dist: blake3; extra == "blake3"
|
|
29
|
+
Provides-Extra: orjson
|
|
30
|
+
Requires-Dist: orjson; extra == "orjson"
|
|
31
|
+
Dynamic: license-file
|
|
32
|
+
|
|
33
|
+
# k3c — Kulkarni Calculus (K3) Python SDK
|
|
34
|
+
|
|
35
|
+
Design causality, and the system emerges.
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
pip install k3c
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Python 3.12+ | Zero dependencies
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## What is K3?
|
|
46
|
+
|
|
47
|
+
K3 is a minimal causal calculus for discrete systems. A system is fully determined by specifying:
|
|
48
|
+
|
|
49
|
+
- What events are **permitted** (guards)
|
|
50
|
+
- How state **transforms** (transitions)
|
|
51
|
+
- What must **always** be true (invariants)
|
|
52
|
+
- What must **eventually** become true (liveness)
|
|
53
|
+
|
|
54
|
+
The spec IS the implementation. `universe()` compiles the spec into the system's own guards, transitions, and invariants. Drift is structurally impossible.
|
|
55
|
+
|
|
56
|
+
## Quick Start
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
from k3c import (
|
|
60
|
+
Spec, universe, Ok, Impossible, Violated,
|
|
61
|
+
Compare, CmpOp, Field, Var, EventField, Always, LInt, LBool,
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
# 1. Define the spec (I, U, K)
|
|
65
|
+
spec = (
|
|
66
|
+
Spec("bank_account")
|
|
67
|
+
.state0({"balance": 100})
|
|
68
|
+
.permit("has_funds",
|
|
69
|
+
when=Compare(CmpOp.GE, Field(Var("state"), "balance"), EventField("amount")),
|
|
70
|
+
on="Withdraw")
|
|
71
|
+
.maintain("non_negative",
|
|
72
|
+
expr=Always(Compare(CmpOp.GE, Field(Var("state"), "balance"), LInt(0))))
|
|
73
|
+
.project("balance_view", lambda s: s["balance"])
|
|
74
|
+
.build()
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
# 2. Implement the system (just the transition function)
|
|
78
|
+
class BankSystem:
|
|
79
|
+
def transition(self, state, event):
|
|
80
|
+
if event.get("type") == "Withdraw":
|
|
81
|
+
return {**state, "balance": state["balance"] - event["amount"]}
|
|
82
|
+
if event.get("type") == "Deposit":
|
|
83
|
+
return {**state, "balance": state["balance"] + event["amount"]}
|
|
84
|
+
return state
|
|
85
|
+
|
|
86
|
+
# 3. Create a Universe
|
|
87
|
+
u = universe(BankSystem(), spec)
|
|
88
|
+
|
|
89
|
+
# 4. Apply events — the spec enforces everything
|
|
90
|
+
match u.apply({"type": "Withdraw", "amount": 50}):
|
|
91
|
+
case Ok(state=s):
|
|
92
|
+
print(f"Balance: {s['balance']}") # Balance: 50
|
|
93
|
+
case Impossible(why):
|
|
94
|
+
print(f"Rejected: {why.message}") # Guard denied
|
|
95
|
+
case Violated(why):
|
|
96
|
+
print(f"BUG: {why.message}") # Invariant broken
|
|
97
|
+
why.raise_() # Escalate if desired
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## The Three Variants
|
|
101
|
+
|
|
102
|
+
| Variant | Meaning | Bug? |
|
|
103
|
+
| --------------------------- | ------------------------------------------------------ | ------- |
|
|
104
|
+
| `Ok(state, ctx, step_hash)` | Success. Guards passed, invariants held. | No |
|
|
105
|
+
| `Impossible(why)` | Guard rejected. Precondition not met. State unchanged. | No |
|
|
106
|
+
| `Violated(why)` | Invariant broken. Implementation diverged from spec. | **Yes** |
|
|
107
|
+
|
|
108
|
+
## K3.Specs = (I, U, K)
|
|
109
|
+
|
|
110
|
+
Every spec is a triplet:
|
|
111
|
+
|
|
112
|
+
| Element | What it defines | Builder method |
|
|
113
|
+
| ------------------ | ---------------------------------------- | ---------------------------------------- |
|
|
114
|
+
| **I** (Initial) | Domain vocabulary, decode, initial state | `.state0()`, `.field()`, `.decode()` |
|
|
115
|
+
| **U** (Unfolding) | Permitted and required dynamics | `.permit()`, `.require()`, `.maintain()` |
|
|
116
|
+
| **K** (Korrelator) | Correctness measurement | `.korrelate()` |
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
spec = (
|
|
120
|
+
Spec("order_system")
|
|
121
|
+
.state0({"status": "pending", "total": 0})
|
|
122
|
+
|
|
123
|
+
# Guards — what events are allowed
|
|
124
|
+
.permit("can_confirm",
|
|
125
|
+
when=Compare(CmpOp.EQ, Field(Var("state"), "status"), LStr("pending")),
|
|
126
|
+
on="Confirm")
|
|
127
|
+
|
|
128
|
+
# Invariants — what must always hold
|
|
129
|
+
.maintain("positive_total",
|
|
130
|
+
expr=Always(Compare(CmpOp.GE, Field(Var("state"), "total"), LInt(0))))
|
|
131
|
+
|
|
132
|
+
# Liveness — what must eventually happen
|
|
133
|
+
.maintain("eventually_ships",
|
|
134
|
+
expr=Always(Implies(
|
|
135
|
+
Compare(CmpOp.EQ, EventField("type"), LStr("Confirm")),
|
|
136
|
+
Eventually(Compare(CmpOp.EQ, Field(Var("state"), "status"), LStr("shipped"))))))
|
|
137
|
+
|
|
138
|
+
# Projections — derived views
|
|
139
|
+
.project("summary", lambda s: {"status": s["status"], "total": s["total"]})
|
|
140
|
+
|
|
141
|
+
# Outputs — post-causal events
|
|
142
|
+
.output("notify", lambda s, e, ns: {"type": "Notification", "order": ns["status"]},
|
|
143
|
+
on="Confirm")
|
|
144
|
+
|
|
145
|
+
.build()
|
|
146
|
+
)
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Universe Algebra
|
|
150
|
+
|
|
151
|
+
Universes compose and bridge. The algebra is closed.
|
|
152
|
+
|
|
153
|
+
### Compose (parallel)
|
|
154
|
+
|
|
155
|
+
```python
|
|
156
|
+
order_u = universe(OrderSystem(), order_spec)
|
|
157
|
+
payment_u = universe(PaymentSystem(), payment_spec)
|
|
158
|
+
|
|
159
|
+
# Route events to left or right
|
|
160
|
+
commerce = order_u.compose(payment_u,
|
|
161
|
+
router=lambda e: "right" if e.get("type", "").startswith("Pay") else "left")
|
|
162
|
+
|
|
163
|
+
commerce.apply({"type": "PlaceOrder", "amount": 100}) # routes to order_u
|
|
164
|
+
commerce.apply({"type": "PayInvoice", "amount": 100}) # routes to payment_u
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Bridge (cross-universe)
|
|
168
|
+
|
|
169
|
+
```python
|
|
170
|
+
from k3c import BridgeMode
|
|
171
|
+
|
|
172
|
+
# Every order event triggers an audit event
|
|
173
|
+
audited = order_u.bridge(
|
|
174
|
+
audit_u,
|
|
175
|
+
mapper=lambda s, e, ns: {"type": "AuditEvent", "data": e},
|
|
176
|
+
mode=BridgeMode.SYNCHRONOUS,
|
|
177
|
+
)
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Bridge modes: `SYNCHRONOUS` (atomic), `ASYNC` (source first), `BEST_EFFORT` (fire and forget).
|
|
181
|
+
|
|
182
|
+
## Property-Based Testing (KC-5)
|
|
183
|
+
|
|
184
|
+
```python
|
|
185
|
+
# Fuzz to discharge well-formedness rule 8
|
|
186
|
+
report = u.fuzz(sequences=1000, steps=100, seed=42)
|
|
187
|
+
|
|
188
|
+
if not report.passed:
|
|
189
|
+
v = report.violations[0]
|
|
190
|
+
print(f"Found violation: {v.violated.why.rule}")
|
|
191
|
+
print(f"Minimal sequence: {v.shrunk_sequence}")
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## Explain (Debugging)
|
|
195
|
+
|
|
196
|
+
```python
|
|
197
|
+
# Dry-run without mutating state
|
|
198
|
+
result = u.explain({"type": "Withdraw", "amount": 500})
|
|
199
|
+
|
|
200
|
+
print(result.summary())
|
|
201
|
+
# ExplainResult: Impossible
|
|
202
|
+
# - [guard] has_funds: fail — denied
|
|
203
|
+
# + [safety] non_negative: pass — invariant holds
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Parallel Processing
|
|
207
|
+
|
|
208
|
+
One unified spec, derived slices for parallel chunks:
|
|
209
|
+
|
|
210
|
+
```python
|
|
211
|
+
from k3c import parallel_reduce
|
|
212
|
+
|
|
213
|
+
# Derive specs from DFA checkpoints
|
|
214
|
+
chunks = partition(records, workers=8)
|
|
215
|
+
specs = [unified_spec.slice(from_state=checkpoint(chunk)) for chunk in chunks]
|
|
216
|
+
|
|
217
|
+
result = parallel_reduce(MySystem(), specs, chunks, workers=8)
|
|
218
|
+
print(f"Processed {result.total_processed} events")
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## Hash Chain
|
|
222
|
+
|
|
223
|
+
Every step produces a tamper-evident chained hash:
|
|
224
|
+
|
|
225
|
+
```text
|
|
226
|
+
step_hash = SHA-256(state, event, prev_step_hash)
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
Pluggable: `sha256` (default, KC-6), `blake2b` (2x faster), `blake3` (4-6x, optional dep).
|
|
230
|
+
|
|
231
|
+
```python
|
|
232
|
+
u = universe(system, spec, hash_fn="blake2b")
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## KC Compliance Levels
|
|
236
|
+
|
|
237
|
+
| Level | Name | What it adds |
|
|
238
|
+
| ----- | -------------- | ------------------------ |
|
|
239
|
+
| KC-1 | Core Semantics | S, S0, E, G, T, N |
|
|
240
|
+
| KC-2 | Observable | + Projections (P) |
|
|
241
|
+
| KC-3 | Traceable | + Replay (Samsara) |
|
|
242
|
+
| KC-4 | Compositional | + Compose, Bridge |
|
|
243
|
+
| KC-5 | Verified | + Fuzz, Verify |
|
|
244
|
+
| KC-6 | Certified | + Signed step_hash chain |
|
|
245
|
+
|
|
246
|
+
## Domain Examples
|
|
247
|
+
|
|
248
|
+
K3 applies to any system with discrete causal dynamics:
|
|
249
|
+
|
|
250
|
+
- **Banking** — balance guards, transaction invariants
|
|
251
|
+
- **Protocols** — TCP sequence monotonicity, MQTT QoS delivery
|
|
252
|
+
- **Distributed systems** — Raft term monotonicity, election liveness
|
|
253
|
+
- **Scheduling** — SSIM airline schedules, serial continuity
|
|
254
|
+
- **State machines** — order lifecycles, workflow engines
|
|
255
|
+
|
|
256
|
+
## Architecture
|
|
257
|
+
|
|
258
|
+
```text
|
|
259
|
+
k3c.lang — K3l expression IR, eval(), serde, compile
|
|
260
|
+
k3c.spec — (I, U, K) builder, SpecCtx, K3Result, extractors
|
|
261
|
+
k3c.universe — engine, Universe, compose, bridge, fuzz, explain
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
The spec IS the implementation. There is no gap to drift.
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
k3c.dev | Python 3.12+ | Zero dependencies | MIT License
|
k3c-0.1.0/README.md
ADDED
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
# k3c — Kulkarni Calculus (K3) Python SDK
|
|
2
|
+
|
|
3
|
+
Design causality, and the system emerges.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
pip install k3c
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Python 3.12+ | Zero dependencies
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## What is K3?
|
|
14
|
+
|
|
15
|
+
K3 is a minimal causal calculus for discrete systems. A system is fully determined by specifying:
|
|
16
|
+
|
|
17
|
+
- What events are **permitted** (guards)
|
|
18
|
+
- How state **transforms** (transitions)
|
|
19
|
+
- What must **always** be true (invariants)
|
|
20
|
+
- What must **eventually** become true (liveness)
|
|
21
|
+
|
|
22
|
+
The spec IS the implementation. `universe()` compiles the spec into the system's own guards, transitions, and invariants. Drift is structurally impossible.
|
|
23
|
+
|
|
24
|
+
## Quick Start
|
|
25
|
+
|
|
26
|
+
```python
|
|
27
|
+
from k3c import (
|
|
28
|
+
Spec, universe, Ok, Impossible, Violated,
|
|
29
|
+
Compare, CmpOp, Field, Var, EventField, Always, LInt, LBool,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
# 1. Define the spec (I, U, K)
|
|
33
|
+
spec = (
|
|
34
|
+
Spec("bank_account")
|
|
35
|
+
.state0({"balance": 100})
|
|
36
|
+
.permit("has_funds",
|
|
37
|
+
when=Compare(CmpOp.GE, Field(Var("state"), "balance"), EventField("amount")),
|
|
38
|
+
on="Withdraw")
|
|
39
|
+
.maintain("non_negative",
|
|
40
|
+
expr=Always(Compare(CmpOp.GE, Field(Var("state"), "balance"), LInt(0))))
|
|
41
|
+
.project("balance_view", lambda s: s["balance"])
|
|
42
|
+
.build()
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
# 2. Implement the system (just the transition function)
|
|
46
|
+
class BankSystem:
|
|
47
|
+
def transition(self, state, event):
|
|
48
|
+
if event.get("type") == "Withdraw":
|
|
49
|
+
return {**state, "balance": state["balance"] - event["amount"]}
|
|
50
|
+
if event.get("type") == "Deposit":
|
|
51
|
+
return {**state, "balance": state["balance"] + event["amount"]}
|
|
52
|
+
return state
|
|
53
|
+
|
|
54
|
+
# 3. Create a Universe
|
|
55
|
+
u = universe(BankSystem(), spec)
|
|
56
|
+
|
|
57
|
+
# 4. Apply events — the spec enforces everything
|
|
58
|
+
match u.apply({"type": "Withdraw", "amount": 50}):
|
|
59
|
+
case Ok(state=s):
|
|
60
|
+
print(f"Balance: {s['balance']}") # Balance: 50
|
|
61
|
+
case Impossible(why):
|
|
62
|
+
print(f"Rejected: {why.message}") # Guard denied
|
|
63
|
+
case Violated(why):
|
|
64
|
+
print(f"BUG: {why.message}") # Invariant broken
|
|
65
|
+
why.raise_() # Escalate if desired
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## The Three Variants
|
|
69
|
+
|
|
70
|
+
| Variant | Meaning | Bug? |
|
|
71
|
+
| --------------------------- | ------------------------------------------------------ | ------- |
|
|
72
|
+
| `Ok(state, ctx, step_hash)` | Success. Guards passed, invariants held. | No |
|
|
73
|
+
| `Impossible(why)` | Guard rejected. Precondition not met. State unchanged. | No |
|
|
74
|
+
| `Violated(why)` | Invariant broken. Implementation diverged from spec. | **Yes** |
|
|
75
|
+
|
|
76
|
+
## K3.Specs = (I, U, K)
|
|
77
|
+
|
|
78
|
+
Every spec is a triplet:
|
|
79
|
+
|
|
80
|
+
| Element | What it defines | Builder method |
|
|
81
|
+
| ------------------ | ---------------------------------------- | ---------------------------------------- |
|
|
82
|
+
| **I** (Initial) | Domain vocabulary, decode, initial state | `.state0()`, `.field()`, `.decode()` |
|
|
83
|
+
| **U** (Unfolding) | Permitted and required dynamics | `.permit()`, `.require()`, `.maintain()` |
|
|
84
|
+
| **K** (Korrelator) | Correctness measurement | `.korrelate()` |
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
spec = (
|
|
88
|
+
Spec("order_system")
|
|
89
|
+
.state0({"status": "pending", "total": 0})
|
|
90
|
+
|
|
91
|
+
# Guards — what events are allowed
|
|
92
|
+
.permit("can_confirm",
|
|
93
|
+
when=Compare(CmpOp.EQ, Field(Var("state"), "status"), LStr("pending")),
|
|
94
|
+
on="Confirm")
|
|
95
|
+
|
|
96
|
+
# Invariants — what must always hold
|
|
97
|
+
.maintain("positive_total",
|
|
98
|
+
expr=Always(Compare(CmpOp.GE, Field(Var("state"), "total"), LInt(0))))
|
|
99
|
+
|
|
100
|
+
# Liveness — what must eventually happen
|
|
101
|
+
.maintain("eventually_ships",
|
|
102
|
+
expr=Always(Implies(
|
|
103
|
+
Compare(CmpOp.EQ, EventField("type"), LStr("Confirm")),
|
|
104
|
+
Eventually(Compare(CmpOp.EQ, Field(Var("state"), "status"), LStr("shipped"))))))
|
|
105
|
+
|
|
106
|
+
# Projections — derived views
|
|
107
|
+
.project("summary", lambda s: {"status": s["status"], "total": s["total"]})
|
|
108
|
+
|
|
109
|
+
# Outputs — post-causal events
|
|
110
|
+
.output("notify", lambda s, e, ns: {"type": "Notification", "order": ns["status"]},
|
|
111
|
+
on="Confirm")
|
|
112
|
+
|
|
113
|
+
.build()
|
|
114
|
+
)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Universe Algebra
|
|
118
|
+
|
|
119
|
+
Universes compose and bridge. The algebra is closed.
|
|
120
|
+
|
|
121
|
+
### Compose (parallel)
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
order_u = universe(OrderSystem(), order_spec)
|
|
125
|
+
payment_u = universe(PaymentSystem(), payment_spec)
|
|
126
|
+
|
|
127
|
+
# Route events to left or right
|
|
128
|
+
commerce = order_u.compose(payment_u,
|
|
129
|
+
router=lambda e: "right" if e.get("type", "").startswith("Pay") else "left")
|
|
130
|
+
|
|
131
|
+
commerce.apply({"type": "PlaceOrder", "amount": 100}) # routes to order_u
|
|
132
|
+
commerce.apply({"type": "PayInvoice", "amount": 100}) # routes to payment_u
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Bridge (cross-universe)
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
from k3c import BridgeMode
|
|
139
|
+
|
|
140
|
+
# Every order event triggers an audit event
|
|
141
|
+
audited = order_u.bridge(
|
|
142
|
+
audit_u,
|
|
143
|
+
mapper=lambda s, e, ns: {"type": "AuditEvent", "data": e},
|
|
144
|
+
mode=BridgeMode.SYNCHRONOUS,
|
|
145
|
+
)
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Bridge modes: `SYNCHRONOUS` (atomic), `ASYNC` (source first), `BEST_EFFORT` (fire and forget).
|
|
149
|
+
|
|
150
|
+
## Property-Based Testing (KC-5)
|
|
151
|
+
|
|
152
|
+
```python
|
|
153
|
+
# Fuzz to discharge well-formedness rule 8
|
|
154
|
+
report = u.fuzz(sequences=1000, steps=100, seed=42)
|
|
155
|
+
|
|
156
|
+
if not report.passed:
|
|
157
|
+
v = report.violations[0]
|
|
158
|
+
print(f"Found violation: {v.violated.why.rule}")
|
|
159
|
+
print(f"Minimal sequence: {v.shrunk_sequence}")
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Explain (Debugging)
|
|
163
|
+
|
|
164
|
+
```python
|
|
165
|
+
# Dry-run without mutating state
|
|
166
|
+
result = u.explain({"type": "Withdraw", "amount": 500})
|
|
167
|
+
|
|
168
|
+
print(result.summary())
|
|
169
|
+
# ExplainResult: Impossible
|
|
170
|
+
# - [guard] has_funds: fail — denied
|
|
171
|
+
# + [safety] non_negative: pass — invariant holds
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Parallel Processing
|
|
175
|
+
|
|
176
|
+
One unified spec, derived slices for parallel chunks:
|
|
177
|
+
|
|
178
|
+
```python
|
|
179
|
+
from k3c import parallel_reduce
|
|
180
|
+
|
|
181
|
+
# Derive specs from DFA checkpoints
|
|
182
|
+
chunks = partition(records, workers=8)
|
|
183
|
+
specs = [unified_spec.slice(from_state=checkpoint(chunk)) for chunk in chunks]
|
|
184
|
+
|
|
185
|
+
result = parallel_reduce(MySystem(), specs, chunks, workers=8)
|
|
186
|
+
print(f"Processed {result.total_processed} events")
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Hash Chain
|
|
190
|
+
|
|
191
|
+
Every step produces a tamper-evident chained hash:
|
|
192
|
+
|
|
193
|
+
```text
|
|
194
|
+
step_hash = SHA-256(state, event, prev_step_hash)
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Pluggable: `sha256` (default, KC-6), `blake2b` (2x faster), `blake3` (4-6x, optional dep).
|
|
198
|
+
|
|
199
|
+
```python
|
|
200
|
+
u = universe(system, spec, hash_fn="blake2b")
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## KC Compliance Levels
|
|
204
|
+
|
|
205
|
+
| Level | Name | What it adds |
|
|
206
|
+
| ----- | -------------- | ------------------------ |
|
|
207
|
+
| KC-1 | Core Semantics | S, S0, E, G, T, N |
|
|
208
|
+
| KC-2 | Observable | + Projections (P) |
|
|
209
|
+
| KC-3 | Traceable | + Replay (Samsara) |
|
|
210
|
+
| KC-4 | Compositional | + Compose, Bridge |
|
|
211
|
+
| KC-5 | Verified | + Fuzz, Verify |
|
|
212
|
+
| KC-6 | Certified | + Signed step_hash chain |
|
|
213
|
+
|
|
214
|
+
## Domain Examples
|
|
215
|
+
|
|
216
|
+
K3 applies to any system with discrete causal dynamics:
|
|
217
|
+
|
|
218
|
+
- **Banking** — balance guards, transaction invariants
|
|
219
|
+
- **Protocols** — TCP sequence monotonicity, MQTT QoS delivery
|
|
220
|
+
- **Distributed systems** — Raft term monotonicity, election liveness
|
|
221
|
+
- **Scheduling** — SSIM airline schedules, serial continuity
|
|
222
|
+
- **State machines** — order lifecycles, workflow engines
|
|
223
|
+
|
|
224
|
+
## Architecture
|
|
225
|
+
|
|
226
|
+
```text
|
|
227
|
+
k3c.lang — K3l expression IR, eval(), serde, compile
|
|
228
|
+
k3c.spec — (I, U, K) builder, SpecCtx, K3Result, extractors
|
|
229
|
+
k3c.universe — engine, Universe, compose, bridge, fuzz, explain
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
The spec IS the implementation. There is no gap to drift.
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
k3c.dev | Python 3.12+ | Zero dependencies | MIT License
|