Assurance Reference¶
EvidenceStrength¶
Vocabulary¶
Two EvidenceStrength vocabularies coexist. Both are values of class EvidenceStrength(str, Enum) in lola/ssfc_taxonomy.py.
| Value | Meaning |
|---|---|
PROVED |
Mathematically complete for the stated scope. |
PROVED-CONDITIONAL |
Holds subject to the listed ASSUME clauses; proved by universal attractor analysis. Recovery analysis only. |
NOT-PROVED |
Analysis cannot establish the property. Not a solver failure; a design finding. Recovery analysis only. |
NOT-REFUTED |
Conservative or over-approximative; no counterexample found but completeness is not guaranteed. |
UNKNOWN |
Solver timeout or encoding gap. |
ASSUMED |
Explicit engineering assumption; not verified. |
Scope of recovery-specific values¶
PROVED-CONDITIONAL and NOT-PROVED are emitted only by the recovery analysis (lola/ssfc_recovery.py). The SSFC structural claims produced by check_all() use PROVED and NOT-REFUTED; they do not emit PROVED-CONDITIONAL or NOT-PROVED.
SSFC Structural Claims¶
These claims are produced by check_all() in lola/ssfc_report.py.
| Claim ID | What it checks | Evidence strength | Approximation / scope |
|---|---|---|---|
C-SAF |
P-invariant: every reachable marking is a valid SSFC marking (no impossible token patterns). | PROVED |
Complete algebraically. |
C-INT |
Region integrity: every reachable marking respects region membership (each region has exactly one active place). | PROVED |
Complete over NetModel. |
C-DEAD |
No dead states: every leaf state (non-superstate) has at least one outgoing transition. | PROVED |
Structural; does not check guard satisfiability. |
C-SYNC-DEAD |
No JOIN source orphan: every place in a JOIN's source set is reachable. | PROVED |
Stated scope only; co-reachability across regions is out of scope. |
C-GUARD-SAT |
Guard satisfiability: every transition guard is satisfiable under the type domain. | PROVED |
Complete over BitVec domain. |
C-DET |
Guard disjointness: no two outgoing guards from the same state can both be satisfied simultaneously. | PROVED |
Complete over BitVec domain. |
C-DATA-DEAD |
Data dead transition: at least one transition guard per non-terminal state is satisfiable under all ASSUMEs. | PROVED |
Complete over BitVec domain. |
C-REACH |
State reachability: a SAT-based BFS finds a path to the state. | NOT-REFUTED on PASS (path found is not a complete proof); PROVED on WARN (no path found even in the over-approximation confirms true unreachability). |
Per-edge-SAT BFS; sound (no false WARN) but incomplete on PASS. |
C-HOME |
Home-state reachability from all marking graph states. | NOT-REFUTED |
Per-edge-SAT BFS witness. |
C-NO-STUCK-MARKING |
No terminal non-home marking is reachable. | NOT-REFUTED |
Marking-graph BFS over reachable markings. |
C-INV |
State invariant (INVARIANT annotation): an SMT invariant claim at a specific state. |
PROVED if proved; NOT-REFUTED if validated by testing only. |
Present only when ssfc is passed to check_all(). |
C-ASSUME |
ASSUME clause acknowledgement: the SSFC has explicit ASSUME clauses used as premises. | PROVED (structural). |
Present only when ssfc is passed to check_all(). |
C-STRUCT-PATH |
Structural liveness path: a guard-ignoring BFS confirms a path from the initial state to a terminal or home state. | PROVED |
Guards ignored; not a liveness guarantee. |
C-STRUCT-REACH |
Structural reachability per place: every place in the net is reachable from the initial marking (marking-graph BFS). | PROVED |
Marking graph required. |
C-STRUCT-HOME |
Backward reachability to home markings: every reachable non-terminal marking has a path to a home marking (backward BFS). | PROVED |
Marking graph required. |
C-REVERSI |
Reversibility to the initial marking: every reachable non-terminal marking can reach the initial marking. | PROVED on PASS; NOT-REFUTED on WARN. |
Backward BFS from each marking to the initial marking; marking graph required. |
C-NO-STUCK-Z3 |
No stuck marking under Z3: no reachable marking has all transition guards UNSAT under ASSUMEs. | PROVED |
Marking-graph + Z3; exact query. |
C-WITHIN-FEASIBLE |
WITHIN annotation: a feasibility witness exists for the timing bound. | NOT-REFUTED |
Existential feasibility; not a timing guarantee. |
Signal Ownership Analysis¶
OwnershipClass¶
Defined in lola/ssfc_ownership.py.
| Class | Meaning |
|---|---|
SINGLE_WRITER |
Exactly one WriteSite writes to this signal. |
EXCLUSIVE_MULTI_WRITER |
Multiple WriteSites exist; all pairs are proved mutually exclusive (cannot be active in the same scan). Mutual exclusion is formally proved; safe to use. |
COMPATIBLE_MULTI_WRITER |
Some co-activatable WriteSite pairs exist, but all such pairs are proved to write the same value. No conflict. |
CONFLICTING |
At least one co-activatable pair of WriteSites writes different or unknown values. Design finding: the signal has a write conflict. |
UNKNOWN |
Co-activation could not be determined (mutual exclusion neither proved nor disproved). Does not imply conflict. |
Epistemics¶
CONFLICTINGrequires: co-activatable = True AND compatible = False.- Co-activatable but value-unknown →
UNKNOWN, notCONFLICTING. EXCLUSIVE_MULTI_WRITERis architecturally safe: the mutual exclusion proof covers all scan-cycle configurations.
API¶
analyze_ownership(ssfc, net, mg) → OwnershipReport
| Method | Returns | Meaning |
|---|---|---|
OwnershipReport.conflict_free() |
bool |
True if no CONFLICTING signals. |
OwnershipReport.analysis_complete() |
bool |
True if no UNKNOWN signals. |
OwnershipReport.is_clean() |
bool |
conflict_free() AND no policy violations. |
OwnershipReport.conflicts() |
List[SignalOwnership] |
All CONFLICTING signals. |
OwnershipReport.unknowns() |
List[SignalOwnership] |
All UNKNOWN signals. |
Transitive Component Effects¶
When an SSFC has WIRING blocks that reference State.X (state activity marker), LoLa traces the chain:
state activation → wiring → child_instance.input → (child FB) → child_instance.output → parent output
Each such chain is a ComponentEffect. They appear in OwnershipReport.component_effects.
Policy Gates¶
Configured in project TOML under [ssfc_assurance].
| Key | Default | Effect |
|---|---|---|
allow_exclusive_multi_writer |
true |
Permit EXCLUSIVE_MULTI_WRITER signals. |
allow_compatible_multi_writer |
true |
Permit COMPATIBLE_MULTI_WRITER signals. |
allow_unknown |
true |
Permit UNKNOWN signals. |
allow_conflict |
false |
Permit CONFLICTING signals. Enabling is unusual. |
Recovery and Progress Analysis¶
Claim Levels¶
Produced by analyze_recovery(source_state, home_state, ssfc, net, mg) in lola/ssfc_recovery.py.
| Level | Quantifier | What is proved | Approximation |
|---|---|---|---|
STRUCTURAL |
∃ | A path from source to home exists in the marking graph, ignoring all guards. | Guards not checked; over-approximation. |
POSSIBLE |
∃ | A path exists where every transition guard is satisfiable under ASSUMEs (SAT). | Per-edge SAT; guard satisfiability checked independently per transition, not as a coherent multi-scan trace. |
GUARANTEED |
∀ | Every admissible execution from source eventually reaches home. Proved by universal attractor over PossibleSucc(M). |
Requires ASSUME clauses for non-tautological guards; result may be PROVED-CONDITIONAL. |
BOUNDED |
∀ | Every admissible execution reaches home within N scans. N = max attractor rank over source markings. | Same as GUARANTEED; additionally, each scan fires exactly one transition (no-stall guaranteed by attractor membership condition). |
Definitions¶
PossibleSucc(M) = {M′ | SAT(guard(t) ∧ assumes) for some transition t: M→M′}. All markings reachable from M in one scan under some admissible input.
no_stall(M) = UNSAT(assumes ∧ ¬g₁ ∧ … ∧ ¬gₙ) where g₁…gₙ are outgoing guards. The system cannot idle in M indefinitely.
Universal attractor:
Attr₀ = home_marks
Attr_{k+1} = Attr_k ∪ {M | no_stall(M) ∧ PossibleSucc(M) ≠ ∅ ∧ PossibleSucc(M) ⊆ Attr_k}
Attractor rank:
B(home) = 0
B(M) = 1 + max_{M′ ∈ PossibleSucc(M)} B(M′), for M ∈ Attr \ home_marks
BOUNDED = max_{M ∈ source ∩ Attr} B(M)
EvidenceStrength for Recovery Claims¶
| Strength | Condition |
|---|---|
PROVED |
Claim holds without any ASSUME clauses. |
PROVED-CONDITIONAL |
Claim holds given the listed ASSUME clauses (assumptions_used is non-empty). |
NOT-PROVED |
Claim does not hold: the analysis found a reachable marking outside the attractor, or a stall-possible marking. Design finding; not a solver failure. |
RecoveryClaim Fields¶
RecoveryClaim has four RecoveryEvidence sub-results:
| Field | Type | Description |
|---|---|---|
.structural |
RecoveryEvidence |
Result for the STRUCTURAL level. |
.possible |
RecoveryEvidence |
Result for the POSSIBLE level. |
.guaranteed |
RecoveryEvidence |
Result for the GUARANTEED level. |
.bounded |
RecoveryEvidence |
Result for the BOUNDED level. |
RecoveryEvidence Fields¶
| Field | Type | Description |
|---|---|---|
.strength |
EvidenceStrength |
Classification of this level's result. |
.assumptions_used |
List[str] |
Load-bearing ASSUME labels: those whose removal causes GUARANTEED to fail (deletion test). May be smaller than the full ASSUME list. |
.bound_scans |
Optional[int] |
For BOUNDED: the worst-case scan count. None otherwise. |
.reason |
str |
Human-readable explanation of the result. |
GuidedSynthesisWarrant¶
A GuidedSynthesisWarrant records that a combinational FUNCTION_BLOCK's
RULE-defined outputs were proved correct by a bounded model checker (Kani or CBMC),
not by the LoLa internal Z3 synthesiser.
Module: lola.guided_synthesis\
Concept: Guided synthesis and EXTERN — same warrant, different source\
How-to: Guided synthesis workflow
Fields¶
| Field | Type | Description |
|---|---|---|
block |
str |
Name of the FUNCTION_BLOCK the warrant covers. |
declaration_sha256 |
str |
SHA-256 of the canonical block contract (inputs, outputs, ASSUME, RULE, synthesis targets). Stable across formatting changes; changes on any contract change. |
semantic_contract_sha256 |
str |
SHA-256 of the canonical expanded AST definitions behind semantic predicates. Stable across locations/formatting and changed by semantic implementation changes. |
candidate_abi |
str |
ABI version of the accepted candidate, e.g. "lola-gs-rust-combinational-v2". |
candidate_body_sha256 |
str |
SHA-256 of the accepted candidate body text. |
proof_backend |
str |
Proof tool: "kani" or "cbmc". |
proof_source_sha256 |
str |
SHA-256 of the proof harness source that was run. |
rules |
tuple[str, ...] |
Human-readable RULE texts from the block's contract. |
target |
str |
Code-generation target: "rust" or "st". |
digest |
str |
SHA-256 of all fields above (excluding digest itself). |
Factory function¶
from lola.guided_synthesis import make_guided_synthesis_warrant
warrant = make_guided_synthesis_warrant(acceptance_json)
acceptance_json must be a dict with schema: 3, produced by
acceptance_receipt() and written to acceptance.json by lola guided accept.
Raises GuidedSynthesisError if the schema is unknown or required keys are missing.
Digest function¶
from lola.guided_synthesis import guided_synthesis_warrant_digest
digest = guided_synthesis_warrant_digest(warrant)
Returns the SHA-256 of the canonical warrant payload (all fields except digest).
Used for content-addressing and tamper detection.
Using with compile_source¶
from lola import compiler
from lola.guided_synthesis import make_guided_synthesis_warrant
import json
warrant = make_guided_synthesis_warrant(json.loads(acceptance_path.read_text()))
comp = compiler.compile_source(
source,
guided_synthesis_warrants={"PumpBank": warrant},
)
Parameter: guided_synthesis_warrants: dict[str, GuidedSynthesisWarrant] | None
When provided, the compiler checks each block whose name appears as a key. If the
block has synthesis targets and the warrant's declaration_sha256 matches the
current source contract, CEGIS synthesis is skipped and the warrant discharges the
RULE proof obligations.
Errors raised by compile_source:
| Error | Cause |
|---|---|
ValueError: must be a GuidedSynthesisWarrant |
Dict value is not a GuidedSynthesisWarrant instance. |
ValueError: declaration_sha256 does not match |
Source contract changed after acceptance; re-run lola guided accept. |
ValueError: could not compute declaration digest |
Source could not be re-parsed for digest comparison. |
In program.assurance¶
After successful compilation with a warrant, the warrant is stored in:
program.assurance.guided_synthesis_warrants # dict[str, GuidedSynthesisWarrant]
Keyed by block name. Included in the G2.8 assurance seal.
Acceptance receipt format (schema: 3)¶
The acceptance receipt written by lola guided accept has this structure:
{
"schema": 3,
"block": "PumpBank",
"target": "rust",
"request_version": 1,
"candidate_abi": "lola-gs-rust-combinational-v2",
"declaration_sha256": "<64 hex chars>",
"semantic_contract_sha256": "<64 hex chars>",
"source_sha256": "<64 hex chars>",
"candidate_body_sha256": "<64 hex chars>",
"proof_backend": "kani",
"proof_source_sha256": "<64 hex chars>",
"rules": ["COUNT(i IN 0..2 : run[i]) = demand", "..."]
}
source_sha256 is the SHA-256 of the source text at acceptance time (for traceability).
declaration_sha256 is the stable contract identity (used for cache and warrant binding).
It includes semantic_contract_sha256, which binds the compiler-owned expanded
meaning of semantic predicates rather than only their human-readable spelling.