super-semantics-vsl 0.3.1__py3-none-any.whl
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.
- super_semantics_vsl-0.3.1.dist-info/METADATA +352 -0
- super_semantics_vsl-0.3.1.dist-info/RECORD +23 -0
- super_semantics_vsl-0.3.1.dist-info/WHEEL +5 -0
- super_semantics_vsl-0.3.1.dist-info/licenses/LICENSE +21 -0
- super_semantics_vsl-0.3.1.dist-info/top_level.txt +1 -0
- vsl_core/__init__.py +166 -0
- vsl_core/catalog/__init__.py +6 -0
- vsl_core/catalog/drift_classes.json +917 -0
- vsl_core/catalog/legion_patterns.json +2290 -0
- vsl_core/catalog/loader.py +400 -0
- vsl_core/cluster.py +90 -0
- vsl_core/conformance/__init__.py +7 -0
- vsl_core/conformance/protocol.py +32 -0
- vsl_core/conformance/reference_adapter.py +45 -0
- vsl_core/conformance/suite.py +244 -0
- vsl_core/constructs.py +171 -0
- vsl_core/exceptions.py +102 -0
- vsl_core/governance.py +205 -0
- vsl_core/identity.py +148 -0
- vsl_core/immudb_store.py +220 -0
- vsl_core/ledger.py +910 -0
- vsl_core/metrics.py +352 -0
- vsl_core/rules_version.py +17 -0
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: super-semantics-vsl
|
|
3
|
+
Version: 0.3.1
|
|
4
|
+
Summary: Framework-agnostic and model-agnostic VSL (VERBA Specification Language) governance primitives.
|
|
5
|
+
License: MIT
|
|
6
|
+
Project-URL: Homepage, https://github.com/supersemantics/VSL-Core
|
|
7
|
+
Project-URL: Repository, https://github.com/supersemantics/VSL-Core
|
|
8
|
+
Project-URL: Changelog, https://github.com/supersemantics/VSL-Core/blob/HEAD/CHANGELOG.md
|
|
9
|
+
Project-URL: Issues, https://github.com/supersemantics/VSL-Core/issues
|
|
10
|
+
Keywords: governance,ai-safety,guardrails,audit-log,vsl,verba
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Development Status :: 3 - Alpha
|
|
15
|
+
Requires-Python: >=3.10
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
License-File: LICENSE
|
|
18
|
+
Provides-Extra: dev
|
|
19
|
+
Requires-Dist: pytest>=7; extra == "dev"
|
|
20
|
+
Provides-Extra: immudb
|
|
21
|
+
Requires-Dist: immudb-py<2,>=1.5; extra == "immudb"
|
|
22
|
+
Dynamic: license-file
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
title: vsl-core
|
|
26
|
+
description: Framework-agnostic VSL governance primitives and hash-chained audit ledgers.
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## vsl-core
|
|
30
|
+
|
|
31
|
+
The framework-agnostic and model-agnostic foundation of **VSL** (VERBA Specification Language) — a governance vocabulary for deciding whether an automated system's next action is allowed to happen, and proving that decision was made.
|
|
32
|
+
|
|
33
|
+
Zero required third-party runtime dependencies. Optional immudb storage uses
|
|
34
|
+
the official Python SDK. MIT licensed.
|
|
35
|
+
|
|
36
|
+
## What this is — and isn't
|
|
37
|
+
|
|
38
|
+
**Is:**
|
|
39
|
+
- The agnostic template: `Invariant`, `PreNode`, `TerminalState`, `Cluster`, the hash-chained `VerbaLedger`, plus a Drift Class / Stabilisation Operator catalog.
|
|
40
|
+
- A conformance contract (`vsl_core.conformance`) so a third party can build an adapter for a framework this package has never heard of, and know mechanically whether they built it correctly.
|
|
41
|
+
|
|
42
|
+
**Is not:**
|
|
43
|
+
- A framework adapter. This package ships no OpenAI Agents SDK, LangGraph, or LangChain integration. Those live in separate `vsl-<framework>` packages, out of scope here. [`vsl-langgraph`](https://github.com/supersemantics/VSL-Langgraph) is a real one — conformance-suite green, with worked examples including a retrofit onto an existing, unfamiliar, third-party codebase (not just built-from-scratch demos).
|
|
44
|
+
- A model integration of any kind. It never imports `openai`, `anthropic`, or any other model-provider SDK.
|
|
45
|
+
- A finished, validated detection system. See the catalog section below — most of what it contains is explicitly unvalidated.
|
|
46
|
+
|
|
47
|
+
If you're building an adapter for a specific framework, see [Building an adapter](#building-an-adapter) below, or start from [`vsl-langgraph`](https://github.com/supersemantics/VSL-Langgraph)'s source as a real, working reference — its own `docs/` also cover lessons that generalize past LangGraph specifically (see `beyond-the-gate.md` and `dos-and-donts.md`).
|
|
48
|
+
|
|
49
|
+
## Getting started (including with an AI coding assistant)
|
|
50
|
+
|
|
51
|
+
[`docs/building-with-vsl-core.md`](https://github.com/supersemantics/VSL-Core/blob/HEAD/docs/building-with-vsl-core.md) is the guide for going from "I have an agent, or an idea for one" to working code: how to find the decision points that actually need governing, which parts of the flow are automatic versus something you write yourself, and a domain-agnostic project scaffold with a worked example. Its companion, [`docs/vsl-core-primitives.json`](https://github.com/supersemantics/VSL-Core/blob/HEAD/docs/vsl-core-primitives.json), is the same material as exact, structured facts — every class, field, and code sample in it has been executed against the real package. Both are written to be handed directly to an AI coding assistant (Claude Code, Codex, or similar) as reference material — no special setup required, though pointing your own project's `CLAUDE.md`/equivalent at them is what makes an assistant reach for them without being asked each time.
|
|
52
|
+
|
|
53
|
+
Stuck on a specific error, not just getting started? [`docs/troubleshooting.md`](https://github.com/supersemantics/VSL-Core/blob/HEAD/docs/troubleshooting.md) is the human-readable version of the JSON's `common_mistakes` — real, reproduced errors (not guessed), with the exact exception text and the fix.
|
|
54
|
+
|
|
55
|
+
## How this relates to governance frameworks (OWASP, NIST, EU AI Act, and others)
|
|
56
|
+
|
|
57
|
+
If you're asking "how does this relate to the OWASP Agentic Top 10, NIST's AI RMF, the EU AI Act, ISO 42001, or similar" — see [`docs/governance-frameworks.md`](https://github.com/supersemantics/VSL-Core/blob/HEAD/docs/governance-frameworks.md). It does not claim vsl-core satisfies, maps to, or complies with any of them. What it does instead: framework by framework, it takes each one's own stated goal in its own words and shows one way a developer might attempt to address it using vsl-core's real primitives — runnable code, actual output, and an honest "we don't attempt this" wherever vsl-core has nothing relevant to offer. Whether a given implementation built this way actually satisfies a given framework, for a real deployment, is a question for a qualified auditor or compliance professional, not something this package or that document can settle in advance.
|
|
58
|
+
|
|
59
|
+
## The F1/F2 assurance distinction (read this before trusting any Assurance Level)
|
|
60
|
+
|
|
61
|
+
Every claim this package (or anything built on it) makes about how trustworthy a governance mechanism is reduces to one test:
|
|
62
|
+
|
|
63
|
+
- **F1 (pre-commitment)** — does the check run *before* the system commits to an action, with no side effect yet fired?
|
|
64
|
+
- **F2 (energy-landscape modification)** — how much does the system change what the model produces? It is judged at the call the gate guards: does the application touch the mechanism that produces the output (logits, weights, activations), only what the model sees (prompt, context) or how it samples, or nothing at all?
|
|
65
|
+
|
|
66
|
+
F2 is never earned by the gate itself. Allowing or blocking an action changes nothing about what a model produces, so a gate that only allows or blocks — and an application that shapes nothing at the guarded call — is `NONE`.
|
|
67
|
+
|
|
68
|
+
| Gate pattern | F1 | F2 | Level |
|
|
69
|
+
|---|---|---|---|
|
|
70
|
+
| Amount cap before `issue_refund` (no model involved) | True | `NONE` | LOW |
|
|
71
|
+
| Gate before a hosted-model call whose system prompt the application writes | True | `PARTIAL` | MEDIUM |
|
|
72
|
+
| Gate before a self-hosted model call where the application steers logits or activations (`PreNode.intervention`) | True | `FULL` | HIGH |
|
|
73
|
+
| A check that runs after the action has already happened, or only logs | False | any | LOW |
|
|
74
|
+
|
|
75
|
+
A mechanism satisfying F1 but only *partial* F2 caps at **MEDIUM** assurance, never HIGH. A hosted model API rules out `FULL`: nobody outside the provider can touch its logits or weights, so a gate in front of one is at most `PARTIAL`, and only because of the prompt or context the application itself sends. Nothing in this package, in any README, or in any client-facing material built on it should blur this distinction.
|
|
76
|
+
|
|
77
|
+
**The level measures influence on the model, not enforcement.** A gate with F1=True and F2=`NONE` derives `LOW`, yet it still blocks every action it denies — that is its F1. Report the two separately ("blocks before the action: yes; shapes the model: no") rather than reading enforcement off the level, and never raise F2 to make a level look better.
|
|
78
|
+
|
|
79
|
+
**Stating a basis is structurally enforced; the basis being true is not.** `AllowedState.assurance_level`/`PreNode.assurance_level`/`Invariant.assurance_level` are *derived*, read-only properties — you can't set them directly, and you can't skip past `AssuranceBasis` to assert a level for free. What you provide instead is an `AssuranceBasis`: the F1 (bool) and F2 (`F2Modification`: `FULL`/`PARTIAL`/`INDIRECT`/`NONE`) facts themselves. `AssuranceBasis.derived_level` computes the level from those facts, so a `PreNode` claiming HIGH has to actually state "yes F1, and F2 is FULL" — it can't just default into HIGH. `AssuranceBasis.__post_init__` also rejects any `f1_pre_commitment` that isn't a strict `bool` and any `f2_modification` that isn't a real `F2Modification` member — `f1_pre_commitment=None`, `f2_modification=None`, a typo, or any other invalid value raises `TypeError` immediately, rather than silently deriving `LOW` by falling through `derived_level` unnoticed (`f1_pre_commitment=None` is falsy, so without this check it would quietly take the `not self.f1_pre_commitment` branch straight to `LOW`). This closes one specific failure mode — a value nobody actually chose being computed anyway — not the other one described below.
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
from vsl_core.metrics import AssuranceBasis, F2Modification
|
|
83
|
+
|
|
84
|
+
# A gate before a hosted-LLM call: runs before the call (F1=True); the app
|
|
85
|
+
# sends its own system prompt there, so F2=PARTIAL. Nothing behind the API
|
|
86
|
+
# can be touched, so FULL is impossible.
|
|
87
|
+
basis = AssuranceBasis(f1_pre_commitment=True, f2_modification=F2Modification.PARTIAL)
|
|
88
|
+
basis.derived_level # AssuranceLevel.MEDIUM -- not HIGH, even if you wanted it to be
|
|
89
|
+
|
|
90
|
+
# An amount cap before issue_refund: no model at the guarded call, so F2=NONE.
|
|
91
|
+
AssuranceBasis(f1_pre_commitment=True, f2_modification=F2Modification.NONE).derived_level # LOW
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**But stating F1/F2 is not the same as proving them.** `AssuranceBasis` is a self-declared claim, not independently verified assurance. Nothing in this package checks that a stated `F2Modification.FULL` actually reflects what the gated `monitor`/`rule` does — a developer can construct a perfectly valid `AssuranceBasis(f1_pre_commitment=True, f2_modification=F2Modification.FULL)` next to a callable that only calls a hosted, black-box LLM API, and `vsl-core` will compute `HIGH` from it without objection. Confirming a stated F2 value is honest requires something external to this package — a human reviewing the actual `monitor`/`rule` code, or a dedicated tool built for that reconciliation. Presenting a derived `AssuranceLevel` to a compliance team, an auditor, or a client as though it were independently confirmed is not something this package does, checks, or claims: treat it as what a developer asserted, not what was proven.
|
|
95
|
+
|
|
96
|
+
The full derivation table (`F1=False` always → LOW regardless of F2; `F1=True`+`FULL` → HIGH; `F1=True`+`PARTIAL`/`INDIRECT` → MEDIUM; `F1=True`+`NONE` → LOW) is implemented and tested exhaustively in `vsl_core.metrics`. The last row (F1 satisfied, but zero claimed energy-landscape effect) isn't in the source paper's table — it's a deliberate interpretive extension, documented as such in the code, not a spec fact.
|
|
97
|
+
|
|
98
|
+
This is a distinct axis from **model-agnostic vs. model-specific** and **framework-agnostic vs. framework-specific** — see the module docstrings in `constructs.py` and `ledger.py` for why conflating those two axes was a real mistake worth avoiding structurally, not just documenting.
|
|
99
|
+
|
|
100
|
+
## The ledger doesn't write itself (read this before assuming an audit trail exists)
|
|
101
|
+
|
|
102
|
+
Nothing in this package writes to `VerbaLedger` automatically. Compiling and calling a gate (`compile_pre_node`/`compile_invariant`, then `await gate(...)`) is the only part of governance that happens without you asking for it — it will raise `AutomationDeniedException`/`InvariantViolation` on its own, every time, correctly. Recording that it happened is a separate, deliberate act your own code must perform:
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
try:
|
|
106
|
+
await gate(candidate_input)
|
|
107
|
+
except InvariantViolation:
|
|
108
|
+
ledger.write(LedgerEntryType.TERMINAL, identity_key=..., payload={...})
|
|
109
|
+
raise
|
|
110
|
+
else:
|
|
111
|
+
ledger.write_monitor(identity_key=..., drift_detected=False)
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
To record a gate's own decision, use `write_gate_decision()`. It writes one standard record, so every agent's gate decisions can be read the same way:
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
REFUND_GATE = "refund-within-policy"
|
|
118
|
+
|
|
119
|
+
async def refund_headroom(request) -> GammaEstimate:
|
|
120
|
+
estimate = GammaEstimate(gamma_hat=REFUND_LIMIT / request["amount"])
|
|
121
|
+
ledger.write_gate_decision(
|
|
122
|
+
identity_key="refund-agent",
|
|
123
|
+
primitive_name=REFUND_GATE, # must equal the PreNode's name
|
|
124
|
+
estimate=estimate,
|
|
125
|
+
gamma_threshold=ROBUST_GAMMA_DEFAULT_THRESHOLD, # must equal the PreNode's threshold
|
|
126
|
+
decision_id=request["decision_id"], # groups this decision's entries
|
|
127
|
+
)
|
|
128
|
+
return estimate
|
|
129
|
+
|
|
130
|
+
refund_pre_node = PreNode(
|
|
131
|
+
name=REFUND_GATE,
|
|
132
|
+
description="Refunds must stay comfortably inside the policy limit.",
|
|
133
|
+
monitor=refund_headroom,
|
|
134
|
+
gamma_threshold=ROBUST_GAMMA_DEFAULT_THRESHOLD,
|
|
135
|
+
assurance_basis=AssuranceBasis(f1_pre_commitment=True, f2_modification=F2Modification.NONE),
|
|
136
|
+
)
|
|
137
|
+
# For an Invariant, record inside its rule: write_gate_decision(..., allowed=holds).
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
The record is a `MONITOR` entry carrying `primitive_name`, `allowed` (computed with the same `sufficient()` check the gate makes), `gamma_hat`, `delta_estimation_error`, `robust_gamma`, `gamma_threshold`, `required_gamma_hat`, `rules_version` and `drift_detected` (`not allowed`). `rules_version` is `ASSURANCE_RULES_VERSION`: if a later release changes how Gamma or assurance levels are judged, every record still says which rules produced it.
|
|
141
|
+
|
|
142
|
+
When one agent hands part of a decision to another before that agent acts, record the hand-off with `write_handover()`, and have the receiver name it as `caused_by` on its first gate decision. Each agent's own gate can pass while the hand-off between them goes unchecked; this makes the decision trace one causal chain across both agents:
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
handover = ledger.write_handover(
|
|
146
|
+
identity_key="intake-agent",
|
|
147
|
+
to_identity_key="refund-agent",
|
|
148
|
+
decision_id=request["decision_id"], # required: the decision both agents share
|
|
149
|
+
reason="customer asked for a refund",
|
|
150
|
+
# cluster_key=... # when the agents form a declared Cluster
|
|
151
|
+
)
|
|
152
|
+
# ...in the refund agent's monitor:
|
|
153
|
+
ledger.write_gate_decision(
|
|
154
|
+
identity_key="refund-agent",
|
|
155
|
+
primitive_name=REFUND_GATE,
|
|
156
|
+
estimate=estimate,
|
|
157
|
+
gamma_threshold=ROBUST_GAMMA_DEFAULT_THRESHOLD,
|
|
158
|
+
decision_id=request["decision_id"],
|
|
159
|
+
caused_by=handover.entry_id, # shows the receiver checked what it was handed
|
|
160
|
+
)
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
The handover is a `MONITOR` entry with `drift_detected` False (a hand-off is not drift) and a `HANDOVER_KEY` (`"handover"`) payload of `{from_identity, to_identity, reason}`. No new entry type, so every ledger store accepts it unchanged.
|
|
164
|
+
|
|
165
|
+
If you never call `ledger.write*` anywhere in your agent, you get real, working governance gates and zero audit trail — `vsl-core` will not warn you this happened, because from its point of view nothing went wrong: the gates it owns did exactly what they were compiled to do. An empty or missing `VerbaLedger` is indistinguishable, from inside this package, from an agent that has never once been gated. See [`docs/building-with-vsl-core.md`](https://github.com/supersemantics/VSL-Core/blob/HEAD/docs/building-with-vsl-core.md)'s "know what's automatic and what you write yourself" for the full breakdown of which of the five steps (construct, compile, call, log, escalate) are automatic and which are entirely on you.
|
|
166
|
+
|
|
167
|
+
## VSL construct → vsl_core object
|
|
168
|
+
|
|
169
|
+
| VSL construct | vsl_core object |
|
|
170
|
+
|---|---|
|
|
171
|
+
| Signal / Tendency / Constraint | not separately modeled — expressed through `PreNode`/`Invariant` |
|
|
172
|
+
| State / Allowed State | `vsl_core.constructs.AllowedState` |
|
|
173
|
+
| Inadmissible State / Drift Node | `vsl_core.constructs.InadmissibleState` |
|
|
174
|
+
| Pre-Node | `vsl_core.constructs.PreNode` |
|
|
175
|
+
| Invariant | `vsl_core.constructs.Invariant` (requires `assurance_basis`, same as `PreNode`/`AllowedState`; optional `on_violation: TerminalState` names which Terminal State a violation enters) |
|
|
176
|
+
| Terminal State | `vsl_core.constructs.TerminalState` |
|
|
177
|
+
| Cluster | `vsl_core.cluster.Cluster` |
|
|
178
|
+
| Fallback | `vsl_core.constructs.Fallback` |
|
|
179
|
+
| Identity Key / Cluster Key | `vsl_core.identity.IdentityKey` / `ClusterKey` |
|
|
180
|
+
| Instance / Re-Enablement | `vsl_core.identity.Instance` (`.new()` / `._re_enable()` — bare mechanism, leading underscore on purpose; see the Re-Enablement section below) |
|
|
181
|
+
| Automation-Denied | `vsl_core.exceptions.AutomationDeniedException` |
|
|
182
|
+
| Human-Authorised Transition | `vsl_core.governance.HumanAuthorisedTransition` / `request_re_enablement()` |
|
|
183
|
+
| Governance Authority | `vsl_core.governance.GovernanceAuthority` |
|
|
184
|
+
| VERBA Ledger | `vsl_core.ledger.VerbaLedger` |
|
|
185
|
+
| VERBA Certificate | `vsl_core.ledger.VerbaCertificate` |
|
|
186
|
+
| Delta / Gamma / GES / EEF | `vsl_core.metrics.Delta` / `GammaEstimate` / `GES` / `EEF` |
|
|
187
|
+
| Beta (inverse temperature) | `vsl_core.metrics.Beta` |
|
|
188
|
+
| Threshold | `vsl_core.metrics.Threshold` + `GAMMA_MONITORING_THRESHOLD` / `JACOBIAN_RED_FLAG_THRESHOLD` / `KL_MONITORING_THRESHOLD` |
|
|
189
|
+
| Policy-as-Code | `vsl_core.governance.Specification` |
|
|
190
|
+
| Proofing | `vsl_core.governance.Proofing` |
|
|
191
|
+
| Binding | `vsl_core.governance.Binding` |
|
|
192
|
+
| Drift | not its own type — see [the Drift payload-key note](#drift-has-no-dedicated-type-by-design) below |
|
|
193
|
+
| Node / Drift Node / Tendency | not modeled as vsl-core types — see [the scoping note](#node-drift-node-and-tendency-are-deliberately-out-of-scope) below |
|
|
194
|
+
|
|
195
|
+
**Ledger entry-type count note**: the source spec's prose describes "six entry types" but then enumerates seven (`MONITOR`, `PRE_NODE`, `VERIFICATION`, `TERMINAL`, `SPECIFICATION_UPDATE`, `HUMAN_AUTHORISED_TRANSITION`, `RE_ENABLEMENT`). This is a stale count in the source document itself. All seven are implemented in `vsl_core.ledger.LedgerEntryType`; the count discrepancy is intentionally not silently resolved.
|
|
196
|
+
|
|
197
|
+
**Beta note**: the source spec describes Beta only qualitatively (higher Beta → lower volatility → stronger concentration on energy minima; systems tuned at normal Beta may fail at crisis Beta) — it gives no closed-form formula relating Beta to Delta or Gamma. `Beta` is a bare value holder for exactly this reason: naming and logging the quantity without fabricating a computation the source paper doesn't provide.
|
|
198
|
+
|
|
199
|
+
**Threshold note**: only Gamma's default threshold (1.1) was previously represented anywhere in this package. The spec also names a Jacobian "red flag" (`lambda_min(J_gov) < 0.05`) and a default KL monitoring threshold (0.15 nats) — both are now reference constants too, so a `DriftMonitor` implementer has the spec's own defaults available instead of re-deriving or mistyping them. Jacobian/KL computation itself stays out of core, same as Gamma estimation — these are just named numbers.
|
|
200
|
+
|
|
201
|
+
**How a threshold is applied.** A Gamma threshold is 1 plus the estimation-error allowance it already includes (1.1 = 10%, 1.2 = 20%). `GammaEstimate.sufficient(threshold)` passes only when `gamma_hat` is strictly greater than `max(threshold, 1 + delta_estimation_error)`, which `required_gamma_hat(threshold)` returns: a monitor's declared error raises the bar only when it is larger than the allowance already in the threshold. Every pass therefore also means `robust_gamma() > 1`. Exactly on the bar does not pass. See [CHANGELOG.md](https://github.com/supersemantics/VSL-Core/blob/HEAD/CHANGELOG.md) for the change from rules version 2026.10.
|
|
202
|
+
|
|
203
|
+
**What a Gamma value means today.** vsl-core never measures Gamma: your monitor computes `gamma_hat`, and the gate only compares it. For most actions (a refund, an email) the spec's Gamma cannot be measured directly, so what a monitor returns is a *gate score in Gamma units*. Make it an honest one:
|
|
204
|
+
|
|
205
|
+
- Build it as a ratio where 1.0 means break-even: a policy limit divided by the requested amount, a judge's score divided by its break-even score, an hourly cap divided by this send's count.
|
|
206
|
+
- Return `0.0` when the input is missing or unreadable, so the gate fails closed.
|
|
207
|
+
- Never use a raw 0–1 confidence as `gamma_hat`: it can never exceed 1.1, so the gate denies every time.
|
|
208
|
+
- A fixed `2.0`-or-`0.0` return is a pass/fail encoding, not a measurement. Say so in a comment; for a rule that must never be broken, use an `Invariant` instead of a large threshold.
|
|
209
|
+
- Use `ROBUST_GAMMA_HIGH_STAKES_THRESHOLD` (1.2) for payments, medical and legal actions; never set a threshold at or below 1.0.
|
|
210
|
+
- Record each decision with `write_gate_decision()` (see "The ledger doesn't write itself" above) if you want to track how a gate's scores move over time. vsl-core keeps no history of its own.
|
|
211
|
+
|
|
212
|
+
### Drift has no dedicated type, by design
|
|
213
|
+
|
|
214
|
+
`VerbaLedger.audit()`'s checks read two payload keys: `DRIFT_DETECTED_KEY` (`"drift_detected"`, a `MONITOR` entry's payload) and `VERIFICATION_RESULT_KEY` (`"result"`, a `VERIFICATION` entry's payload, compared against `VerificationResult.INSUFFICIENT`). These are exported constants, not magic strings you need to remember — use `VerbaLedger.write_monitor(identity_key=..., drift_detected=...)` and `VerbaLedger.write_verification(identity_key=..., result=VerificationResult.INSUFFICIENT)` instead of hand-building the payload dict, and the audit checks can never silently miss a differently-spelled key.
|
|
215
|
+
|
|
216
|
+
### Node, Drift Node, and Tendency are deliberately out of scope
|
|
217
|
+
|
|
218
|
+
The source spec's Layer 0/1 vocabulary includes `Node` (a stabilised, repeatable pattern of behaviour, classified as an Allowed Node or Drift Node) and `Tendency` (a directional bias detected via KL-divergence comparison, before any output is generated). vsl-core does not model either as its own type. This is a deliberate scoping decision, not an oversight: Node classification is an *inference* concern — it requires observing a real system's behaviour over time and classifying the pattern that emerges — which belongs to analysis tooling built on top of vsl-core, not to something a spec author instantiates directly the way they instantiate a `PreNode` or `Invariant`. vsl-core models the State layer (`AllowedState`/`InadmissibleState`) and the Gamma-based sufficiency judgment (`GammaEstimate.sufficient()`) that a Tendency's KL comparison would ultimately feed into, and stops there.
|
|
219
|
+
|
|
220
|
+
### Re-Enablement: the one sanctioned path out of a Terminal State
|
|
221
|
+
|
|
222
|
+
`Instance._re_enable()` is a mechanism, not a policy gate — it's directly callable with just an `Evidence` object and has no concept of a `GovernanceAuthority`. The leading underscore is deliberate (renamed from a public `re_enable()` after an external review correctly flagged the public name as an easy accidental-bypass risk) — it signals "not the sanctioned entry point," though Python still can't make that a hard guarantee. The sanctioned, audited path is `governance.request_re_enablement()`, which pairs the new `Instance` with the `HumanAuthorisedTransition` record that authorises it, so you can't get one without the other:
|
|
223
|
+
|
|
224
|
+
```python
|
|
225
|
+
from vsl_core.identity import Instance, Evidence
|
|
226
|
+
from vsl_core.governance import GovernanceAuthority, request_re_enablement
|
|
227
|
+
|
|
228
|
+
terminated_instance = Instance.new()
|
|
229
|
+
authority = GovernanceAuthority(name="safety-board", escalation_contact="oncall@example.com")
|
|
230
|
+
evidence = Evidence(
|
|
231
|
+
root_cause_analysis="alarm software infinite loop",
|
|
232
|
+
specification_update_proposal="add heartbeat invariant",
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
new_instance, transition = request_re_enablement(
|
|
236
|
+
terminated_instance,
|
|
237
|
+
authority,
|
|
238
|
+
authorised_by="jane.doe",
|
|
239
|
+
evidence=evidence,
|
|
240
|
+
)
|
|
241
|
+
# new_instance -> write a RE_ENABLEMENT ledger entry
|
|
242
|
+
# transition -> write a HUMAN_AUTHORISED_TRANSITION ledger entry
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
Like `AutomationDeniedException`'s "cannot be silently caught," this is a convention, not a language-enforced guarantee: nothing stops a caller from calling `Instance._re_enable()` directly and skipping the authority/evidence trail. Adapters and client code that need the audited path should always go through `request_re_enablement()`.
|
|
246
|
+
|
|
247
|
+
Also worth being precise about, for the same reason: an `InvariantViolation` now carries a `terminal_state_name: str | None` field — set to `on_violation.name` when the violated `Invariant` named one, `None` otherwise. This used to be recoverable only by parsing the free-text `reason` string for the phrase "entering terminal state"; a plain PreNode failure, an ordinary Invariant violation, and a violation that halted the system into a Terminal State are three operationally different events, and telling them apart shouldn't require string matching.
|
|
248
|
+
|
|
249
|
+
### VerbaLedger: causal correlation, schema versioning, and cross-process safety
|
|
250
|
+
|
|
251
|
+
Three additions to the ledger, all backward-compatible — existing single-decision-at-a-time callers are unaffected.
|
|
252
|
+
|
|
253
|
+
**Causal correlation.** `audit()`'s checks originally matched entries only by "same `identity_key`/`instance_id` and a later timestamp" — which can mismatch when a single `Instance` has more than one decision in flight at once (e.g. a payment check and an email verification interleaved on the same agent, where the unrelated email `PRE_NODE` could look like it resolves the payment `MONITOR`'s drift). `write()`/`write_monitor()`/`write_verification()` now accept optional `decision_id`/`caused_by` kwargs; `caused_by` lets an entry name the exact prior `entry_id` it resolves, and `audit()` matches causally whenever it's set, falling back to the old heuristic only when it's absent. Both fields are part of the hash chain, so a forged causal claim is detectable the same way a forged payload is.
|
|
254
|
+
|
|
255
|
+
**Schema versioning.** `LedgerEntry.schema_version` records which shape of the entry wrote it (`LEDGER_SCHEMA_VERSION`, currently `"1.0"`). `VerbaLedger.write()` stamps it on every entry it constructs; a bare `LedgerEntry(...)` built directly — or one reconstructed from a persisted entry that predates this field — doesn't silently claim a version it wasn't actually written under.
|
|
256
|
+
|
|
257
|
+
**Checkpoints.** `VerbaLedger.current_checkpoint()` returns a `LedgerCheckpoint` (`sequence`, `entry_hash`, `checked_at`), which an external anchoring service can witness over time. `verify_integrity()` only proves internal consistency of whatever entries the store currently holds; it cannot detect truncation or wholesale replacement with an older, still-consistent snapshot. The optional immudb store also checks local entries against a remote copy during synchronization.
|
|
258
|
+
|
|
259
|
+
**Cross-process safety.** `JsonlLedgerStore.append()`'s read-last-entry-then-write sequence is now guarded by an OS-level advisory lock (`fcntl.flock` on POSIX, `msvcrt.locking` on Windows) on a sibling `.lock` file, not just the in-process `threading.RLock`. Two separate `JsonlLedgerStore` instances — in one process or several — writing to the same file can no longer race and corrupt the sequence/hash chain.
|
|
260
|
+
|
|
261
|
+
**Storage options.** This package includes `InMemoryLedgerStore`,
|
|
262
|
+
`JsonlLedgerStore`, and optional `ImmuDBLedgerStore`. The immudb store writes
|
|
263
|
+
the same hash-chained entries to local JSONL and immudb, with connection
|
|
264
|
+
settings supplied by the application or environment. See
|
|
265
|
+
[immudb ledger storage](https://github.com/supersemantics/VSL-Core/blob/HEAD/docs/immudb-ledger.md) for setup and recovery.
|
|
266
|
+
`VerbaLedger` uses the same `LedgerStore` interface for every store, so
|
|
267
|
+
any other durable store can be plugged in the same way.
|
|
268
|
+
|
|
269
|
+
## The Drift Class / Stabilisation Operator catalog (`vsl_core.catalog`)
|
|
270
|
+
|
|
271
|
+
Loads two real data files (Paper 5, "Toward a Basis Representation of Drift Forensics"): 45 Drift Classes across five categories (external, internal, systemic, linguistic, authority) tagged by evidence tier (A = well evidenced, B = theoretically grounded, C = hypothesised, D = a limit class possibly unfixable by any operator), and 10 Stabilisation Operators.
|
|
272
|
+
|
|
273
|
+
**This catalog is explicitly not a finished, validated detection system.** Of the 113 Legion detection heuristics in `legion_patterns.json`, **106 (94%) are self-labeled `SPECULATIVE`**, with the stated caveat that "no verified detection signature exists yet — treat matches as a prompt for manual review, not a confirmed finding." Only **7 heuristics carry real confidence** (4 HIGH, 3 MEDIUM), concentrated in `DC-E13` (3), `DC-I11` (2), and the orphan `CLUSTER-HANDOVER` entry (2). Call `catalog.loader.only_validated_heuristics()` if you want only those seven — do not treat the other 106 as ready to act on automatically.
|
|
274
|
+
|
|
275
|
+
Known data-quality findings, surfaced by `catalog.loader.validate()` and never silently fixed:
|
|
276
|
+
|
|
277
|
+
1. `drift_classes.json`'s own `metadata.total_drift_classes` claims **36**; the real, computed count across all five categories is **45** (external=15, internal=19, systemic=7, linguistic=3, authority=1). Do not trust the metadata field.
|
|
278
|
+
2. `legion_patterns.json` contains a `CLUSTER-HANDOVER` entry with no corresponding Drift Class anywhere in `drift_classes.json`.
|
|
279
|
+
3. **10 Drift Classes have zero Legion detection heuristics at all** (`legions: {}`): `DC-S1, DC-S2, DC-S3, DC-S4, DC-S5, DC-S6, DC-L1, DC-L2, DC-L3, DC-A1` — all of the systemic and linguistic tiers, plus the sole authority-tier class. This is a coverage gap (mostly tier B/C/D theoretical/limit classes with no heuristic proposed yet), not a data error, and is worded accordingly in `validate()`'s output.
|
|
280
|
+
|
|
281
|
+
## Building an adapter
|
|
282
|
+
|
|
283
|
+
A framework adapter must implement `vsl_core.conformance.protocol.VSLAdapter` (`compile_pre_node`, `compile_invariant`) and pass `vsl_core.conformance.suite.run_conformance_suite(your_adapter)` with an empty result before calling itself VSL-conformant. The suite mechanically proves — using a real `PreNode`/`Invariant` and a mutable side-effect counter, not just return-value checks — that your compiled gates:
|
|
284
|
+
|
|
285
|
+
1. Block before any side effect when a `PreNode`'s Gamma estimate is insufficient (the F1 property, checked mechanically).
|
|
286
|
+
2. Pass through normally when Gamma is sufficient.
|
|
287
|
+
3. Raise `InvariantViolation` specifically (not a bare `AutomationDeniedException`) when an `Invariant` fails.
|
|
288
|
+
4. Don't raise when an `Invariant` holds.
|
|
289
|
+
5. Are safely reusable — no state leaks between calls on the same compiled gate.
|
|
290
|
+
|
|
291
|
+
Deliberately absent from this list: writing to `VerbaLedger`. Ledger writes are the calling application's responsibility, never the adapter's — see [The ledger doesn't write itself](#the-ledger-doesnt-write-itself-read-this-before-assuming-an-audit-trail-exists) above. A conformant adapter should not call `ledger.write*` internally; doing so would silently couple gate compilation to a logging policy the application may not want.
|
|
292
|
+
|
|
293
|
+
`vsl_core.conformance.reference_adapter.PlainPythonReferenceAdapter` is the minimal reference implementation — proof the contract is satisfiable at all, not merely specified on paper. [`vsl-langgraph`](https://github.com/supersemantics/VSL-Langgraph) is the minimal *framework* implementation, for the same reason — read `src/vsl_langgraph/adapter.py` alongside `PlainPythonReferenceAdapter` to see how little actually changes between them, and why: most frameworks have nothing framework-specific to compile a gate *into*.
|
|
294
|
+
|
|
295
|
+
## Calling the compiled gate: two real integration shapes
|
|
296
|
+
|
|
297
|
+
Compiling a gate is the framework-agnostic half of the story. *Where* and *how* you actually call the resulting gate depends entirely on how the application you're integrating with is shaped — the conformance contract says nothing about this, on purpose, because it genuinely varies. Two shapes, both real, both verified against actual running code, not just described:
|
|
298
|
+
|
|
299
|
+
**One hook per guarded action.** If the framework gives you a natural per-action extension point — a node in a graph, a middleware slot, a decorator — wrap that action so the gate is checked immediately before it runs, and route around a denial the way the framework already routes. This is the common case, and it's what [`vsl-langgraph`](https://github.com/supersemantics/VSL-Langgraph)'s `gated_node`/`route_on_denial` helpers assume.
|
|
300
|
+
|
|
301
|
+
**No per-action hook — call the gate directly inside whatever dispatch point already exists.** Some real applications route every action through one shared dispatcher instead — e.g. a single "execute whichever tool the model picked" function, common in tool-calling agents — rather than one hook per action. There's nothing to *wrap* in that shape. The compiled gate is still just `async def gate(candidate_input) -> None`, so you call it directly, inline, immediately before the specific action you're guarding that call site, and catch the exception yourself. No adapter change needed — the gate doesn't know or care how it's called, which is exactly why this works without modification. Proven on a real, unfamiliar, third-party production LangGraph template that turned out to use a single shared tool dispatcher, not one node per tool — see [`building-with-vsl-core.md`](https://github.com/supersemantics/VSL-Core/blob/HEAD/docs/building-with-vsl-core.md#retrofitting-an-existing-agent-a-real-case-study) for the full case study.
|
|
302
|
+
|
|
303
|
+
## Install
|
|
304
|
+
|
|
305
|
+
```
|
|
306
|
+
pip install super-semantics-vsl
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
The package is published as `super-semantics-vsl`; in code you `import vsl_core` (the distribution
|
|
310
|
+
name and the module name differ, as with `beautifulsoup4` and `bs4`). For the optional immudb ledger
|
|
311
|
+
store: `pip install "super-semantics-vsl[immudb]"`.
|
|
312
|
+
|
|
313
|
+
For local development:
|
|
314
|
+
|
|
315
|
+
```
|
|
316
|
+
git clone https://github.com/supersemantics/VSL-Core.git
|
|
317
|
+
cd VSL-Core
|
|
318
|
+
pip install -e .
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
## Package layout
|
|
322
|
+
|
|
323
|
+
```
|
|
324
|
+
src/vsl_core/
|
|
325
|
+
├── exceptions.py exception hierarchy
|
|
326
|
+
├── rules_version.py ASSURANCE_RULES_VERSION (written into every gate-decision record)
|
|
327
|
+
├── metrics.py Delta, Gamma, GES, EEF, Beta, Threshold, AssuranceBasis
|
|
328
|
+
├── identity.py IdentityKey, ClusterKey, Instance, Evidence
|
|
329
|
+
├── ledger.py VerbaLedger, hash-chained LedgerEntry, gate-decision records, causal audit checks, checkpoints
|
|
330
|
+
├── immudb_store.py optional ImmuDBLedgerStore (JSONL plus verified immudb replication)
|
|
331
|
+
├── constructs.py AllowedState, PreNode, Invariant, TerminalState
|
|
332
|
+
├── cluster.py Cluster, ClusterPreNode
|
|
333
|
+
├── governance.py GovernanceAuthority, HumanAuthorisedTransition, Proofing, Binding, Specification
|
|
334
|
+
├── catalog/ Drift Class / Stabilisation Operator / Legion data + loader
|
|
335
|
+
└── conformance/ VSLAdapter protocol, run_conformance_suite, reference adapter
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
## Verifying the zero-dependency / framework-agnostic guarantee
|
|
339
|
+
|
|
340
|
+
```
|
|
341
|
+
grep -rn "^from agents\|^import agents\|^from langgraph\|^import langgraph\|^from langchain\|^import langchain\|^from openai\|^import openai\|^from anthropic\|^import anthropic\|RunContextWrapper\|InputGuardrail\|GuardrailFunctionOutput" src/vsl_core/
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
should return nothing. A fresh virtual environment containing only `vsl-core` and `pytest` should install and pass the full test suite with no other packages pulled in.
|
|
345
|
+
|
|
346
|
+
## What a VerbaCertificate does *not* claim
|
|
347
|
+
|
|
348
|
+
`VerbaLedger.issue_certificate()` only returns a certificate if all five audit checks pass, and even then: **it does not guarantee no Inadmissible State was ever reached.** It certifies that every *detected* Drift event was addressed, Terminal States were properly escalated, and governance was continuously monitored — it certifies the governance *process*, not the underlying system, model, or domain. This disclaimer is embedded in `VerbaCertificate.NOTE` and surfaced in its `__str__`, not just documented here.
|
|
349
|
+
|
|
350
|
+
## License
|
|
351
|
+
|
|
352
|
+
MIT — see [LICENSE](https://github.com/supersemantics/VSL-Core/blob/HEAD/LICENSE). Copyright Super Semantics.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
super_semantics_vsl-0.3.1.dist-info/licenses/LICENSE,sha256=k_93isT77tF7gkFv2yNPM8ESgDazhABxVak4K5tmjs8,1072
|
|
2
|
+
vsl_core/__init__.py,sha256=PwhoNJqlw76B2C0C2ni23XV0SqAS6C1IjQEbeBxSkWk,4066
|
|
3
|
+
vsl_core/cluster.py,sha256=MBaKtJbztoWnUQM9NvsEgI4xUyLQx2YxhfCke1BddLE,3348
|
|
4
|
+
vsl_core/constructs.py,sha256=0UG9iHJLil4vZECQm9WYqnqKdBaOnY-8l6IUiLzSXZU,5983
|
|
5
|
+
vsl_core/exceptions.py,sha256=MluFX7Cu9sIrRVpnFX1j248_Jvqe_BaN8iUfuq_z-JY,4175
|
|
6
|
+
vsl_core/governance.py,sha256=cn1AsFP8KaLoDihzcXnJYaY0v1rlekyaMwAEWGzvYxs,8291
|
|
7
|
+
vsl_core/identity.py,sha256=wn33KE_172LFDtSdJ2RUyaKnhweUXBQG4fRu7UAlUYA,5935
|
|
8
|
+
vsl_core/immudb_store.py,sha256=M-sIWhEg-c8fNSpRh3HgeOxIk9NVt2Q3FjlnwUDI6t0,8633
|
|
9
|
+
vsl_core/ledger.py,sha256=ye8dVvrHKUB0GHCr7cxgWJXwkv2sZRvfkQ8e619dmdQ,38788
|
|
10
|
+
vsl_core/metrics.py,sha256=sQgvgtQA23KXhZFJdeBr-Vul2sAv1LSs439kD7ys0C4,15223
|
|
11
|
+
vsl_core/rules_version.py,sha256=F83lOldst_kLb-14_BShPx8Y5LFhMKXA-EcEGQ6-c_8,785
|
|
12
|
+
vsl_core/catalog/__init__.py,sha256=GbkoTvMn3vX6JHkwyIEToVnv2AdGuNoi0X6n62_a-io,258
|
|
13
|
+
vsl_core/catalog/drift_classes.json,sha256=75CbpK7Zf3P7m1UKe0F-fvdH8bdq_Tk5kmkW2MRcZRM,43102
|
|
14
|
+
vsl_core/catalog/legion_patterns.json,sha256=rJ1Sxprxp5cHSb783Pe14qrNKWtIiH_sD4n5XA6f6dU,75432
|
|
15
|
+
vsl_core/catalog/loader.py,sha256=LsbhkrqykneBy-zWPPPKI-LddNF8R16qNPFRf6tww-Y,13276
|
|
16
|
+
vsl_core/conformance/__init__.py,sha256=hIWRBsMeyKvjUQJ0CF61QN8QI4Y-Me_uVbbL_1js-sw,344
|
|
17
|
+
vsl_core/conformance/protocol.py,sha256=KW59W5cHn-8Y0Ww_zV1n3nGsqTjX4r4sS7UHsgJvacI,1075
|
|
18
|
+
vsl_core/conformance/reference_adapter.py,sha256=ffrjxSBKlYL8wNSCdZ-PnwgMC8ViIL2cd8dkO_Y3r0U,1839
|
|
19
|
+
vsl_core/conformance/suite.py,sha256=U3VMcRVYE_QOZfxYptvGLbp13RKGbYoSbjOKOSqlMAk,8797
|
|
20
|
+
super_semantics_vsl-0.3.1.dist-info/METADATA,sha256=1iAVaPl4BjA6ApPpbPSot8AVgdOjrB4k0YPva0i1Vbc,35307
|
|
21
|
+
super_semantics_vsl-0.3.1.dist-info/WHEEL,sha256=mOdXR9C3wMVov7cSY8PY-XCzo3SmmWCHvGQr5csJoao,91
|
|
22
|
+
super_semantics_vsl-0.3.1.dist-info/top_level.txt,sha256=Qw4Z0YW0l4KZN6Fwb2NSQIkexFYatVcTnW9pMqfKbqk,9
|
|
23
|
+
super_semantics_vsl-0.3.1.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Super Semantics
|
|
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.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
vsl_core
|
vsl_core/__init__.py
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"""vsl-core: the framework-agnostic and model-agnostic foundation of VSL
|
|
2
|
+
(VERBA Specification Language) -- a governance vocabulary for deciding
|
|
3
|
+
whether an automated system's next action is allowed to happen, and
|
|
4
|
+
proving that decision was made.
|
|
5
|
+
|
|
6
|
+
Zero third-party runtime dependencies. Never imports any agent-framework
|
|
7
|
+
package (agents, langgraph, langchain, ...) or model-provider SDK (openai,
|
|
8
|
+
anthropic, ...) anywhere under this package. Framework adapters that wire
|
|
9
|
+
this vocabulary into a specific agent framework are separate packages
|
|
10
|
+
(vsl-<framework>), out of scope here -- see vsl_core.conformance for the
|
|
11
|
+
contract those adapters must satisfy.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from .cluster import Cluster, ClusterInadmissibleState, ClusterPreNode
|
|
15
|
+
from .constructs import (
|
|
16
|
+
AllowedState,
|
|
17
|
+
DriftMonitor,
|
|
18
|
+
Fallback,
|
|
19
|
+
FormationLayerIntervention,
|
|
20
|
+
InadmissibleState,
|
|
21
|
+
Invariant,
|
|
22
|
+
PreNode,
|
|
23
|
+
TerminalState,
|
|
24
|
+
register_invariant,
|
|
25
|
+
registered_invariants,
|
|
26
|
+
)
|
|
27
|
+
from .exceptions import (
|
|
28
|
+
AutomationDeniedException,
|
|
29
|
+
CatalogValidationError,
|
|
30
|
+
ConformanceError,
|
|
31
|
+
InvariantViolation,
|
|
32
|
+
LedgerIntegrityError,
|
|
33
|
+
VSLError,
|
|
34
|
+
)
|
|
35
|
+
from .governance import (
|
|
36
|
+
Binding,
|
|
37
|
+
GovernanceAuthority,
|
|
38
|
+
HumanAuthorisedTransition,
|
|
39
|
+
Proofing,
|
|
40
|
+
Specification,
|
|
41
|
+
request_re_enablement,
|
|
42
|
+
)
|
|
43
|
+
from .identity import ClusterKey, Evidence, IdentityKey, Instance
|
|
44
|
+
from .immudb_store import ImmuDBConfig, ImmuDBLedgerStore, ImmuDBSyncError
|
|
45
|
+
from .ledger import (
|
|
46
|
+
DRIFT_DETECTED_KEY,
|
|
47
|
+
GATE_ALLOWED_KEY,
|
|
48
|
+
HANDOVER_KEY,
|
|
49
|
+
GENESIS_HASH,
|
|
50
|
+
HUMAN_AUTHORISED_TRANSITION,
|
|
51
|
+
LEDGER_SCHEMA_VERSION,
|
|
52
|
+
PRIMITIVE_NAME_KEY,
|
|
53
|
+
RE_ENABLEMENT,
|
|
54
|
+
RULES_VERSION_KEY,
|
|
55
|
+
VERIFICATION_RESULT_KEY,
|
|
56
|
+
InMemoryLedgerStore,
|
|
57
|
+
JsonlLedgerStore,
|
|
58
|
+
LedgerAuditReport,
|
|
59
|
+
LedgerCheckpoint,
|
|
60
|
+
LedgerEntry,
|
|
61
|
+
LedgerEntryType,
|
|
62
|
+
LedgerStore,
|
|
63
|
+
VerbaCertificate,
|
|
64
|
+
VerbaLedger,
|
|
65
|
+
VerificationResult,
|
|
66
|
+
)
|
|
67
|
+
from .metrics import (
|
|
68
|
+
EEF,
|
|
69
|
+
GAMMA_MONITORING_THRESHOLD,
|
|
70
|
+
GES,
|
|
71
|
+
JACOBIAN_RED_FLAG_THRESHOLD,
|
|
72
|
+
KL_MONITORING_THRESHOLD,
|
|
73
|
+
ROBUST_GAMMA_DEFAULT_THRESHOLD,
|
|
74
|
+
ROBUST_GAMMA_HIGH_STAKES_THRESHOLD,
|
|
75
|
+
AssuranceBasis,
|
|
76
|
+
AssuranceLevel,
|
|
77
|
+
Beta,
|
|
78
|
+
Delta,
|
|
79
|
+
EEFZone,
|
|
80
|
+
F2Modification,
|
|
81
|
+
GammaEstimate,
|
|
82
|
+
Threshold,
|
|
83
|
+
)
|
|
84
|
+
from .rules_version import ASSURANCE_RULES_VERSION
|
|
85
|
+
|
|
86
|
+
__version__ = "0.3.0"
|
|
87
|
+
|
|
88
|
+
__all__ = [
|
|
89
|
+
"__version__",
|
|
90
|
+
# constructs
|
|
91
|
+
"AllowedState",
|
|
92
|
+
"InadmissibleState",
|
|
93
|
+
"Fallback",
|
|
94
|
+
"Invariant",
|
|
95
|
+
"PreNode",
|
|
96
|
+
"TerminalState",
|
|
97
|
+
"DriftMonitor",
|
|
98
|
+
"FormationLayerIntervention",
|
|
99
|
+
"register_invariant",
|
|
100
|
+
"registered_invariants",
|
|
101
|
+
# cluster
|
|
102
|
+
"Cluster",
|
|
103
|
+
"ClusterInadmissibleState",
|
|
104
|
+
"ClusterPreNode",
|
|
105
|
+
# identity
|
|
106
|
+
"IdentityKey",
|
|
107
|
+
"ClusterKey",
|
|
108
|
+
"Instance",
|
|
109
|
+
"Evidence",
|
|
110
|
+
# governance
|
|
111
|
+
"GovernanceAuthority",
|
|
112
|
+
"HumanAuthorisedTransition",
|
|
113
|
+
"Proofing",
|
|
114
|
+
"Binding",
|
|
115
|
+
"Specification",
|
|
116
|
+
"request_re_enablement",
|
|
117
|
+
# ledger
|
|
118
|
+
"GENESIS_HASH",
|
|
119
|
+
"LedgerEntryType",
|
|
120
|
+
"LedgerEntry",
|
|
121
|
+
"LedgerStore",
|
|
122
|
+
"InMemoryLedgerStore",
|
|
123
|
+
"JsonlLedgerStore",
|
|
124
|
+
"ImmuDBConfig",
|
|
125
|
+
"ImmuDBLedgerStore",
|
|
126
|
+
"ImmuDBSyncError",
|
|
127
|
+
"LedgerAuditReport",
|
|
128
|
+
"LedgerCheckpoint",
|
|
129
|
+
"VerbaCertificate",
|
|
130
|
+
"VerbaLedger",
|
|
131
|
+
"HUMAN_AUTHORISED_TRANSITION",
|
|
132
|
+
"RE_ENABLEMENT",
|
|
133
|
+
"DRIFT_DETECTED_KEY",
|
|
134
|
+
"VERIFICATION_RESULT_KEY",
|
|
135
|
+
"PRIMITIVE_NAME_KEY",
|
|
136
|
+
"GATE_ALLOWED_KEY",
|
|
137
|
+
"HANDOVER_KEY",
|
|
138
|
+
"RULES_VERSION_KEY",
|
|
139
|
+
"VerificationResult",
|
|
140
|
+
"LEDGER_SCHEMA_VERSION",
|
|
141
|
+
# assurance rules
|
|
142
|
+
"ASSURANCE_RULES_VERSION",
|
|
143
|
+
# metrics
|
|
144
|
+
"AssuranceLevel",
|
|
145
|
+
"AssuranceBasis",
|
|
146
|
+
"F2Modification",
|
|
147
|
+
"GammaEstimate",
|
|
148
|
+
"Delta",
|
|
149
|
+
"GES",
|
|
150
|
+
"EEF",
|
|
151
|
+
"EEFZone",
|
|
152
|
+
"Beta",
|
|
153
|
+
"Threshold",
|
|
154
|
+
"ROBUST_GAMMA_DEFAULT_THRESHOLD",
|
|
155
|
+
"ROBUST_GAMMA_HIGH_STAKES_THRESHOLD",
|
|
156
|
+
"GAMMA_MONITORING_THRESHOLD",
|
|
157
|
+
"JACOBIAN_RED_FLAG_THRESHOLD",
|
|
158
|
+
"KL_MONITORING_THRESHOLD",
|
|
159
|
+
# exceptions
|
|
160
|
+
"VSLError",
|
|
161
|
+
"AutomationDeniedException",
|
|
162
|
+
"InvariantViolation",
|
|
163
|
+
"LedgerIntegrityError",
|
|
164
|
+
"CatalogValidationError",
|
|
165
|
+
"ConformanceError",
|
|
166
|
+
]
|