eyeprolog 1.3.99 → 1.4.0

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.
Files changed (51) hide show
  1. package/README.md +4 -1
  2. package/examples/cross-organization-data-sharing.pl +121 -0
  3. package/examples/data/README.md +15 -0
  4. package/examples/data/cross-organization-data-sharing-input.nq +40 -0
  5. package/examples/data/cross-organization-data-sharing-output.nq +5 -0
  6. package/examples/data/cross-organization-data-sharing-output.pl +3 -0
  7. package/examples/data/cross-organization-data-sharing-rules.pl +77 -0
  8. package/examples/data/explainable-ev-depot-configuration-input.nq +22 -0
  9. package/examples/data/explainable-ev-depot-configuration-output.nq +4 -0
  10. package/examples/data/explainable-ev-depot-configuration-output.pl +2 -0
  11. package/examples/data/explainable-ev-depot-configuration-rules.pl +52 -0
  12. package/examples/data/operational-incident-response-input.nq +17 -0
  13. package/examples/data/operational-incident-response-output.nq +9 -0
  14. package/examples/data/operational-incident-response-output.pl +7 -0
  15. package/examples/data/operational-incident-response-rules.pl +68 -0
  16. package/examples/data/sbom-vulnerability-response-input.nq +19 -0
  17. package/examples/data/sbom-vulnerability-response-output.nq +5 -0
  18. package/examples/data/sbom-vulnerability-response-output.pl +3 -0
  19. package/examples/data/sbom-vulnerability-response-rules.pl +85 -0
  20. package/examples/data/scientific-evidence-graph-input.nq +32 -0
  21. package/examples/data/scientific-evidence-graph-output.nq +4 -0
  22. package/examples/data/scientific-evidence-graph-output.pl +2 -0
  23. package/examples/data/scientific-evidence-graph-rules.pl +54 -0
  24. package/examples/deck/README.md +5 -0
  25. package/examples/deck/cross-organization-data-sharing.md +35 -0
  26. package/examples/deck/explainable-ev-depot-configuration.md +38 -0
  27. package/examples/deck/operational-incident-response.md +35 -0
  28. package/examples/deck/sbom-vulnerability-response.md +42 -0
  29. package/examples/deck/scientific-evidence-graph.md +40 -0
  30. package/examples/explainable-ev-depot-configuration.pl +78 -0
  31. package/examples/operational-incident-response.pl +89 -0
  32. package/examples/output/cross-organization-data-sharing.pl +8 -0
  33. package/examples/output/explainable-ev-depot-configuration.pl +8 -0
  34. package/examples/output/operational-incident-response.pl +8 -0
  35. package/examples/output/sbom-vulnerability-response.pl +4 -0
  36. package/examples/output/scientific-evidence-graph.pl +9 -0
  37. package/examples/sbom-vulnerability-response.pl +108 -0
  38. package/examples/scientific-evidence-graph.pl +90 -0
  39. package/package.json +1 -1
  40. package/playground.html +8 -3
  41. package/src/lib/freeze.pl +23 -14
  42. package/src/write.js +13 -0
  43. package/test/conformance/ISO-COMPLIANCE.md +2 -2
  44. package/test/conformance/WG17-SYNTAX-STATUS.md +4 -1
  45. package/test/conformance/wg17-syntax-cases.json +7 -7
  46. package/test/run-playground.mjs +12 -0
  47. package/test/run-regression.mjs +45 -0
  48. package/test/run-wg17.mjs +43 -0
  49. package/the-art-of-eyeprolog.md +11 -4
  50. package/tools/report-wg17-syntax-coverage.mjs +4 -1
  51. package/why-eyeprolog.md +2 -0
