Skip to main content

qualia_core_db/modalities/logic/
logic_modalities_shacl.rs

1//! SHACL extensions for ALL Webizen VM logic modalities.
2//!
3//! Every logic modality wired to a `Native*` opcode carries a SHACL
4//! `q42:<Name>ConfigurationShape` constraining its parameters and the
5//! predicate/opcode packing convention it relies on. Namespace
6//! `https://webizen.org/q42#` (mirrors `core_modalities_shacl.rs`). The TTL is
7//! also mirrored at `shapes/logic-modalities.shacl.ttl`.
8
9/// The logic modalities that MUST each have a configuration shape below.
10/// Used by the completeness test so a new modality cannot land without its SHACL.
11pub const LOGIC_MODALITY_SHAPES: [&str; 42] = [
12    "DeonticConfigurationShape",
13    "EpistemicConfigurationShape",
14    "LinearConfigurationShape",
15    "AspConfigurationShape",
16    "ParaconsistentConfigurationShape",
17    "DialecticalConfigurationShape",
18    "DefeasibleConfigurationShape",
19    "LtlConfigurationShape",
20    "AllenIntervalConfigurationShape",
21    "ProbabilisticConfigurationShape",
22    "DlSubsumptionConfigurationShape",
23    "ArgumentationConfigurationShape",
24    "MetricTemporalConfigurationShape",
25    "ContraryToDutyConfigurationShape",
26    "CausalNecessityConfigurationShape",
27    "AbductiveConfigurationShape",
28    "ClosedWorldConfigurationShape",
29    "FuzzyConfigurationShape",
30    "CtlConfigurationShape",
31    "ModalConfigurationShape",
32    "Rcc8ConfigurationShape",
33    // ── SDL⁺ deontic stack (DEONTIC_LOGIC_PLAN Phases 1–6) ──
34    "DeonticLifecycleConfigurationShape",
35    "DeonticExtConfigurationShape",
36    "JuralConfigurationShape",
37    "StitConfigurationShape",
38    "MensReaConfigurationShape",
39    "InteractionGovernanceConfigurationShape",
40    "MetaDeonticConfigurationShape",
41    // ── Extended legal-logic stack (legal_logic.md §16–§30) ──
42    "ResponsibilityStatusConfigurationShape",
43    "SystemicMetaGuardConfigurationShape",
44    "JuridicalCapacityConfigurationShape",
45    "DelegationChainConfigurationShape",
46    "ContractFormationConfigurationShape",
47    "ValueFlowConfigurationShape",
48    "CapabilityGapConfigurationShape",
49    "ResilientIdentityConfigurationShape",
50    "ZkGatedConfigurationShape",
51    "ProportionalityConfigurationShape",
52    "SenseTranslationConfigurationShape",
53    "ConsensusConfigurationShape",
54    "ManifoldLogicConfigurationShape",
55    "CarrierBindingConfigurationShape",
56];
57
58/// SHACL TTL covering every VM logic modality (configuration + structural shapes).
59pub fn get_logic_modalities_shacl_ttl() -> &'static str {
60    r#"
61@prefix q42: <https://webizen.org/q42#> .
62@prefix sh:  <http://www.w3.org/ns/shacl#> .
63@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
64
65# ── Deontic (O/P/F) ─────────────────────────────────────────────────────────
66q42:DeonticConfigurationShape a sh:NodeShape ;
67    sh:property [ sh:path q42:deonticOpcode ; sh:datatype xsd:unsignedByte ;
68        sh:minInclusive 16 ; sh:maxInclusive 18 ;
69        sh:message "Deontic opcode must be OP_OBLIGATE(0x10) | OP_PERMIT(0x11) | OP_FORBID(0x12)." ] .
70
71# ── Epistemic (Knows / Believes / Common-Knowledge + named bands + nesting) ──
72q42:EpistemicConfigurationShape a sh:NodeShape ;
73    sh:property [ sh:path q42:epistemicOpcode ; sh:datatype xsd:unsignedByte ;
74        sh:minInclusive 32 ; sh:maxInclusive 34 ;
75        sh:message "Epistemic opcode ∈ {OP_KNOWS 0x20, OP_BELIEVES 0x21, OP_COMMON_KNOWLEDGE 0x22}." ] ;
76    sh:property [ sh:path q42:certainty ; sh:datatype xsd:unsignedByte ;
77        sh:minInclusive 0 ; sh:maxInclusive 255 ;
78        sh:message "Certainty band (predicate bits [8..15]): knows 255, affirms 230, believes/recognizes 200, considers 128, supposes 100, suspects 80, speculates 50, doubts 20. ≥128 ⇒ Active, else Uncertain; KNOWS/COMMON_KNOWLEDGE are categorically Active." ] ;
79    sh:property [ sh:path q42:nestingDepth ; sh:datatype xsd:unsignedByte ;
80        sh:minInclusive 0 ; sh:maxInclusive 255 ;
81        sh:message "Nested-attitude depth (predicate bits [16..], NESTING_BIT_SHIFT) for RDF-Star K(B(φ))." ] ;
82    sh:property [ sh:path q42:worldContext ; sh:nodeKind sh:IRI ;
83        sh:message "0 = all worlds; else the claim is scoped to that possible-world/context hash." ] ;
84    sh:property [ sh:path q42:agentDid ; sh:nodeKind sh:IRI ;
85        sh:message "0 = all agents; else the attitude is held by that specific agent DID (COMMON_KNOWLEDGE excepted)." ] .
86
87# ── Linear (resource consumption) ───────────────────────────────────────────
88q42:LinearConfigurationShape a sh:NodeShape ;
89    sh:property [ sh:path q42:linearResource ; sh:nodeKind sh:IRI ; sh:minCount 1 ;
90        sh:message "A linear gate names the resource quin it consumes." ] .
91
92# ── ASP (stable models) ─────────────────────────────────────────────────────
93q42:AspConfigurationShape a sh:NodeShape ;
94    sh:property [ sh:path q42:maxStableModels ; sh:datatype xsd:integer ;
95        sh:minInclusive 1 ; sh:maxInclusive 8 ;
96        sh:message "Stable models enumerated ≤ MAX_STABLE_MODELS (8)." ] .
97
98# ── Paraconsistent ──────────────────────────────────────────────────────────
99q42:ParaconsistentConfigurationShape a sh:NodeShape ;
100    sh:property [ sh:path q42:isolateContradictions ; sh:datatype xsd:boolean ;
101        sh:message "Paraconsistent routing isolates contradictory quins." ] .
102
103# ── Dialectical (thesis/antithesis → synthesis) ─────────────────────────────
104q42:DialecticalConfigurationShape a sh:NodeShape ;
105    sh:property [ sh:path q42:minFacts ; sh:datatype xsd:integer ; sh:minInclusive 2 ;
106        sh:message "Dialectical synthesis requires ≥ 2 contradictory facts." ] .
107
108# ── Defeasible (q42:unless) ─────────────────────────────────────────────────
109q42:DefeasibleConfigurationShape a sh:NodeShape ;
110    sh:property [ sh:path q42:defeaterBit ; sh:datatype xsd:boolean ;
111        sh:message "A defeater node sets the DEFEATER_BIT (predicate bit 63)." ] .
112
113# ── Temporal LTL ────────────────────────────────────────────────────────────
114q42:LtlConfigurationShape a sh:NodeShape ;
115    sh:property [ sh:path q42:ltlOpcode ; sh:datatype xsd:unsignedByte ;
116        sh:minInclusive 64 ; sh:maxInclusive 68 ;
117        sh:message "LTL opcode ∈ {Globally 0x40 … Release 0x44}; compares the FULL predicate (PLAN §9.2)." ] .
118
119# ── Allen interval algebra ──────────────────────────────────────────────────
120q42:AllenIntervalConfigurationShape a sh:NodeShape ;
121    sh:property [ sh:path q42:allenRelation ; sh:datatype xsd:unsignedByte ;
122        sh:minInclusive 0 ; sh:maxInclusive 6 ;
123        sh:message "Allen relation ∈ {Before 0 … Equals 6}." ] .
124
125# ── Probabilistic (Bayesian threshold) ──────────────────────────────────────
126q42:ProbabilisticConfigurationShape a sh:NodeShape ;
127    sh:property [ sh:path q42:weight ; sh:datatype xsd:decimal ;
128        sh:minInclusive 0.0 ; sh:maxInclusive 1.0 ;
129        sh:message "A probabilistic belief weight is a probability in [0,1]." ] .
130
131# ── Description-logic subsumption ───────────────────────────────────────────
132q42:DlSubsumptionConfigurationShape a sh:NodeShape ;
133    sh:property [ sh:path q42:subClassPredicate ; sh:nodeKind sh:IRI ; sh:minCount 1 ;
134        sh:message "DL subsumption walks transitive rdfs:subClassOf edges." ] .
135
136# ── Argumentation (Dung grounded) ───────────────────────────────────────────
137q42:ArgumentationConfigurationShape a sh:NodeShape ;
138    sh:property [ sh:path q42:maxArguments ; sh:datatype xsd:integer ;
139        sh:minInclusive 1 ; sh:maxInclusive 128 ;
140        sh:message "Grounded-extension membership over ≤ MAX_GROUNDED_ARGS (128) arguments." ] .
141
142# ── Metric/timed temporal (deadlines) ───────────────────────────────────────
143q42:MetricTemporalConfigurationShape a sh:NodeShape ;
144    sh:property [ sh:path q42:window ; sh:datatype xsd:integer ; sh:minInclusive 0 ;
145        sh:message "MTL 'within' window is a non-negative duration; event timestamps live in metadata." ] .
146
147# ── Contrary-to-duty (dyadic deontic) ───────────────────────────────────────
148q42:ContraryToDutyConfigurationShape a sh:NodeShape ;
149    sh:property [ sh:path q42:primaryObligation ; sh:nodeKind sh:IRI ; sh:minCount 1 ;
150        sh:message "CTD names the primary (breached) obligation." ] ;
151    sh:property [ sh:path q42:reparation ; sh:nodeKind sh:IRI ; sh:minCount 1 ;
152        sh:message "CTD names the secondary reparation obligation required after breach." ] .
153
154# ── Causal necessity (but-for) ──────────────────────────────────────────────
155q42:CausalNecessityConfigurationShape a sh:NodeShape ;
156    sh:property [ sh:path q42:causalEdgePredicate ; sh:nodeKind sh:IRI ; sh:minCount 1 ;
157        sh:message "But-for necessity is computed over cause→effect edge quins." ] .
158
159# ── Abductive (inference to best explanation) ───────────────────────────────
160q42:AbductiveConfigurationShape a sh:NodeShape ;
161    sh:property [ sh:path q42:explainsPredicate ; sh:nodeKind sh:IRI ; sh:minCount 1 ;
162        sh:message "Abduction walks backward over hypothesis→observation explanatory edges." ] .
163
164# ── Closed-world / negation-as-failure ──────────────────────────────────────
165q42:ClosedWorldConfigurationShape a sh:NodeShape ;
166    sh:property [ sh:path q42:closedWorld ; sh:datatype xsd:boolean ;
167        sh:message "NAF: a proposition holds by default exactly when it is absent (unprovable)." ] .
168
169# ── Fuzzy / many-valued (t-norm) ────────────────────────────────────────────
170q42:FuzzyConfigurationShape a sh:NodeShape ;
171    sh:property [ sh:path q42:truthDegree ; sh:datatype xsd:decimal ;
172        sh:minInclusive 0.0 ; sh:maxInclusive 1.0 ;
173        sh:message "A fuzzy truth degree ∈ [0,1]; conjunction via the Gödel t-norm (min)." ] .
174
175# ── CTL (branching-time) ────────────────────────────────────────────────────
176q42:CtlConfigurationShape a sh:NodeShape ;
177    sh:property [ sh:path q42:ctlOperator ; sh:in ( "EF" "AG" ) ;
178        sh:message "Supported CTL operators: EF (exists-finally), AG (always-globally)." ] .
179
180# ── General modal (Kripke □/◇) ──────────────────────────────────────────────
181q42:ModalConfigurationShape a sh:NodeShape ;
182    sh:property [ sh:path q42:modalOperator ; sh:in ( "box" "diamond" ) ;
183        sh:message "Modal operator: box (□ necessary, all accessible worlds) | diamond (◇ possible, some)." ] ;
184    sh:property [ sh:path q42:accessibilityPredicate ; sh:nodeKind sh:IRI ; sh:minCount 1 ;
185        sh:message "□/◇ quantify over a Kripke accessibility relation (modal:accesses)." ] .
186
187# ── RCC-8 spatial topology (full polygon, zero-heap) ────────────────────────
188q42:Rcc8ConfigurationShape a sh:NodeShape ;
189    sh:property [ sh:path q42:rcc8Relation ; sh:datatype xsd:unsignedByte ;
190        sh:minInclusive 0 ; sh:maxInclusive 7 ;
191        sh:message "RCC-8 relation ∈ {DC 0, EC 1, PO 2, TPP 3, TPPi 4, NTPP 5, NTPPi 6, EQ 7}." ] ;
192    sh:property [ sh:path q42:maxBoundaryPoints ; sh:datatype xsd:integer ;
193        sh:minInclusive 3 ; sh:maxInclusive 64 ;
194        sh:message "A region is 3–MAX_BOUNDARY_POINTS (64) boundary-point quins (spatial:boundary; metadata = vertex sequence)." ] .
195
196# ════════════════════════════════════════════════════════════════════════════
197# SDL⁺ deontic stack (DEONTIC_LOGIC_PLAN Phases 1–6) — full coverage
198# ════════════════════════════════════════════════════════════════════════════
199
200# ── Deontic lifecycle (Pending→Active→{Violated,Discharged,Defeated,Expired}) ─
201q42:DeonticLifecycleConfigurationShape a sh:NodeShape ;
202    sh:property [ sh:path q42:lifecycleStatus ; sh:datatype xsd:unsignedByte ;
203        sh:minInclusive 0 ; sh:maxInclusive 6 ;
204        sh:message "DeonticStatus ∈ {Active 0, Defeated 1, Expired 2, Malformed 3, Pending 4, Violated 5, Discharged 6}." ] ;
205    sh:property [ sh:path q42:effectiveFrom ; sh:datatype xsd:integer ; sh:minInclusive 0 ;
206        sh:message "effective_from is a unix32 lower bound; now < it ⇒ Pending. Facts (q42:fulfilled/breached/performed) drive Discharged/Violated." ] .
207
208# ── SDL⁺ extension opcodes (Optionality, Gratuitousness, Conditional, Undercut) ─
209q42:DeonticExtConfigurationShape a sh:NodeShape ;
210    sh:property [ sh:path q42:deonticExtOpcode ; sh:datatype xsd:unsignedByte ;
211        sh:minInclusive 19 ; sh:maxInclusive 23 ;
212        sh:message "SDL⁺ opcode ∈ {OPTIONAL 0x13 (U=¬O∧¬F), GRATUITOUS 0x14 (G=¬O), CONDITIONAL 0x15 (O(q|p)), STIT 0x16, UNDERCUT 0x17}." ] ;
213    sh:property [ sh:path q42:defeatKind ; sh:in ( "None" "Rebutting" "Undercutting" ) ;
214        sh:message "A defeated norm records HOW: Rebutting (contrary O/P/F) vs Undercutting (OP_UNDERCUT, link-invalidation)." ] .
215
216# ── Hohfeldian jural square (8 positions, correlatives) ──────────────────────
217q42:JuralConfigurationShape a sh:NodeShape ;
218    sh:property [ sh:path q42:juralPosition ; sh:datatype xsd:unsignedByte ;
219        sh:minInclusive 48 ; sh:maxInclusive 55 ;
220        sh:message "Jural position opcode ∈ 0x30–0x37 {Claim, Duty, Privilege, No-Right, Power, Liability, Immunity, Disability}; correlatives are involutive." ] ;
221    sh:property [ sh:path q42:juralCounterparty ; sh:nodeKind sh:IRI ; sh:minCount 1 ;
222        sh:message "A jural relation binds a holder (subject) to a counterparty (object) who bears the correlative." ] .
223
224# ── STIT agency (α sees to it that φ) ────────────────────────────────────────
225q42:StitConfigurationShape a sh:NodeShape ;
226    sh:property [ sh:path q42:stitAgent ; sh:nodeKind sh:IRI ; sh:minCount 1 ;
227        sh:message "O[α stit φ] names the causal agent α (the duty-bearer, not a bystander)." ] ;
228    sh:property [ sh:path q42:broughtAbout ; sh:nodeKind sh:IRI ;
229        sh:message "The causal fact (α, q42:broughtAbout, φ) discharges an obligation / violates a prohibition; its absence under an in-force obligation is an omission." ] .
230
231# ── Mens rea (epistemic × deontic) ──────────────────────────────────────────
232q42:MensReaConfigurationShape a sh:NodeShape ;
233    sh:property [ sh:path q42:dutyToKnow ; sh:datatype xsd:boolean ;
234        sh:message "When a duty-to-know is in force, ignorance is no excuse (InexcusableIgnorance); else an unknowing violation is Ignorant, a knowing one Knowing." ] .
235
236# ── Interaction governance (verdict → runtime policy mode) ───────────────────
237q42:InteractionGovernanceConfigurationShape a sh:NodeShape ;
238    sh:property [ sh:path q42:policyMode ;
239        sh:in ( "PreventiveBlock" "PermissiveAudit" "Prioritize" "Interactive" "Allow" ) ;
240        sh:message "A verdict maps to exactly one PolicyMode; ambiguity ⇒ Interactive, non-derogable violation ⇒ PreventiveBlock (DenyRollback)." ] ;
241    sh:property [ sh:path q42:nonDerogable ; sh:datatype xsd:boolean ;
242        sh:message "A non-derogable (Hohfeldian Immunity / ICCPR Art 4(2)) violation forces PreventiveBlock." ] .
243
244# ── Meta-deontic (provenance, court-admissible record, endorsement) ──────────
245q42:MetaDeonticConfigurationShape a sh:NodeShape ;
246    sh:property [ sh:path q42:provenanceInstrument ; sh:nodeKind sh:IRI ; sh:minCount 1 ;
247        sh:message "A BreachRecord is anchored (context) to the instrument the breached norm derived from (prov:wasDerivedFrom)." ] ;
248    sh:property [ sh:path q42:endorser ; sh:nodeKind sh:IRI ;
249        sh:message "An endorsement is an Ed25519-signed Credential by a (human) endorser — Curation Directive; the engine holds no keys." ] .
250
251# ════════════════════════════════════════════════════════════════════════════
252# Extended legal-logic stack (legal_logic.md §16–§30) — full coverage
253# ════════════════════════════════════════════════════════════════════════════
254
255# ── §25 Responsibility status (allegation → adjudication) ────────────────────
256q42:ResponsibilityStatusConfigurationShape a sh:NodeShape ;
257    sh:property [ sh:path q42:responsibilityStatus ; sh:in ( "Alleged" "Adjudicated" "Dismissed" ) ;
258        sh:message "A claim of conduct is Alleged until an authority adjudicates; only Adjudicated is an enforceable fact." ] .
259
260# ── §30 Systemic meta-guard (the person protected from the system) ───────────
261q42:SystemicMetaGuardConfigurationShape a sh:NodeShape ;
262    sh:property [ sh:path q42:metaGuardFlag ;
263        sh:in ( "RuleOfLawAsymmetry" "EnforcerOverreach" "AccountabilityVacuum" ) ;
264        sh:message "The enforcer is bound by the baselines it enforces: no power-without-remedy, no block-without-appeal, no harm-without-accountable-person." ] .
265
266# ── §18 Juridical capacity (duress → voidable, not void) ─────────────────────
267q42:JuridicalCapacityConfigurationShape a sh:NodeShape ;
268    sh:property [ sh:path q42:capacityStatus ; sh:in ( "Intact" "Impaired" "UnderDuress" ) ;
269        sh:message "Stipulation binding only when Intact; UnderDuress → VOIDABLE at the victim's election (not auto-void)." ] .
270
271# ── §21 Delegation chain (authority + revocation cascade) ────────────────────
272q42:DelegationChainConfigurationShape a sh:NodeShape ;
273    sh:property [ sh:path q42:delegatesTo ; sh:nodeKind sh:IRI ; sh:minCount 1 ;
274        sh:message "Authority flows along (delegator, q42:delegatesTo, delegatee) edges; revoking an upstream node defeats all descendants." ] .
275
276# ── §22 Contract formation (Offer → Assent → Binding) ────────────────────────
277q42:ContractFormationConfigurationShape a sh:NodeShape ;
278    sh:property [ sh:path q42:formationStage ; sh:in ( "None" "Offer" "Binding" ) ;
279        sh:message "Binding needs offer + assent AND both parties' capacity Intact (composes §18)." ] .
280
281# ── §23 Value-flow / Permissive Commons (capped ROI, threshold discharge) ────
282q42:ValueFlowConfigurationShape a sh:NodeShape ;
283    sh:property [ sh:path q42:roiCapPercent ; sh:datatype xsd:integer ; sh:minInclusive 0 ;
284        sh:message "Commons cost = production cost + a legally CAPPED ROI margin (extraction guard); pool ≥ cost → Discharged, freed globally." ] .
285
286# ── §24 Capability gap / RPL (computable set-difference) ─────────────────────
287q42:CapabilityGapConfigurationShape a sh:NodeShape ;
288    sh:property [ sh:path q42:requiredCapability ; sh:nodeKind sh:IRI ; sh:minCount 1 ;
289        sh:message "Gap = Req \\ Holds; experiential skos:closeMatch counts as held (RPL)." ] .
290
291# ── §27 Resilient relational identity (k-of-n fabric recovery) ───────────────
292q42:ResilientIdentityConfigurationShape a sh:NodeShape ;
293    sh:property [ sh:path q42:recoveryQuorum ; sh:datatype xsd:integer ; sh:minInclusive 1 ;
294        sh:message "An identifier is not an identity; identity survives key loss iff a quorum (≥1) of the anchor fabric remains." ] .
295
296# ── §17 ZK-gated eligibility (privacy-preserving) ────────────────────────────
297q42:ZkGatedConfigurationShape a sh:NodeShape ;
298    sh:property [ sh:path q42:zkVerified ; sh:datatype xsd:boolean ;
299        sh:message "A ZK-gated obligation applies iff the proof verifies (zk_proofs Groth16); the private witness stays hidden, else claimedIdentityUnverifiable." ] .
300
301# ── §26 Proportionality (CAS-derived) ────────────────────────────────────────
302q42:ProportionalityConfigurationShape a sh:NodeShape ;
303    sh:property [ sh:path q42:advantageThreshold ; sh:datatype xsd:decimal ;
304        sh:message "Proportionate iff ∂Harm/∂x < Advantage (symbolic_algebra differentiate/eval)." ] .
305
306# ── §19 Sense translation (Curation Directive gating) ────────────────────────
307q42:SenseTranslationConfigurationShape a sh:NodeShape ;
308    sh:property [ sh:path q42:matchStatus ; sh:in ( "CloseMatch" "ExactMatch" "RequiresHumanReview" ) ;
309        sh:message "Machine proposes skos:closeMatch; only a human attests skos:exactMatch; untranslatable → human review (never flattened)." ] .
310
311# ── §28 Distributed consensus (suspended tx, partition tolerance) ────────────
312q42:ConsensusConfigurationShape a sh:NodeShape ;
313    sh:property [ sh:path q42:txStatus ; sh:in ( "Suspended" "Committed" ) ;
314        sh:message "A multi-party obligation commits only on full consensus; local validity ≠ global until synced; pre-partition duties survive." ] .
315
316# ── §20 Manifold logic (continuous → discrete) ───────────────────────────────
317q42:ManifoldLogicConfigurationShape a sh:NodeShape ;
318    sh:property [ sh:path q42:signalThreshold ; sh:datatype xsd:decimal ;
319        sh:message "∫Ψ over the wave samples > threshold → instantiate a discrete factual quin (bridge to epistemic.rs). GPU 10D renderer is separate (STELLAR)." ] .
320
321# ── §29 Carrier binding (content-addressed, tamper-evident) ──────────────────
322q42:CarrierBindingConfigurationShape a sh:NodeShape ;
323    sh:property [ sh:path q42:mediaTag ; sh:datatype xsd:unsignedLong ;
324        sh:message "media_tag = BLAKE3(blob); the carried graph is bound to THAT media — any edit breaks the binding. Container codecs (PDF/A-3, PNG) are separate (task #9)." ] .
325"#
326}
327
328#[cfg(test)]
329mod tests {
330    use super::*;
331
332    #[test]
333    fn every_modality_has_a_configuration_shape() {
334        let ttl = get_logic_modalities_shacl_ttl();
335        for shape in LOGIC_MODALITY_SHAPES {
336            assert!(
337                ttl.contains(&format!("q42:{shape}")),
338                "missing SHACL configuration shape for {shape}"
339            );
340        }
341        // The new modalities specifically must be present.
342        for s in [
343            "MetricTemporal",
344            "ContraryToDuty",
345            "CausalNecessity",
346            "Abductive",
347            "ClosedWorld",
348            "Fuzzy",
349            "Ctl",
350            "Modal",
351        ] {
352            assert!(ttl.contains(s), "new modality {s} missing its SHACL shape");
353        }
354        // Namespace migrated (no residual qualia.* namespace).
355        assert!(ttl.contains("https://webizen.org/q42#"));
356        assert!(!ttl.contains("qualia.network/q42"));
357    }
358
359    #[test]
360    fn sdl_plus_deontic_stack_has_full_shacl_coverage() {
361        let ttl = get_logic_modalities_shacl_ttl();
362        // Every SDL⁺ phase carries a configuration shape.
363        for s in [
364            "DeonticLifecycleConfigurationShape",
365            "DeonticExtConfigurationShape",
366            "JuralConfigurationShape",
367            "StitConfigurationShape",
368            "MensReaConfigurationShape",
369            "InteractionGovernanceConfigurationShape",
370            "MetaDeonticConfigurationShape",
371        ] {
372            assert!(ttl.contains(s), "SDL⁺ shape {s} missing");
373        }
374        // The key opcode-range constraints are stated (engine ↔ SHACL parity).
375        assert!(ttl.contains("OPTIONAL 0x13"), "SDL⁺ ext opcodes documented");
376        assert!(ttl.contains("0x30–0x37"), "jural opcode block documented");
377        assert!(
378            ttl.contains("Pending 4, Violated 5, Discharged 6"),
379            "lifecycle states documented"
380        );
381    }
382
383    #[test]
384    fn epistemic_shape_covers_the_full_engine() {
385        let ttl = get_logic_modalities_shacl_ttl();
386        // Not just `certainty` anymore — opcodes, bands, nesting, world/agent scoping.
387        assert!(
388            ttl.contains("q42:epistemicOpcode"),
389            "epistemic opcode range"
390        );
391        assert!(
392            ttl.contains("OP_COMMON_KNOWLEDGE 0x22"),
393            "all three epistemic operators"
394        );
395        assert!(
396            ttl.contains("q42:nestingDepth"),
397            "nested-attitude depth (RDF-Star)"
398        );
399        assert!(
400            ttl.contains("q42:worldContext") && ttl.contains("q42:agentDid"),
401            "possible-world + agent scoping"
402        );
403        // The named doxastic bands are documented.
404        for band in ["affirms 230", "considers 128", "doubts 20"] {
405            assert!(ttl.contains(band), "certainty band '{band}' documented");
406        }
407    }
408
409    #[test]
410    fn extended_legal_logic_16_30_has_full_shacl_coverage() {
411        let ttl = get_logic_modalities_shacl_ttl();
412        for s in [
413            "ResponsibilityStatusConfigurationShape",
414            "SystemicMetaGuardConfigurationShape",
415            "JuridicalCapacityConfigurationShape",
416            "DelegationChainConfigurationShape",
417            "ContractFormationConfigurationShape",
418            "ValueFlowConfigurationShape",
419            "CapabilityGapConfigurationShape",
420            "ResilientIdentityConfigurationShape",
421            "ZkGatedConfigurationShape",
422            "ProportionalityConfigurationShape",
423            "SenseTranslationConfigurationShape",
424            "ConsensusConfigurationShape",
425            "ManifoldLogicConfigurationShape",
426            "CarrierBindingConfigurationShape",
427        ] {
428            assert!(ttl.contains(s), "§16–§30 shape {s} missing");
429        }
430        // A few load-bearing semantics are stated (engine ↔ SHACL parity).
431        assert!(
432            ttl.contains("VOIDABLE at the victim's election"),
433            "§18 duress reading documented"
434        );
435        assert!(
436            ttl.contains("only Adjudicated is an enforceable fact"),
437            "§25 due-process gate"
438        );
439        assert!(
440            ttl.contains("∂Harm/∂x < Advantage"),
441            "§26 proportionality test"
442        );
443    }
444}