@@ -0,0 +1,85 @@
1
+ % Flagship example: software supply-chain deployment risk.
2
+ % RDF carries the SBOM, vulnerability feed, and policy. ISO Prolog performs
3
+ % transitive dependency analysis, waiver handling, and the deployment decision.
4
+
5
+ :- use_module(library(lists)).
6
+
7
+ %% goal: deployment_decision(X0, X1)
8
+ %% goal: exposure_path(X0, X1, X2)
9
+ %% goal: required_action(X0, X1)
10
+ %% goal: waiver_effect(X0, X1, X2)
11
+
12
+ v(root_component, iri('https://example.org/vocab/rootComponent')).
13
+ v(depends_on, iri('https://example.org/vocab/dependsOn')).
14
+ v(affected_by, iri('https://example.org/vocab/affectedBy')).
15
+ v(severity_score, iri('https://example.org/vocab/severityScore')).
16
+ v(fixed_component, iri('https://example.org/vocab/fixedComponent')).
17
+ v(critical_service, iri('https://example.org/vocab/criticalService')).
18
+ v(current_date, iri('https://example.org/vocab/currentDate')).
19
+ v(waives_for_service, iri('https://example.org/vocab/waivesForService')).
20
+ v(waives_vulnerability, iri('https://example.org/vocab/waivesVulnerability')).
21
+ v(expires_on, iri('https://example.org/vocab/expiresOn')).
22
+
23
+ g(sbom, iri('https://example.org/supply-chain/graph/sbom')).
24
+ g(vulnerabilities, iri('https://example.org/supply-chain/graph/vulnerabilities')).
25
+ g(policy, iri('https://example.org/supply-chain/graph/policy')).
26
+
27
+ resource(checkout_prod, iri('https://example.org/supply-chain/service/checkout-prod')).
28
+ resource(shop_app, iri('https://example.org/supply-chain/component/shop-app')).
29
+ resource(payments_sdk, iri('https://example.org/supply-chain/component/payments-sdk')).
30
+ resource(crypto_wrapper, iri('https://example.org/supply-chain/component/crypto-wrapper')).
31
+ resource(openssl_3_0_12, iri('https://example.org/supply-chain/component/openssl-3.0.12')).
32
+ resource(log_agent, iri('https://example.org/supply-chain/component/log-agent')).
33
+ resource(log_core_2_1, iri('https://example.org/supply-chain/component/log-core-2.1')).
34
+ resource(openssl_3_0_14, iri('https://example.org/supply-chain/component/openssl-3.0.14')).
35
+ resource(log_core_2_2, iri('https://example.org/supply-chain/component/log-core-2.2')).
36
+ resource(cve_2026_7777, iri('https://example.org/supply-chain/cve/CVE-2026-7777')).
37
+ resource(cve_2026_2222, iri('https://example.org/supply-chain/cve/CVE-2026-2222')).
38
+
39
+ yes(iri('https://example.org/supply-chain/value/yes')).
40
+
41
+ integer_literal(literal(Text, datatype('http://www.w3.org/2001/XMLSchema#integer')), N) :- atom_chars(Text, Cs), number_chars(N, Cs).
42
+
43
+ root_component(Service, Root) :- resource(Service,S), v(root_component,P), g(sbom,G), rdf(S,P,R,G), resource(Root,R).
44
+ depends(A,B) :- resource(A,RA), resource(B,RB), v(depends_on,P), g(sbom,G), rdf(RA,P,RB,G).
45
+ vulnerability(Component,Vuln) :- resource(Component,C), resource(Vuln,V), v(affected_by,P), g(vulnerabilities,G), rdf(C,P,V,G).
46
+ severity(Vuln,Score) :- resource(Vuln,V), v(severity_score,P), g(vulnerabilities,G), rdf(V,P,L,G), integer_literal(L,Score).
47
+ fix(Vuln,Fixed) :- resource(Vuln,V), resource(Fixed,F), v(fixed_component,P), g(vulnerabilities,G), rdf(V,P,F,G).
48
+
49
+ component_path(A,B,Path) :- component_path(A,B,[A],Path).
50
+ component_path(A,B,Visited,[A,B]) :- depends(A,B), \+ member(B,Visited).
51
+ component_path(A,B,Visited,[A|Rest]) :- depends(A,C), \+ member(C,Visited), component_path(C,B,[C|Visited],Rest).
52
+
53
+ dependency_path(Service,Component,Path) :- root_component(Service,Root), component_path(Root,Component,Path).
54
+
55
+ current_date(Service,Date) :- resource(Service,S), v(current_date,P), g(policy,G), rdf(S,P,L,G), integer_literal(L,Date).
56
+ critical(Service) :- resource(Service,S), v(critical_service,P), g(policy,G), yes(Y), rdf(S,P,Y,G).
57
+ active_waiver(Service,Vuln) :-
58
+ resource(Service,S), resource(Vuln,V), g(policy,G),
59
+ v(waives_for_service,PS), v(waives_vulnerability,PV), v(expires_on,PE),
60
+ rdf(W,PS,S,G), rdf(W,PV,V,G), rdf(W,PE,L,G), integer_literal(L,Expiry), current_date(Service,Today), Expiry >= Today.
61
+
62
+ exposed(Service,Vuln,Path,Score) :-
63
+ dependency_path(Service,Component,Path), vulnerability(Component,Vuln), severity(Vuln,Score), \+ active_waiver(Service,Vuln).
64
+
65
+ blocking_exposure(Service,Vuln,Path,Score) :- exposed(Service,Vuln,Path,Score), Score >= 70.
66
+
67
+ deployment_decision(Service, block) :- critical(Service), blocking_exposure(Service,_V,_P,_S).
68
+ exposure_path(Service,Vuln,Path) :- blocking_exposure(Service,Vuln,Path,_Score).
69
+ required_action(Service, upgrade(Component,Fixed)) :-
70
+ blocking_exposure(Service,Vuln,Path,_), last(Path,Component), fix(Vuln,Fixed).
71
+ waiver_effect(Service,Vuln,accepted_until(Expiry)) :-
72
+ active_waiver(Service,Vuln), resource(Service,S), resource(Vuln,V), g(policy,G),
73
+ v(waives_for_service,PS), v(waives_vulnerability,PV), v(expires_on,PE),
74
+ rdf(W,PS,S,G), rdf(W,PV,V,G), rdf(W,PE,L,G), integer_literal(L,Expiry).
75
+
76
+ result_rdf(S, iri('https://example.org/vocab/deploymentDecision'), iri('https://example.org/supply-chain/decision/block'), iri('https://example.org/supply-chain/graph/derived')) :-
77
+ deployment_decision(checkout_prod,block), resource(checkout_prod,S).
78
+ result_rdf(S, iri('https://example.org/vocab/exposedTo'), V, iri('https://example.org/supply-chain/graph/derived')) :-
79
+ exposure_path(checkout_prod,Vuln,_), resource(checkout_prod,S), resource(Vuln,V).
80
+ result_rdf(C, iri('https://example.org/vocab/upgradeTo'), F, iri('https://example.org/supply-chain/graph/derived')) :-
81
+ required_action(checkout_prod,upgrade(Component,Fixed)), resource(Component,C), resource(Fixed,F).
82
+
83
+ write_results :- result_rdf(S,P,O,G), write_term(rdf(S,P,O,G), [quoted(true)]), write('.'), nl, fail.
84
+ write_results.
85
+ :- set_prolog_flag(unknown, fail).
@@ -0,0 +1,32 @@
1
+ VERSION "1.2"
2
+
3
+ <https://example.org/evidence/study/study-a> <https://example.org/vocab/statement> <<( <https://example.org/evidence/intervention/therapy-x> <https://example.org/vocab/reduces> <https://example.org/evidence/outcome/inflammation-marker> )>> <https://example.org/evidence/graph/evidence> .
4
+ <https://example.org/evidence/study/study-a> <https://example.org/vocab/direction> <https://example.org/evidence/direction/supports> <https://example.org/evidence/graph/evidence> .
5
+ <https://example.org/evidence/study/study-a> <https://example.org/vocab/design> <https://example.org/evidence/design/randomized-trial> <https://example.org/evidence/graph/evidence> .
6
+ <https://example.org/evidence/study/study-a> <https://example.org/vocab/institution> <https://example.org/evidence/institution/lab-a> <https://example.org/evidence/graph/evidence> .
7
+ <https://example.org/evidence/study/study-a> <https://example.org/vocab/sampleSize> "240"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/evidence/graph/evidence> .
8
+ <https://example.org/evidence/study/study-a> <https://example.org/vocab/peerReviewed> <https://example.org/evidence/value/yes> <https://example.org/evidence/graph/evidence> .
9
+ <https://example.org/evidence/study/study-b> <https://example.org/vocab/statement> <<( <https://example.org/evidence/intervention/therapy-x> <https://example.org/vocab/reduces> <https://example.org/evidence/outcome/inflammation-marker> )>> <https://example.org/evidence/graph/evidence> .
10
+ <https://example.org/evidence/study/study-b> <https://example.org/vocab/direction> <https://example.org/evidence/direction/supports> <https://example.org/evidence/graph/evidence> .
11
+ <https://example.org/evidence/study/study-b> <https://example.org/vocab/design> <https://example.org/evidence/design/randomized-trial> <https://example.org/evidence/graph/evidence> .
12
+ <https://example.org/evidence/study/study-b> <https://example.org/vocab/institution> <https://example.org/evidence/institution/lab-b> <https://example.org/evidence/graph/evidence> .
13
+ <https://example.org/evidence/study/study-b> <https://example.org/vocab/sampleSize> "310"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/evidence/graph/evidence> .
14
+ <https://example.org/evidence/study/study-b> <https://example.org/vocab/peerReviewed> <https://example.org/evidence/value/yes> <https://example.org/evidence/graph/evidence> .
15
+ <https://example.org/evidence/study/study-c> <https://example.org/vocab/statement> <<( <https://example.org/evidence/intervention/therapy-x> <https://example.org/vocab/reduces> <https://example.org/evidence/outcome/inflammation-marker> )>> <https://example.org/evidence/graph/evidence> .
16
+ <https://example.org/evidence/study/study-c> <https://example.org/vocab/direction> <https://example.org/evidence/direction/contradicts> <https://example.org/evidence/graph/evidence> .
17
+ <https://example.org/evidence/study/study-c> <https://example.org/vocab/design> <https://example.org/evidence/design/observational> <https://example.org/evidence/graph/evidence> .
18
+ <https://example.org/evidence/study/study-c> <https://example.org/vocab/institution> <https://example.org/evidence/institution/lab-c> <https://example.org/evidence/graph/evidence> .
19
+ <https://example.org/evidence/study/study-c> <https://example.org/vocab/sampleSize> "40"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/evidence/graph/evidence> .
20
+ <https://example.org/evidence/study/study-c> <https://example.org/vocab/peerReviewed> <https://example.org/evidence/value/yes> <https://example.org/evidence/graph/evidence> .
21
+ <https://example.org/evidence/study/study-d> <https://example.org/vocab/statement> <<( <https://example.org/evidence/intervention/therapy-x> <https://example.org/vocab/improves> <https://example.org/evidence/outcome/survival> )>> <https://example.org/evidence/graph/evidence> .
22
+ <https://example.org/evidence/study/study-d> <https://example.org/vocab/direction> <https://example.org/evidence/direction/supports> <https://example.org/evidence/graph/evidence> .
23
+ <https://example.org/evidence/study/study-d> <https://example.org/vocab/design> <https://example.org/evidence/design/randomized-trial> <https://example.org/evidence/graph/evidence> .
24
+ <https://example.org/evidence/study/study-d> <https://example.org/vocab/institution> <https://example.org/evidence/institution/lab-a> <https://example.org/evidence/graph/evidence> .
25
+ <https://example.org/evidence/study/study-d> <https://example.org/vocab/sampleSize> "180"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/evidence/graph/evidence> .
26
+ <https://example.org/evidence/study/study-d> <https://example.org/vocab/peerReviewed> <https://example.org/evidence/value/yes> <https://example.org/evidence/graph/evidence> .
27
+ <https://example.org/evidence/study/study-e> <https://example.org/vocab/statement> <<( <https://example.org/evidence/intervention/therapy-x> <https://example.org/vocab/improves> <https://example.org/evidence/outcome/survival> )>> <https://example.org/evidence/graph/evidence> .
28
+ <https://example.org/evidence/study/study-e> <https://example.org/vocab/direction> <https://example.org/evidence/direction/contradicts> <https://example.org/evidence/graph/evidence> .
29
+ <https://example.org/evidence/study/study-e> <https://example.org/vocab/design> <https://example.org/evidence/design/randomized-trial> <https://example.org/evidence/graph/evidence> .
30
+ <https://example.org/evidence/study/study-e> <https://example.org/vocab/institution> <https://example.org/evidence/institution/lab-b> <https://example.org/evidence/graph/evidence> .
31
+ <https://example.org/evidence/study/study-e> <https://example.org/vocab/sampleSize> "210"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/evidence/graph/evidence> .
32
+ <https://example.org/evidence/study/study-e> <https://example.org/vocab/peerReviewed> <https://example.org/evidence/value/yes> <https://example.org/evidence/graph/evidence> .
@@ -0,0 +1,4 @@
1
+ VERSION "1.2"
2
+
3
+ <https://example.org/evidence/claim/marker-reduction> <https://example.org/vocab/evidenceState> <https://example.org/evidence/state/supported> <https://example.org/evidence/graph/derived> .
4
+ <https://example.org/evidence/claim/survival-benefit> <https://example.org/vocab/evidenceState> <https://example.org/evidence/state/contested> <https://example.org/evidence/graph/derived> .
@@ -0,0 +1,2 @@
1
+ rdf(iri('https://example.org/evidence/claim/marker-reduction'),iri('https://example.org/vocab/evidenceState'),iri('https://example.org/evidence/state/supported'),iri('https://example.org/evidence/graph/derived')).
2
+ rdf(iri('https://example.org/evidence/claim/survival-benefit'),iri('https://example.org/vocab/evidenceState'),iri('https://example.org/evidence/state/contested'),iri('https://example.org/evidence/graph/derived')).
@@ -0,0 +1,54 @@
1
+ % Flagship example: a scientific evidence graph with RDF 1.2 triple terms.
2
+ % Studies make statements about candidate claims without turning every claim into
3
+ % accepted truth. Prolog combines study design, sample size, independence, and
4
+ % conflicting evidence into explicit evidence states.
5
+
6
+ %% goal: evidence_state(X0, X1)
7
+ %% goal: supporting_study(X0, X1)
8
+ %% goal: counterevidence(X0, X1, X2)
9
+ %% goal: evidence_reason(X0, X1)
10
+
11
+ v(statement,iri('https://example.org/vocab/statement')).
12
+ v(direction,iri('https://example.org/vocab/direction')).
13
+ v(design,iri('https://example.org/vocab/design')).
14
+ v(institution,iri('https://example.org/vocab/institution')).
15
+ v(sample_size,iri('https://example.org/vocab/sampleSize')).
16
+ v(peer_reviewed,iri('https://example.org/vocab/peerReviewed')).
17
+ g(evidence,iri('https://example.org/evidence/graph/evidence')).
18
+
19
+ yes(iri('https://example.org/evidence/value/yes')).
20
+ supports(iri('https://example.org/evidence/direction/supports')).
21
+ contradicts(iri('https://example.org/evidence/direction/contradicts')).
22
+ randomized(iri('https://example.org/evidence/design/randomized-trial')).
23
+
24
+ claim(marker_reduction,iri('https://example.org/evidence/claim/marker-reduction'),triple(iri('https://example.org/evidence/intervention/therapy-x'),iri('https://example.org/vocab/reduces'),iri('https://example.org/evidence/outcome/inflammation-marker'))).
25
+ claim(survival_benefit,iri('https://example.org/evidence/claim/survival-benefit'),triple(iri('https://example.org/evidence/intervention/therapy-x'),iri('https://example.org/vocab/improves'),iri('https://example.org/evidence/outcome/survival'))).
26
+
27
+ study(study_a,iri('https://example.org/evidence/study/study-a')). study(study_b,iri('https://example.org/evidence/study/study-b')). study(study_c,iri('https://example.org/evidence/study/study-c')).
28
+ study(study_d,iri('https://example.org/evidence/study/study-d')). study(study_e,iri('https://example.org/evidence/study/study-e')).
29
+ integer_literal(literal(Text,datatype('http://www.w3.org/2001/XMLSchema#integer')),N):-atom_chars(Text,Cs),number_chars(N,Cs).
30
+
31
+ study_statement(Study,Claim,Direction,Institution,Design,N):-
32
+ study(Study,S),claim(Claim,_ClaimResource,C),g(evidence,G),v(statement,PS),v(direction,PD),v(institution,PI),v(design,PDe),v(sample_size,PN),v(peer_reviewed,PP),
33
+ rdf(S,PS,C,G),rdf(S,PD,Direction,G),rdf(S,PI,Institution,G),rdf(S,PDe,Design,G),rdf(S,PN,L,G),integer_literal(L,N),yes(Y),rdf(S,PP,Y,G).
34
+
35
+ high_quality(Study,Claim,Direction,Institution):-study_statement(Study,Claim,Direction,Institution,Design,N),randomized(R),Design=R,N >= 100.
36
+ independent_support_pair(Claim,S1,S2):-supports(S),high_quality(S1,Claim,S,I1),high_quality(S2,Claim,S,I2),S1 @< S2,I1 \= I2.
37
+ high_quality_counterevidence(Claim,Study):-contradicts(C),high_quality(Study,Claim,C,_).
38
+
39
+ supporting_study(Claim,Study):-supports(S),high_quality(Study,Claim,S,_).
40
+ counterevidence(Claim,Study,low_quality):-contradicts(C),study_statement(Study,Claim,C,_I,_D,_N),\+ high_quality(Study,Claim,C,_).
41
+ counterevidence(Claim,Study,high_quality):-high_quality_counterevidence(Claim,Study).
42
+
43
+ evidence_state(Claim,supported):-independent_support_pair(Claim,_S1,_S2),\+ high_quality_counterevidence(Claim,_Counter).
44
+ evidence_state(Claim,contested):-supporting_study(Claim,_),high_quality_counterevidence(Claim,_).
45
+
46
+ evidence_reason(marker_reduction,"Two independent randomized studies with sample size >= 100 support the claim; the contradictory observational study is retained as lower-quality counterevidence."):-evidence_state(marker_reduction,supported).
47
+ evidence_reason(survival_benefit,"High-quality randomized evidence exists on both sides, so the claim remains contested instead of being collapsed to a single truth value."):-evidence_state(survival_benefit,contested).
48
+
49
+ result_rdf(ClaimResource,iri('https://example.org/vocab/evidenceState'),State,iri('https://example.org/evidence/graph/derived')):-claim(Claim,ClaimResource,_Statement),evidence_state(Claim,S),state_iri(S,State).
50
+ state_iri(supported,iri('https://example.org/evidence/state/supported')). state_iri(contested,iri('https://example.org/evidence/state/contested')).
51
+
52
+ write_results:-result_rdf(S,P,O,G),write_term(rdf(S,P,O,G),[quoted(true)]),write('.'),nl,fail.
53
+ write_results.
54
+ :- set_prolog_flag(unknown, fail).
@@ -2,5 +2,10 @@
2
2
 
3
3
  Wide-audience companion explanations for selected runnable examples.
4
4
 
5
+ - [Cross-organization data sharing](cross-organization-data-sharing.md) — ODRL/DPV sharing decisions with permit, deny, review, safeguards, and obligations.
6
+ - [Explainable EV-depot configuration](explainable-ev-depot-configuration.md) — reversible configuration rules that select a charger, explain blockers, and derive required changes.
5
7
  - [ODRL policy reasoning](odrl-policy-reasoning.md) — permissions, prohibitions, duties, conflicts, and defaults.
8
+ - [Operational incident response](operational-incident-response.md) — topology-aware root-cause, impact, evidence-chain, and safe-mitigation reasoning.
9
+ - [SBOM vulnerability response](sbom-vulnerability-response.md) — transitive exposure paths, severity policy, waivers, deployment decisions, and upgrade actions.
10
+ - [Scientific evidence graph](scientific-evidence-graph.md) — RDF 1.2 claims, provenance, evidence quality, corroboration, and explicit disagreement.
6
11
  - [Symbiotic Knowledge Graphs](symbiotic-knowledge-graphs.md) — a real-world RDF → Prolog → RDF heatwave-response loop in which AI proposes, explicit rules govern, people review, and accepted knowledge improves later decisions.
@@ -0,0 +1,35 @@
1
+ # Cross-organization data sharing
2
+
3
+ ## Decision
4
+
5
+ **May this dataset be shared with this organization for this purpose, under these safeguards?**
6
+
7
+ Three requests deliberately exercise different outcomes: an EU research request is **permitted**, a marketing distribution is **denied** by an explicit ODRL prohibition, and an otherwise valid out-of-region research request is sent to **review** because a required transfer safeguard is missing.
8
+
9
+ ## Why this is challenging
10
+
11
+ A real sharing decision is not one boolean rule. It combines the requested action and purpose, recipient properties, retention, technical safeguards, legal basis, jurisdiction, explicit prohibitions, and obligations that apply after permission.
12
+
13
+ The example uses RDF as the interoperable data layer, W3C ODRL terms for permissions/prohibitions, DPV terms for purposes/legal basis, and ISO Prolog rules for the decision procedure. The important output is not only `permit/deny/review`, but the exact condition that produced it.
14
+
15
+ ## Files
16
+
17
+ - [`../cross-organization-data-sharing.pl`](../cross-organization-data-sharing.pl)
18
+ - [`../data/cross-organization-data-sharing-input.nq`](../data/cross-organization-data-sharing-input.nq)
19
+ - [`../data/cross-organization-data-sharing-rules.pl`](../data/cross-organization-data-sharing-rules.pl)
20
+ - [`../data/cross-organization-data-sharing-output.nq`](../data/cross-organization-data-sharing-output.nq)
21
+
22
+ ## Reproduce
23
+
24
+ ```sh
25
+ rdf-to-prolog examples/data/cross-organization-data-sharing-input.nq \
26
+ --rules examples/data/cross-organization-data-sharing-rules.pl \
27
+ -o examples/cross-organization-data-sharing.pl
28
+
29
+ eyeprolog examples/cross-organization-data-sharing.pl
30
+
31
+ eyeprolog --goal write_results examples/cross-organization-data-sharing.pl \
32
+ > examples/data/cross-organization-data-sharing-output.pl
33
+ prolog-to-rdf examples/data/cross-organization-data-sharing-output.pl \
34
+ -o examples/data/cross-organization-data-sharing-output.nq
35
+ ```
@@ -0,0 +1,38 @@
1
+ # Explainable EV-depot configuration
2
+
3
+ ## Questions, not just filtering
4
+
5
+ A depot needs a charger compatible with its **60 kW available site power**, **22 kW minimum charging rate**, **CCS2 connector**, and **three-phase supply**.
6
+
7
+ EyeProlog does four useful things with the same rules:
8
+
9
+ 1. finds the compatible option (`fleet22`);
10
+ 2. recommends it;
11
+ 3. explains why each rejected option fails; and
12
+ 4. answers the reverse question: **what would have to change to make this option viable?**
13
+
14
+ Examples include `increase_site_power_to(80)`, `choose_charger_at_least_kw(22)`, and `use_connector(ccs2)`.
15
+
16
+ That reversibility is a practical difference between a relational rule model and a one-way scoring/filtering pipeline. The rules describe the relationships that must hold, so they can support selection, diagnosis, and what-if questions without creating three separate business-rule implementations.
17
+
18
+ ## Files
19
+
20
+ - [`../explainable-ev-depot-configuration.pl`](../explainable-ev-depot-configuration.pl)
21
+ - [`../data/explainable-ev-depot-configuration-input.nq`](../data/explainable-ev-depot-configuration-input.nq)
22
+ - [`../data/explainable-ev-depot-configuration-rules.pl`](../data/explainable-ev-depot-configuration-rules.pl)
23
+ - [`../data/explainable-ev-depot-configuration-output.nq`](../data/explainable-ev-depot-configuration-output.nq)
24
+
25
+ ## Reproduce
26
+
27
+ ```sh
28
+ rdf-to-prolog examples/data/explainable-ev-depot-configuration-input.nq \
29
+ --rules examples/data/explainable-ev-depot-configuration-rules.pl \
30
+ -o examples/explainable-ev-depot-configuration.pl
31
+
32
+ eyeprolog examples/explainable-ev-depot-configuration.pl
33
+
34
+ eyeprolog --goal write_results examples/explainable-ev-depot-configuration.pl \
35
+ > examples/data/explainable-ev-depot-configuration-output.pl
36
+ prolog-to-rdf examples/data/explainable-ev-depot-configuration-output.pl \
37
+ -o examples/data/explainable-ev-depot-configuration-output.nq
38
+ ```
@@ -0,0 +1,35 @@
1
+ # Operational incident response
2
+
3
+ ## Decision
4
+
5
+ **What is the most defensible root cause, what is impacted, and what should operations do next?**
6
+
7
+ The scenario combines a live service topology with incident symptoms and telemetry. EyeProlog correlates a payment API database-timeout symptom with a primary database at 100% disk usage, confirms that the authentication service is healthy, propagates impact through the dependency graph, and recommends failover only because the replica is independently healthy.
8
+
9
+ ## Why this is harder than alert matching
10
+
11
+ Production incidents are graph-shaped. The component that alarms is often not the component that failed, downstream business services inherit impact transitively, and a mitigation is safe only under additional conditions. A useful answer therefore needs both **correlation** and **dependency reasoning**.
12
+
13
+ The example exposes the complete chain as ordinary relations: `root_cause/3`, `impacted_service/2`, `recommended_action/2`, and `evidence_chain/2`.
14
+
15
+ ## Files
16
+
17
+ - [`../operational-incident-response.pl`](../operational-incident-response.pl)
18
+ - [`../data/operational-incident-response-input.nq`](../data/operational-incident-response-input.nq)
19
+ - [`../data/operational-incident-response-rules.pl`](../data/operational-incident-response-rules.pl)
20
+ - [`../data/operational-incident-response-output.nq`](../data/operational-incident-response-output.nq)
21
+
22
+ ## Reproduce
23
+
24
+ ```sh
25
+ rdf-to-prolog examples/data/operational-incident-response-input.nq \
26
+ --rules examples/data/operational-incident-response-rules.pl \
27
+ -o examples/operational-incident-response.pl
28
+
29
+ eyeprolog examples/operational-incident-response.pl
30
+
31
+ eyeprolog --goal write_results examples/operational-incident-response.pl \
32
+ > examples/data/operational-incident-response-output.pl
33
+ prolog-to-rdf examples/data/operational-incident-response-output.pl \
34
+ -o examples/data/operational-incident-response-output.nq
35
+ ```
@@ -0,0 +1,42 @@
1
+ # Software supply-chain vulnerability response
2
+
3
+ ## Decision
4
+
5
+ **Should `checkout-prod` be deployed, and if not, exactly which transitive dependency and fix are responsible?**
6
+
7
+ The checked example answers **block**. The production service reaches a critical CVE through `shop-app → payments-sdk → crypto-wrapper → openssl-3.0.12`. A separate medium-severity logging CVE is covered by an active, explicit waiver, so it does not masquerade as the blocking reason.
8
+
9
+ ## Why this is a useful EyeProlog case
10
+
11
+ Real SBOM review is a graph problem plus policy: dependencies are transitive, vulnerability feeds change, exceptions expire, and reviewers need more than a red/green score. EyeProlog keeps the dependency path, policy, exception, and resulting action in the same inspectable reasoning model.
12
+
13
+ The example demonstrates:
14
+
15
+ - transitive dependency reasoning over RDF `rdf/4` facts;
16
+ - severity policy and time-bounded waivers;
17
+ - a concrete deployment decision;
18
+ - an exact exposure path, not just “vulnerable”;
19
+ - a machine-readable upgrade conclusion that can round-trip to RDF.
20
+
21
+ ## Files
22
+
23
+ - [`../sbom-vulnerability-response.pl`](../sbom-vulnerability-response.pl) — runnable combined example
24
+ - [`../data/sbom-vulnerability-response-input.nq`](../data/sbom-vulnerability-response-input.nq) — RDF 1.2 input
25
+ - [`../data/sbom-vulnerability-response-rules.pl`](../data/sbom-vulnerability-response-rules.pl) — portable rules
26
+ - [`../data/sbom-vulnerability-response-output.nq`](../data/sbom-vulnerability-response-output.nq) — materialized RDF result
27
+
28
+ ## Reproduce the boundary
29
+
30
+ ```sh
31
+ rdf-to-prolog examples/data/sbom-vulnerability-response-input.nq \
32
+ --rules examples/data/sbom-vulnerability-response-rules.pl \
33
+ -o examples/sbom-vulnerability-response.pl
34
+
35
+ eyeprolog examples/sbom-vulnerability-response.pl
36
+
37
+ eyeprolog --goal write_results examples/sbom-vulnerability-response.pl \
38
+ > examples/data/sbom-vulnerability-response-output.pl
39
+
40
+ prolog-to-rdf examples/data/sbom-vulnerability-response-output.pl \
41
+ -o examples/data/sbom-vulnerability-response-output.nq
42
+ ```
@@ -0,0 +1,40 @@
1
+ # Scientific evidence graph
2
+
3
+ ## Decision
4
+
5
+ **What should a knowledge graph say when studies disagree?**
6
+
7
+ This example does not turn every published statement into truth. RDF 1.2 triple terms represent the scientific claims themselves, while study metadata records who produced evidence, study design, sample size, peer review, and whether the result supports or contradicts the claim.
8
+
9
+ EyeProlog then derives two deliberately different conclusions:
10
+
11
+ - **marker reduction: supported** — two independent randomized studies with sample size ≥100 agree; a small observational contradiction remains visible as lower-quality counterevidence;
12
+ - **survival benefit: contested** — high-quality randomized evidence exists on both sides, so the graph refuses to flatten the disagreement into a single accepted assertion.
13
+
14
+ ## Why this matters
15
+
16
+ Knowledge graphs are good at storing statements and provenance, but scientific use needs an explicit policy for what those statements justify. The interesting reasoning is about **quality, independence, corroboration, contradiction, and the boundary between evidence and accepted conclusion**.
17
+
18
+ This is also a natural symbiotic-KG case: machines can extract candidate evidence, RDF preserves the source structure, Prolog makes the acceptance policy inspectable, and humans can challenge either the evidence metadata or the policy itself.
19
+
20
+ ## Files
21
+
22
+ - [`../scientific-evidence-graph.pl`](../scientific-evidence-graph.pl)
23
+ - [`../data/scientific-evidence-graph-input.nq`](../data/scientific-evidence-graph-input.nq)
24
+ - [`../data/scientific-evidence-graph-rules.pl`](../data/scientific-evidence-graph-rules.pl)
25
+ - [`../data/scientific-evidence-graph-output.nq`](../data/scientific-evidence-graph-output.nq)
26
+
27
+ ## Reproduce
28
+
29
+ ```sh
30
+ rdf-to-prolog examples/data/scientific-evidence-graph-input.nq \
31
+ --rules examples/data/scientific-evidence-graph-rules.pl \
32
+ -o examples/scientific-evidence-graph.pl
33
+
34
+ eyeprolog examples/scientific-evidence-graph.pl
35
+
36
+ eyeprolog --goal write_results examples/scientific-evidence-graph.pl \
37
+ > examples/data/scientific-evidence-graph-output.pl
38
+ prolog-to-rdf examples/data/scientific-evidence-graph-output.pl \
39
+ -o examples/data/scientific-evidence-graph-output.nq
40
+ ```
@@ -0,0 +1,78 @@
1
+ % Generated by rdf-prolog-roundtrip.
2
+
3
+ % RDF terms use rdf(Subject, Predicate, Object, Graph).
4
+
5
+ rdf(iri('https://example.org/ev-depot/site/depot-a'), iri('https://example.org/vocab/availablePowerKw'), literal('60', datatype('http://www.w3.org/2001/XMLSchema#integer')), iri('https://example.org/ev-depot/graph/site')).
6
+ rdf(iri('https://example.org/ev-depot/site/depot-a'), iri('https://example.org/vocab/requiredChargeKw'), literal('22', datatype('http://www.w3.org/2001/XMLSchema#integer')), iri('https://example.org/ev-depot/graph/site')).
7
+ rdf(iri('https://example.org/ev-depot/site/depot-a'), iri('https://example.org/vocab/requiredConnector'), iri('https://example.org/ev-depot/connector/ccs2'), iri('https://example.org/ev-depot/graph/site')).
8
+ rdf(iri('https://example.org/ev-depot/site/depot-a'), iri('https://example.org/vocab/supply'), iri('https://example.org/ev-depot/supply/three-phase'), iri('https://example.org/ev-depot/graph/site')).
9
+ rdf(iri('https://example.org/ev-depot/charger/fleet22'), iri('https://example.org/vocab/chargeKw'), literal('22', datatype('http://www.w3.org/2001/XMLSchema#integer')), iri('https://example.org/ev-depot/graph/catalog')).
10
+ rdf(iri('https://example.org/ev-depot/charger/fleet22'), iri('https://example.org/vocab/sitePowerRequirementKw'), literal('45', datatype('http://www.w3.org/2001/XMLSchema#integer')), iri('https://example.org/ev-depot/graph/catalog')).
11
+ rdf(iri('https://example.org/ev-depot/charger/fleet22'), iri('https://example.org/vocab/connector'), iri('https://example.org/ev-depot/connector/ccs2'), iri('https://example.org/ev-depot/graph/catalog')).
12
+ rdf(iri('https://example.org/ev-depot/charger/fleet22'), iri('https://example.org/vocab/supply'), iri('https://example.org/ev-depot/supply/three-phase'), iri('https://example.org/ev-depot/graph/catalog')).
13
+ rdf(iri('https://example.org/ev-depot/charger/rapid50'), iri('https://example.org/vocab/chargeKw'), literal('50', datatype('http://www.w3.org/2001/XMLSchema#integer')), iri('https://example.org/ev-depot/graph/catalog')).
14
+ rdf(iri('https://example.org/ev-depot/charger/rapid50'), iri('https://example.org/vocab/sitePowerRequirementKw'), literal('80', datatype('http://www.w3.org/2001/XMLSchema#integer')), iri('https://example.org/ev-depot/graph/catalog')).
15
+ rdf(iri('https://example.org/ev-depot/charger/rapid50'), iri('https://example.org/vocab/connector'), iri('https://example.org/ev-depot/connector/ccs2'), iri('https://example.org/ev-depot/graph/catalog')).
16
+ rdf(iri('https://example.org/ev-depot/charger/rapid50'), iri('https://example.org/vocab/supply'), iri('https://example.org/ev-depot/supply/three-phase'), iri('https://example.org/ev-depot/graph/catalog')).
17
+ rdf(iri('https://example.org/ev-depot/charger/budget11'), iri('https://example.org/vocab/chargeKw'), literal('11', datatype('http://www.w3.org/2001/XMLSchema#integer')), iri('https://example.org/ev-depot/graph/catalog')).
18
+ rdf(iri('https://example.org/ev-depot/charger/budget11'), iri('https://example.org/vocab/sitePowerRequirementKw'), literal('25', datatype('http://www.w3.org/2001/XMLSchema#integer')), iri('https://example.org/ev-depot/graph/catalog')).
19
+ rdf(iri('https://example.org/ev-depot/charger/budget11'), iri('https://example.org/vocab/connector'), iri('https://example.org/ev-depot/connector/ccs2'), iri('https://example.org/ev-depot/graph/catalog')).
20
+ rdf(iri('https://example.org/ev-depot/charger/budget11'), iri('https://example.org/vocab/supply'), iri('https://example.org/ev-depot/supply/three-phase'), iri('https://example.org/ev-depot/graph/catalog')).
21
+ rdf(iri('https://example.org/ev-depot/charger/legacy22'), iri('https://example.org/vocab/chargeKw'), literal('22', datatype('http://www.w3.org/2001/XMLSchema#integer')), iri('https://example.org/ev-depot/graph/catalog')).
22
+ rdf(iri('https://example.org/ev-depot/charger/legacy22'), iri('https://example.org/vocab/sitePowerRequirementKw'), literal('45', datatype('http://www.w3.org/2001/XMLSchema#integer')), iri('https://example.org/ev-depot/graph/catalog')).
23
+ rdf(iri('https://example.org/ev-depot/charger/legacy22'), iri('https://example.org/vocab/connector'), iri('https://example.org/ev-depot/connector/type2'), iri('https://example.org/ev-depot/graph/catalog')).
24
+ rdf(iri('https://example.org/ev-depot/charger/legacy22'), iri('https://example.org/vocab/supply'), iri('https://example.org/ev-depot/supply/three-phase'), iri('https://example.org/ev-depot/graph/catalog')).
25
+
26
+ % Rules
27
+ % Flagship example: explainable configuration rather than opaque filtering.
28
+ % The same relational model answers: what fits, why does an option fail, and
29
+ % what would have to change to make a rejected option viable?
30
+
31
+ %% goal: compatible(X0, X1)
32
+ %% goal: recommendation(X0, X1)
33
+ %% goal: blocker(X0, X1, X2)
34
+ %% goal: required_change(X0, X1, X2)
35
+
36
+ v(available_power,iri('https://example.org/vocab/availablePowerKw')).
37
+ v(required_charge,iri('https://example.org/vocab/requiredChargeKw')).
38
+ v(required_connector,iri('https://example.org/vocab/requiredConnector')).
39
+ v(supply,iri('https://example.org/vocab/supply')).
40
+ v(charge_kw,iri('https://example.org/vocab/chargeKw')).
41
+ v(site_power_requirement,iri('https://example.org/vocab/sitePowerRequirementKw')).
42
+ v(connector,iri('https://example.org/vocab/connector')).
43
+
44
+ g(site,iri('https://example.org/ev-depot/graph/site')). g(catalog,iri('https://example.org/ev-depot/graph/catalog')).
45
+ resource(depot_a,iri('https://example.org/ev-depot/site/depot-a')).
46
+ resource(fleet22,iri('https://example.org/ev-depot/charger/fleet22')).
47
+ resource(rapid50,iri('https://example.org/ev-depot/charger/rapid50')).
48
+ resource(budget11,iri('https://example.org/ev-depot/charger/budget11')).
49
+ resource(legacy22,iri('https://example.org/ev-depot/charger/legacy22')).
50
+ product(fleet22). product(rapid50). product(budget11). product(legacy22).
51
+ integer_literal(literal(Text,datatype('http://www.w3.org/2001/XMLSchema#integer')),N):-atom_chars(Text,Cs),number_chars(N,Cs).
52
+
53
+ site_number(Key,N):-resource(depot_a,S),v(Key,P),g(site,G),rdf(S,P,L,G),integer_literal(L,N).
54
+ site_term(Key,V):-resource(depot_a,S),v(Key,P),g(site,G),rdf(S,P,V,G).
55
+ product_number(Product,Key,N):-resource(Product,R),v(Key,P),g(catalog,G),rdf(R,P,L,G),integer_literal(L,N).
56
+ product_term(Product,Key,V):-resource(Product,R),v(Key,P),g(catalog,G),rdf(R,P,V,G).
57
+
58
+ blocker(depot_a,Product,insufficient_site_power(Available,Needed)):-product(Product),site_number(available_power,Available),product_number(Product,site_power_requirement,Needed),Available < Needed.
59
+ blocker(depot_a,Product,insufficient_charge_rate(Offered,Required)):-product(Product),product_number(Product,charge_kw,Offered),site_number(required_charge,Required),Offered < Required.
60
+ blocker(depot_a,Product,connector_mismatch(Offered,Required)):-product(Product),product_term(Product,connector,OfferedIri),site_term(required_connector,RequiredIri),OfferedIri \= RequiredIri,connector_name(OfferedIri,Offered),connector_name(RequiredIri,Required).
61
+ blocker(depot_a,Product,supply_mismatch):-product(Product),product_term(Product,supply,S),site_term(supply,SiteS),S \= SiteS.
62
+
63
+ connector_name(iri('https://example.org/ev-depot/connector/ccs2'),ccs2).
64
+ connector_name(iri('https://example.org/ev-depot/connector/type2'),type2).
65
+
66
+ compatible(depot_a,Product):-product(Product),\+ blocker(depot_a,Product,_).
67
+ recommendation(depot_a,fleet22):-compatible(depot_a,fleet22).
68
+
69
+ required_change(depot_a,Product,increase_site_power_to(Needed)):-blocker(depot_a,Product,insufficient_site_power(_,Needed)).
70
+ required_change(depot_a,Product,choose_charger_at_least_kw(Required)):-blocker(depot_a,Product,insufficient_charge_rate(_,Required)).
71
+ required_change(depot_a,Product,use_connector(Required)):-blocker(depot_a,Product,connector_mismatch(_,Required)).
72
+
73
+ result_rdf(S,iri('https://example.org/vocab/recommendedCharger'),C,iri('https://example.org/ev-depot/graph/derived')):-recommendation(depot_a,Product),resource(depot_a,S),resource(Product,C).
74
+ result_rdf(C,iri('https://example.org/vocab/configurationStatus'),iri('https://example.org/ev-depot/state/compatible'),iri('https://example.org/ev-depot/graph/derived')):-compatible(depot_a,Product),resource(Product,C).
75
+
76
+ write_results:-result_rdf(S,P,O,G),write_term(rdf(S,P,O,G),[quoted(true)]),write('.'),nl,fail.
77
+ write_results.
78
+ :- set_prolog_flag(unknown, fail).
@@ -0,0 +1,89 @@
1
+ % Generated by rdf-prolog-roundtrip.
2
+
3
+ % RDF terms use rdf(Subject, Predicate, Object, Graph).
4
+
5
+ rdf(iri('https://example.org/operations/service/storefront'), iri('https://example.org/vocab/dependsOn'), iri('https://example.org/operations/service/checkout-api'), iri('https://example.org/operations/graph/topology')).
6
+ rdf(iri('https://example.org/operations/service/mobile-app'), iri('https://example.org/vocab/dependsOn'), iri('https://example.org/operations/service/checkout-api'), iri('https://example.org/operations/graph/topology')).
7
+ rdf(iri('https://example.org/operations/service/checkout-api'), iri('https://example.org/vocab/dependsOn'), iri('https://example.org/operations/service/payment-api'), iri('https://example.org/operations/graph/topology')).
8
+ rdf(iri('https://example.org/operations/service/payment-api'), iri('https://example.org/vocab/dependsOn'), iri('https://example.org/operations/db/primary'), iri('https://example.org/operations/graph/topology')).
9
+ rdf(iri('https://example.org/operations/service/payment-api'), iri('https://example.org/vocab/dependsOn'), iri('https://example.org/operations/service/auth-service'), iri('https://example.org/operations/graph/topology')).
10
+ rdf(iri('https://example.org/operations/service/auth-service'), iri('https://example.org/vocab/dependsOn'), iri('https://example.org/operations/db/identity'), iri('https://example.org/operations/graph/topology')).
11
+ rdf(iri('https://example.org/operations/incident/inc-900'), iri('https://example.org/vocab/symptom'), iri('https://example.org/operations/symptom/db-timeout'), iri('https://example.org/operations/graph/incident')).
12
+ rdf(iri('https://example.org/operations/incident/inc-900'), iri('https://example.org/vocab/observedOn'), iri('https://example.org/operations/service/payment-api'), iri('https://example.org/operations/graph/incident')).
13
+ rdf(iri('https://example.org/operations/db/primary'), iri('https://example.org/vocab/status'), iri('https://example.org/operations/state/unhealthy'), iri('https://example.org/operations/graph/telemetry')).
14
+ rdf(iri('https://example.org/operations/db/primary'), iri('https://example.org/vocab/diskUsagePercent'), literal('100', datatype('http://www.w3.org/2001/XMLSchema#integer')), iri('https://example.org/operations/graph/telemetry')).
15
+ rdf(iri('https://example.org/operations/db/replica'), iri('https://example.org/vocab/status'), iri('https://example.org/operations/state/healthy'), iri('https://example.org/operations/graph/telemetry')).
16
+ rdf(iri('https://example.org/operations/service/auth-service'), iri('https://example.org/vocab/status'), iri('https://example.org/operations/state/healthy'), iri('https://example.org/operations/graph/telemetry')).
17
+ rdf(iri('https://example.org/operations/service/payment-api'), iri('https://example.org/vocab/errorRatePercent'), literal('72', datatype('http://www.w3.org/2001/XMLSchema#integer')), iri('https://example.org/operations/graph/telemetry')).
18
+ rdf(iri('https://example.org/operations/runbook/db-failover'), iri('https://example.org/vocab/whenCause'), iri('https://example.org/operations/cause/disk-full'), iri('https://example.org/operations/graph/runbook')).
19
+ rdf(iri('https://example.org/operations/runbook/db-failover'), iri('https://example.org/vocab/action'), iri('https://example.org/operations/action/failover-to-replica'), iri('https://example.org/operations/graph/runbook')).
20
+
21
+ % Rules
22
+ % Flagship example: operational incident diagnosis and response.
23
+ % The topology, incident observations, telemetry, and runbook are RDF data.
24
+ % Prolog correlates evidence, traverses service dependencies, and recommends a
25
+ % bounded mitigation with an inspectable evidence chain.
26
+
27
+ %% goal: root_cause(X0, X1, X2)
28
+ %% goal: impacted_service(X0, X1)
29
+ %% goal: recommended_action(X0, X1)
30
+ %% goal: evidence_chain(X0, X1)
31
+
32
+ v(depends_on,iri('https://example.org/vocab/dependsOn')).
33
+ v(symptom,iri('https://example.org/vocab/symptom')).
34
+ v(observed_on,iri('https://example.org/vocab/observedOn')).
35
+ v(status,iri('https://example.org/vocab/status')).
36
+ v(disk_usage,iri('https://example.org/vocab/diskUsagePercent')).
37
+ v(error_rate,iri('https://example.org/vocab/errorRatePercent')).
38
+ v(when_cause,iri('https://example.org/vocab/whenCause')).
39
+ v(action,iri('https://example.org/vocab/action')).
40
+
41
+ g(topology,iri('https://example.org/operations/graph/topology')).
42
+ g(telemetry,iri('https://example.org/operations/graph/telemetry')).
43
+ g(incident,iri('https://example.org/operations/graph/incident')).
44
+ g(runbook,iri('https://example.org/operations/graph/runbook')).
45
+
46
+ resource(inc900,iri('https://example.org/operations/incident/inc-900')).
47
+ resource(storefront,iri('https://example.org/operations/service/storefront')).
48
+ resource(mobile_app,iri('https://example.org/operations/service/mobile-app')).
49
+ resource(checkout_api,iri('https://example.org/operations/service/checkout-api')).
50
+ resource(payment_api,iri('https://example.org/operations/service/payment-api')).
51
+ resource(auth_service,iri('https://example.org/operations/service/auth-service')).
52
+ resource(primary_db,iri('https://example.org/operations/db/primary')).
53
+ resource(replica_db,iri('https://example.org/operations/db/replica')).
54
+
55
+ integer_literal(literal(Text,datatype('http://www.w3.org/2001/XMLSchema#integer')),N):-atom_chars(Text,Cs),number_chars(N,Cs).
56
+
57
+ depends(A,B):-resource(A,RA),resource(B,RB),v(depends_on,P),g(topology,G),rdf(RA,P,RB,G).
58
+ transitively_depends(A,B):-depends(A,B).
59
+ transitively_depends(A,B):-depends(A,C),transitively_depends(C,B).
60
+
61
+ telemetry(Resource,Key,Value):-resource(Resource,R),v(Key,P),g(telemetry,G),rdf(R,P,Value,G).
62
+ incident_fact(Key,Value):-resource(inc900,I),v(Key,P),g(incident,G),rdf(I,P,Value,G).
63
+
64
+ root_cause(inc900,primary_db,disk_full):-
65
+ incident_fact(symptom,iri('https://example.org/operations/symptom/db-timeout')),
66
+ telemetry(primary_db,status,iri('https://example.org/operations/state/unhealthy')),
67
+ telemetry(primary_db,disk_usage,L),integer_literal(L,100),
68
+ telemetry(payment_api,error_rate,E),integer_literal(E,Rate),Rate >= 50,
69
+ telemetry(auth_service,status,iri('https://example.org/operations/state/healthy')).
70
+
71
+ impacted_service(inc900,primary_db):-root_cause(inc900,primary_db,_).
72
+ impacted_service(inc900,Service):-root_cause(inc900,primary_db,_),transitively_depends(Service,primary_db).
73
+
74
+ cause_iri(disk_full,iri('https://example.org/operations/cause/disk-full')).
75
+ action_iri(failover_to_replica,iri('https://example.org/operations/action/failover-to-replica')).
76
+ runbook_action(Cause,Action):-g(runbook,G),v(when_cause,PC),v(action,PA),cause_iri(Cause,C),action_iri(Action,A),rdf(Rule,PC,C,G),rdf(Rule,PA,A,G).
77
+
78
+ recommended_action(inc900,failover(primary_db,replica_db)):-
79
+ root_cause(inc900,primary_db,disk_full),runbook_action(disk_full,failover_to_replica),telemetry(replica_db,status,iri('https://example.org/operations/state/healthy')).
80
+
81
+ evidence_chain(inc900,[payment_api_db_timeout,primary_db_unhealthy,primary_db_disk_100_percent,auth_service_healthy,replica_db_healthy]):-recommended_action(inc900,_).
82
+
83
+ result_rdf(I,iri('https://example.org/vocab/rootCause'),C,iri('https://example.org/operations/graph/derived')):-root_cause(inc900,primary_db,disk_full),resource(inc900,I),resource(primary_db,C).
84
+ result_rdf(I,iri('https://example.org/vocab/recommendedAction'),ActionIri,iri('https://example.org/operations/graph/derived')):-recommended_action(inc900,_),runbook_action(disk_full,failover_to_replica),action_iri(failover_to_replica,ActionIri),resource(inc900,I).
85
+ result_rdf(I,iri('https://example.org/vocab/impacts'),S,iri('https://example.org/operations/graph/derived')):-impacted_service(inc900,Service),resource(inc900,I),resource(Service,S).
86
+
87
+ write_results:-result_rdf(S,P,O,G),write_term(rdf(S,P,O,G),[quoted(true)]),write('.'),nl,fail.
88
+ write_results.
89
+ :- set_prolog_flag(unknown, fail).
@@ -0,0 +1,8 @@
1
+ sharing_decision(marketing, deny).
2
+ sharing_decision(research_us, review).
3
+ sharing_decision(research_eu, permit).
4
+ obligation(research_eu, delete_after_days(120)).
5
+ obligation(research_eu, retain_audit_log).
6
+ decision_reason(research_eu, "ODRL permission matches; recipient is certified, data is pseudonymized, retention is within 180 days, and the transfer stays in-region.").
7
+ decision_reason(marketing, "The requested marketing distribution matches an explicit ODRL prohibition.").
8
+ decision_reason(research_us, "The research purpose is permitted, but the out-of-region transfer lacks the required contractual safeguard and must be reviewed.").
@@ -0,0 +1,8 @@
1
+ blocker(depot_a, rapid50, insufficient_site_power(60, 80)).
2
+ blocker(depot_a, budget11, insufficient_charge_rate(11, 22)).
3
+ blocker(depot_a, legacy22, connector_mismatch(type2, ccs2)).
4
+ compatible(depot_a, fleet22).
5
+ recommendation(depot_a, fleet22).
6
+ required_change(depot_a, rapid50, increase_site_power_to(80)).
7
+ required_change(depot_a, budget11, choose_charger_at_least_kw(22)).
8
+ required_change(depot_a, legacy22, use_connector(ccs2)).