eyeprolog 1.3.98 → 1.3.100

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 (45) 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/test/run-playground.mjs +12 -0
  43. package/test/run-regression.mjs +17 -0
  44. package/the-art-of-eyeprolog.md +11 -4
  45. package/why-eyeprolog.md +2 -0
package/README.md CHANGED
@@ -64,8 +64,9 @@ printf 'human(socrates).\nmortal(X) :- human(X).\n' |
64
64
  - [Why EyeProlog?](https://eyereasoner.github.io/eyeprolog/why-eyeprolog) — project scope and design
65
65
  - [Playground](https://eyereasoner.github.io/eyeprolog/playground) — run EyeProlog in a browser
66
66
  - [Examples](examples) — runnable programs and checked output
67
+ - [Example decks](examples/deck/README.md) — explainable RDF/Prolog scenarios with reproducible roundtrips
67
68
  - [Symbiotic Knowledge Graphs](examples/deck/symbiotic-knowledge-graphs.md) — RDF ↔ Prolog heatwave-response demo for human/AI/KG co-evolution
68
- - [rdf-prolog-roundtrip](https://github.com/eyereasoner/rdf-prolog-roundtrip) — standalone RDF 1.2 ↔ ISO Prolog bridge used by the symbiotic example
69
+ - [rdf-prolog-roundtrip](https://github.com/eyereasoner/rdf-prolog-roundtrip) — standalone RDF 1.2 ↔ ISO Prolog bridge used by the RDF examples
69
70
  - [ISO conformance audit](test/conformance/ISO-COMPLIANCE.md) — supported Part 1 profile
70
71
  - [Conformance report](conformance-report.md) — generated public corpus summary
71
72
  - [OpenRuleBench](openrulebench/README.md) — portable benchmark profile
@@ -76,6 +77,8 @@ EyeProlog can sit behind an RDF knowledge graph without inventing a private grap
76
77
 
77
78
  The checked [Symbiotic Knowledge Graphs example](examples/symbiotic-knowledge-graph.pl) uses named graphs and RDF 1.2 triple terms to distinguish trusted knowledge, AI-proposed statements, and human review. Its [wide-audience companion](examples/deck/symbiotic-knowledge-graphs.md) explains why this is a useful present-day software model for human/AI/KG co-evolution: RDF supplies shared semantic memory, Prolog supplies explicit deliberation, AI supplies new hypotheses, and people remain participants in meaning and judgment.
78
79
 
80
+ The same RDF → Prolog → RDF boundary is exercised by five additional checked scenarios: [cross-organization data sharing](examples/deck/cross-organization-data-sharing.md), [explainable EV-depot configuration](examples/deck/explainable-ev-depot-configuration.md), [operational incident response](examples/deck/operational-incident-response.md), [software supply-chain vulnerability response](examples/deck/sbom-vulnerability-response.md), and a [scientific evidence graph](examples/deck/scientific-evidence-graph.md). Together they cover policy decisions, reversible configuration reasoning, dependency-graph diagnosis, transitive SBOM exposure, and evidence aggregation with explicit disagreement.
81
+
79
82
  ## Development
80
83
 
81
84
  ```sh
@@ -0,0 +1,121 @@
1
+ % Generated by rdf-prolog-roundtrip.
2
+
3
+ % RDF terms use rdf(Subject, Predicate, Object, Graph).
4
+
5
+ rdf(iri('https://example.org/data-sharing/policy/main'), iri('http://www.w3.org/ns/odrl/2/permission'), iri('https://example.org/data-sharing/policy/research-permission'), iri('https://example.org/data-sharing/graph/policy')).
6
+ rdf(iri('https://example.org/data-sharing/policy/research-permission'), iri('http://www.w3.org/ns/odrl/2/target'), iri('https://example.org/data-sharing/dataset/cohort-a'), iri('https://example.org/data-sharing/graph/policy')).
7
+ rdf(iri('https://example.org/data-sharing/policy/research-permission'), iri('http://www.w3.org/ns/odrl/2/action'), iri('http://www.w3.org/ns/odrl/2/use'), iri('https://example.org/data-sharing/graph/policy')).
8
+ rdf(iri('https://example.org/data-sharing/policy/research-permission'), iri('http://www.w3.org/ns/odrl/2/purpose'), iri('https://w3id.org/dpv#ScientificResearch'), iri('https://example.org/data-sharing/graph/policy')).
9
+ rdf(iri('https://example.org/data-sharing/policy/research-permission'), iri('https://example.org/vocab/maxRetentionDays'), literal('180', datatype('http://www.w3.org/2001/XMLSchema#integer')), iri('https://example.org/data-sharing/graph/policy')).
10
+ rdf(iri('https://example.org/data-sharing/policy/main'), iri('http://www.w3.org/ns/odrl/2/prohibition'), iri('https://example.org/data-sharing/policy/marketing-prohibition'), iri('https://example.org/data-sharing/graph/policy')).
11
+ rdf(iri('https://example.org/data-sharing/policy/marketing-prohibition'), iri('http://www.w3.org/ns/odrl/2/target'), iri('https://example.org/data-sharing/dataset/cohort-a'), iri('https://example.org/data-sharing/graph/policy')).
12
+ rdf(iri('https://example.org/data-sharing/policy/marketing-prohibition'), iri('http://www.w3.org/ns/odrl/2/action'), iri('http://www.w3.org/ns/odrl/2/distribute'), iri('https://example.org/data-sharing/graph/policy')).
13
+ rdf(iri('https://example.org/data-sharing/policy/marketing-prohibition'), iri('http://www.w3.org/ns/odrl/2/purpose'), iri('https://w3id.org/dpv#Marketing'), iri('https://example.org/data-sharing/graph/policy')).
14
+ rdf(iri('https://example.org/data-sharing/org/university-eu'), iri('https://example.org/vocab/region'), iri('https://example.org/data-sharing/region/eu'), iri('https://example.org/data-sharing/graph/organizations')).
15
+ rdf(iri('https://example.org/data-sharing/org/university-eu'), iri('https://example.org/vocab/certifiedResearchOrg'), iri('https://example.org/data-sharing/value/yes'), iri('https://example.org/data-sharing/graph/organizations')).
16
+ rdf(iri('https://example.org/data-sharing/org/university-us'), iri('https://example.org/vocab/region'), iri('https://example.org/data-sharing/region/us'), iri('https://example.org/data-sharing/graph/organizations')).
17
+ rdf(iri('https://example.org/data-sharing/org/university-us'), iri('https://example.org/vocab/certifiedResearchOrg'), iri('https://example.org/data-sharing/value/yes'), iri('https://example.org/data-sharing/graph/organizations')).
18
+ rdf(iri('https://example.org/data-sharing/org/ad-network'), iri('https://example.org/vocab/region'), iri('https://example.org/data-sharing/region/eu'), iri('https://example.org/data-sharing/graph/organizations')).
19
+ rdf(iri('https://example.org/data-sharing/request/research-eu'), iri('https://example.org/vocab/dataset'), iri('https://example.org/data-sharing/dataset/cohort-a'), iri('https://example.org/data-sharing/graph/requests')).
20
+ rdf(iri('https://example.org/data-sharing/request/research-eu'), iri('https://example.org/vocab/recipient'), iri('https://example.org/data-sharing/org/university-eu'), iri('https://example.org/data-sharing/graph/requests')).
21
+ rdf(iri('https://example.org/data-sharing/request/research-eu'), iri('https://example.org/vocab/action'), iri('http://www.w3.org/ns/odrl/2/use'), iri('https://example.org/data-sharing/graph/requests')).
22
+ rdf(iri('https://example.org/data-sharing/request/research-eu'), iri('https://example.org/vocab/purpose'), iri('https://w3id.org/dpv#ScientificResearch'), iri('https://example.org/data-sharing/graph/requests')).
23
+ rdf(iri('https://example.org/data-sharing/request/research-eu'), iri('https://example.org/vocab/retentionDays'), literal('120', datatype('http://www.w3.org/2001/XMLSchema#integer')), iri('https://example.org/data-sharing/graph/requests')).
24
+ rdf(iri('https://example.org/data-sharing/request/research-eu'), iri('https://example.org/vocab/pseudonymized'), iri('https://example.org/data-sharing/value/yes'), iri('https://example.org/data-sharing/graph/requests')).
25
+ rdf(iri('https://example.org/data-sharing/request/research-eu'), iri('https://example.org/vocab/legalBasis'), iri('https://w3id.org/dpv#Consent'), iri('https://example.org/data-sharing/graph/requests')).
26
+ rdf(iri('https://example.org/data-sharing/request/research-eu'), iri('https://example.org/vocab/standardContractualClauses'), iri('https://example.org/data-sharing/value/yes'), iri('https://example.org/data-sharing/graph/requests')).
27
+ rdf(iri('https://example.org/data-sharing/request/marketing'), iri('https://example.org/vocab/dataset'), iri('https://example.org/data-sharing/dataset/cohort-a'), iri('https://example.org/data-sharing/graph/requests')).
28
+ rdf(iri('https://example.org/data-sharing/request/marketing'), iri('https://example.org/vocab/recipient'), iri('https://example.org/data-sharing/org/ad-network'), iri('https://example.org/data-sharing/graph/requests')).
29
+ rdf(iri('https://example.org/data-sharing/request/marketing'), iri('https://example.org/vocab/action'), iri('http://www.w3.org/ns/odrl/2/distribute'), iri('https://example.org/data-sharing/graph/requests')).
30
+ rdf(iri('https://example.org/data-sharing/request/marketing'), iri('https://example.org/vocab/purpose'), iri('https://w3id.org/dpv#Marketing'), iri('https://example.org/data-sharing/graph/requests')).
31
+ rdf(iri('https://example.org/data-sharing/request/marketing'), iri('https://example.org/vocab/retentionDays'), literal('30', datatype('http://www.w3.org/2001/XMLSchema#integer')), iri('https://example.org/data-sharing/graph/requests')).
32
+ rdf(iri('https://example.org/data-sharing/request/marketing'), iri('https://example.org/vocab/pseudonymized'), iri('https://example.org/data-sharing/value/no'), iri('https://example.org/data-sharing/graph/requests')).
33
+ rdf(iri('https://example.org/data-sharing/request/marketing'), iri('https://example.org/vocab/legalBasis'), iri('https://w3id.org/dpv#Consent'), iri('https://example.org/data-sharing/graph/requests')).
34
+ rdf(iri('https://example.org/data-sharing/request/marketing'), iri('https://example.org/vocab/standardContractualClauses'), iri('https://example.org/data-sharing/value/yes'), iri('https://example.org/data-sharing/graph/requests')).
35
+ rdf(iri('https://example.org/data-sharing/request/research-us'), iri('https://example.org/vocab/dataset'), iri('https://example.org/data-sharing/dataset/cohort-a'), iri('https://example.org/data-sharing/graph/requests')).
36
+ rdf(iri('https://example.org/data-sharing/request/research-us'), iri('https://example.org/vocab/recipient'), iri('https://example.org/data-sharing/org/university-us'), iri('https://example.org/data-sharing/graph/requests')).
37
+ rdf(iri('https://example.org/data-sharing/request/research-us'), iri('https://example.org/vocab/action'), iri('http://www.w3.org/ns/odrl/2/use'), iri('https://example.org/data-sharing/graph/requests')).
38
+ rdf(iri('https://example.org/data-sharing/request/research-us'), iri('https://example.org/vocab/purpose'), iri('https://w3id.org/dpv#ScientificResearch'), iri('https://example.org/data-sharing/graph/requests')).
39
+ rdf(iri('https://example.org/data-sharing/request/research-us'), iri('https://example.org/vocab/retentionDays'), literal('90', datatype('http://www.w3.org/2001/XMLSchema#integer')), iri('https://example.org/data-sharing/graph/requests')).
40
+ rdf(iri('https://example.org/data-sharing/request/research-us'), iri('https://example.org/vocab/pseudonymized'), iri('https://example.org/data-sharing/value/yes'), iri('https://example.org/data-sharing/graph/requests')).
41
+ rdf(iri('https://example.org/data-sharing/request/research-us'), iri('https://example.org/vocab/legalBasis'), iri('https://w3id.org/dpv#Consent'), iri('https://example.org/data-sharing/graph/requests')).
42
+ rdf(iri('https://example.org/data-sharing/request/research-us'), iri('https://example.org/vocab/standardContractualClauses'), iri('https://example.org/data-sharing/value/no'), iri('https://example.org/data-sharing/graph/requests')).
43
+
44
+ % Rules
45
+ % Flagship example: cross-organization data-sharing decisions using RDF,
46
+ % W3C ODRL vocabulary, DPV terms, and portable ISO Prolog policy rules.
47
+
48
+ %% goal: sharing_decision(X0, X1)
49
+ %% goal: obligation(X0, X1)
50
+ %% goal: decision_reason(X0, X1)
51
+
52
+ v(dataset, iri('https://example.org/vocab/dataset')).
53
+ v(recipient, iri('https://example.org/vocab/recipient')).
54
+ v(action, iri('https://example.org/vocab/action')).
55
+ v(purpose, iri('https://example.org/vocab/purpose')).
56
+ v(retention_days, iri('https://example.org/vocab/retentionDays')).
57
+ v(pseudonymized, iri('https://example.org/vocab/pseudonymized')).
58
+ v(legal_basis, iri('https://example.org/vocab/legalBasis')).
59
+ v(scc, iri('https://example.org/vocab/standardContractualClauses')).
60
+ v(region, iri('https://example.org/vocab/region')).
61
+ v(certified, iri('https://example.org/vocab/certifiedResearchOrg')).
62
+ v(max_retention, iri('https://example.org/vocab/maxRetentionDays')).
63
+
64
+ g(requests, iri('https://example.org/data-sharing/graph/requests')).
65
+ g(policy, iri('https://example.org/data-sharing/graph/policy')).
66
+ g(orgs, iri('https://example.org/data-sharing/graph/organizations')).
67
+
68
+ yes(iri('https://example.org/data-sharing/value/yes')).
69
+ no(iri('https://example.org/data-sharing/value/no')).
70
+ eu(iri('https://example.org/data-sharing/region/eu')).
71
+ consent_basis(iri('https://w3id.org/dpv#Consent')).
72
+
73
+ request(research_eu, iri('https://example.org/data-sharing/request/research-eu')).
74
+ request(marketing, iri('https://example.org/data-sharing/request/marketing')).
75
+ request(research_us, iri('https://example.org/data-sharing/request/research-us')).
76
+
77
+ integer_literal(literal(Text, datatype('http://www.w3.org/2001/XMLSchema#integer')), N) :- atom_chars(Text,Cs), number_chars(N,Cs).
78
+
79
+ request_data(Id,R,D,Recipient,Action,Purpose,Retention,Pseudo,Basis,Scc) :-
80
+ request(Id,R), g(requests,G), v(dataset,PD),v(recipient,PR),v(action,PA),v(purpose,PP),v(retention_days,PT),v(pseudonymized,PPs),v(legal_basis,PL),v(scc,PS),
81
+ rdf(R,PD,D,G),rdf(R,PR,Recipient,G),rdf(R,PA,Action,G),rdf(R,PP,Purpose,G),rdf(R,PT,L,G),integer_literal(L,Retention),rdf(R,PPs,Pseudo,G),rdf(R,PL,Basis,G),rdf(R,PS,Scc,G).
82
+
83
+ policy_permission(D,Action,Purpose,MaxRetention) :-
84
+ g(policy,G), rdf(_,iri('http://www.w3.org/ns/odrl/2/permission'),Rule,G),
85
+ rdf(Rule,iri('http://www.w3.org/ns/odrl/2/target'),D,G), rdf(Rule,iri('http://www.w3.org/ns/odrl/2/action'),Action,G), rdf(Rule,iri('http://www.w3.org/ns/odrl/2/purpose'),Purpose,G),
86
+ v(max_retention,PM), rdf(Rule,PM,L,G), integer_literal(L,MaxRetention).
87
+
88
+ policy_prohibition(D,Action,Purpose) :-
89
+ g(policy,G), rdf(_,iri('http://www.w3.org/ns/odrl/2/prohibition'),Rule,G),
90
+ rdf(Rule,iri('http://www.w3.org/ns/odrl/2/target'),D,G), rdf(Rule,iri('http://www.w3.org/ns/odrl/2/action'),Action,G), rdf(Rule,iri('http://www.w3.org/ns/odrl/2/purpose'),Purpose,G).
91
+
92
+ recipient_region(Recipient,Region) :- g(orgs,G),v(region,P),rdf(Recipient,P,Region,G).
93
+ certified(Recipient) :- g(orgs,G),v(certified,P),yes(Y),rdf(Recipient,P,Y,G).
94
+
95
+ sharing_decision(Id, deny) :- request_data(Id,_R,D,_Recip,Action,Purpose,_Ret,_Ps,_B,_S), policy_prohibition(D,Action,Purpose).
96
+ sharing_decision(Id, review) :-
97
+ request_data(Id,_R,D,Recip,Action,Purpose,Retention,Pseudo,Basis,Scc), consent_basis(Basis), policy_permission(D,Action,Purpose,Max), certified(Recip), Retention =< Max, yes(Y), Pseudo=Y,
98
+ recipient_region(Recip,Region), eu(EU), Region \= EU, no(N), Scc=N.
99
+ sharing_decision(Id, permit) :-
100
+ request_data(Id,_R,D,Recip,Action,Purpose,Retention,Pseudo,Basis,_Scc), consent_basis(Basis), policy_permission(D,Action,Purpose,Max), certified(Recip), Retention =< Max, yes(Y), Pseudo=Y,
101
+ recipient_region(Recip,Region), eu(EU), Region=EU.
102
+ sharing_decision(Id, permit) :-
103
+ request_data(Id,_R,D,Recip,Action,Purpose,Retention,Pseudo,Basis,Scc), consent_basis(Basis), policy_permission(D,Action,Purpose,Max), certified(Recip), Retention =< Max, yes(Y), Pseudo=Y,
104
+ recipient_region(Recip,Region), eu(EU), Region \= EU, Scc=Y.
105
+
106
+ obligation(research_eu, delete_after_days(120)) :- sharing_decision(research_eu,permit).
107
+ obligation(research_eu, retain_audit_log) :- sharing_decision(research_eu,permit).
108
+
109
+ decision_reason(research_eu, "ODRL permission matches; recipient is certified, data is pseudonymized, retention is within 180 days, and the transfer stays in-region.") :- sharing_decision(research_eu,permit).
110
+ decision_reason(marketing, "The requested marketing distribution matches an explicit ODRL prohibition.") :- sharing_decision(marketing,deny).
111
+ decision_reason(research_us, "The research purpose is permitted, but the out-of-region transfer lacks the required contractual safeguard and must be reviewed.") :- sharing_decision(research_us,review).
112
+
113
+ result_rdf(R, iri('https://example.org/vocab/sharingDecision'), D, iri('https://example.org/data-sharing/graph/derived')) :-
114
+ sharing_decision(Id,Decision), request(Id,R), decision_iri(Decision,D).
115
+ decision_iri(permit,iri('https://example.org/data-sharing/decision/permit')).
116
+ decision_iri(deny,iri('https://example.org/data-sharing/decision/deny')).
117
+ decision_iri(review,iri('https://example.org/data-sharing/decision/review')).
118
+
119
+ write_results :- result_rdf(S,P,O,G), write_term(rdf(S,P,O,G),[quoted(true)]), write('.'), nl, fail.
120
+ write_results.
121
+ :- set_prolog_flag(unknown, fail).
@@ -19,3 +19,18 @@ symbiotic-knowledge-graph-input.nq
19
19
  The input uses named graphs for source boundaries and RDF 1.2 triple terms for AI-proposed statements. A proposed triple is therefore metadata until governance rules accept it; it does not become an operational assertion merely because an AI produced it.
20
20
 
21
21
  See [the wide-audience deck](../deck/symbiotic-knowledge-graphs.md) for the scenario and architecture.
22
+
23
+ ## Additional decision and evidence roundtrips
24
+
25
+ Five further examples use the same explicit boundary: source RDF is converted to `rdf/4` facts, portable rules are appended for EyeProlog, checked conclusions are emitted as Prolog, and ground result facts are converted back to RDF.
26
+
27
+ | Scenario | Source and rules | Materialized result | Companion |
28
+ | --- | --- | --- | --- |
29
+ | Cross-organization data sharing | [`cross-organization-data-sharing-input.nq`](cross-organization-data-sharing-input.nq) · [`cross-organization-data-sharing-rules.pl`](cross-organization-data-sharing-rules.pl) | [`cross-organization-data-sharing-output.nq`](cross-organization-data-sharing-output.nq) | [deck](../deck/cross-organization-data-sharing.md) |
30
+ | Explainable EV-depot configuration | [`explainable-ev-depot-configuration-input.nq`](explainable-ev-depot-configuration-input.nq) · [`explainable-ev-depot-configuration-rules.pl`](explainable-ev-depot-configuration-rules.pl) | [`explainable-ev-depot-configuration-output.nq`](explainable-ev-depot-configuration-output.nq) | [deck](../deck/explainable-ev-depot-configuration.md) |
31
+ | Operational incident response | [`operational-incident-response-input.nq`](operational-incident-response-input.nq) · [`operational-incident-response-rules.pl`](operational-incident-response-rules.pl) | [`operational-incident-response-output.nq`](operational-incident-response-output.nq) | [deck](../deck/operational-incident-response.md) |
32
+ | SBOM vulnerability response | [`sbom-vulnerability-response-input.nq`](sbom-vulnerability-response-input.nq) · [`sbom-vulnerability-response-rules.pl`](sbom-vulnerability-response-rules.pl) | [`sbom-vulnerability-response-output.nq`](sbom-vulnerability-response-output.nq) | [deck](../deck/sbom-vulnerability-response.md) |
33
+ | Scientific evidence graph | [`scientific-evidence-graph-input.nq`](scientific-evidence-graph-input.nq) · [`scientific-evidence-graph-rules.pl`](scientific-evidence-graph-rules.pl) | [`scientific-evidence-graph-output.nq`](scientific-evidence-graph-output.nq) | [deck](../deck/scientific-evidence-graph.md) |
34
+
35
+ Each scenario also has a generated runnable program one directory up and a checked stdout file in `../output/`. The corresponding deck contains the exact reproduction commands for the RDF roundtrip.
36
+
@@ -0,0 +1,40 @@
1
+ VERSION "1.2"
2
+
3
+ <https://example.org/data-sharing/policy/main> <http://www.w3.org/ns/odrl/2/permission> <https://example.org/data-sharing/policy/research-permission> <https://example.org/data-sharing/graph/policy> .
4
+ <https://example.org/data-sharing/policy/research-permission> <http://www.w3.org/ns/odrl/2/target> <https://example.org/data-sharing/dataset/cohort-a> <https://example.org/data-sharing/graph/policy> .
5
+ <https://example.org/data-sharing/policy/research-permission> <http://www.w3.org/ns/odrl/2/action> <http://www.w3.org/ns/odrl/2/use> <https://example.org/data-sharing/graph/policy> .
6
+ <https://example.org/data-sharing/policy/research-permission> <http://www.w3.org/ns/odrl/2/purpose> <https://w3id.org/dpv#ScientificResearch> <https://example.org/data-sharing/graph/policy> .
7
+ <https://example.org/data-sharing/policy/research-permission> <https://example.org/vocab/maxRetentionDays> "180"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/data-sharing/graph/policy> .
8
+ <https://example.org/data-sharing/policy/main> <http://www.w3.org/ns/odrl/2/prohibition> <https://example.org/data-sharing/policy/marketing-prohibition> <https://example.org/data-sharing/graph/policy> .
9
+ <https://example.org/data-sharing/policy/marketing-prohibition> <http://www.w3.org/ns/odrl/2/target> <https://example.org/data-sharing/dataset/cohort-a> <https://example.org/data-sharing/graph/policy> .
10
+ <https://example.org/data-sharing/policy/marketing-prohibition> <http://www.w3.org/ns/odrl/2/action> <http://www.w3.org/ns/odrl/2/distribute> <https://example.org/data-sharing/graph/policy> .
11
+ <https://example.org/data-sharing/policy/marketing-prohibition> <http://www.w3.org/ns/odrl/2/purpose> <https://w3id.org/dpv#Marketing> <https://example.org/data-sharing/graph/policy> .
12
+ <https://example.org/data-sharing/org/university-eu> <https://example.org/vocab/region> <https://example.org/data-sharing/region/eu> <https://example.org/data-sharing/graph/organizations> .
13
+ <https://example.org/data-sharing/org/university-eu> <https://example.org/vocab/certifiedResearchOrg> <https://example.org/data-sharing/value/yes> <https://example.org/data-sharing/graph/organizations> .
14
+ <https://example.org/data-sharing/org/university-us> <https://example.org/vocab/region> <https://example.org/data-sharing/region/us> <https://example.org/data-sharing/graph/organizations> .
15
+ <https://example.org/data-sharing/org/university-us> <https://example.org/vocab/certifiedResearchOrg> <https://example.org/data-sharing/value/yes> <https://example.org/data-sharing/graph/organizations> .
16
+ <https://example.org/data-sharing/org/ad-network> <https://example.org/vocab/region> <https://example.org/data-sharing/region/eu> <https://example.org/data-sharing/graph/organizations> .
17
+ <https://example.org/data-sharing/request/research-eu> <https://example.org/vocab/dataset> <https://example.org/data-sharing/dataset/cohort-a> <https://example.org/data-sharing/graph/requests> .
18
+ <https://example.org/data-sharing/request/research-eu> <https://example.org/vocab/recipient> <https://example.org/data-sharing/org/university-eu> <https://example.org/data-sharing/graph/requests> .
19
+ <https://example.org/data-sharing/request/research-eu> <https://example.org/vocab/action> <http://www.w3.org/ns/odrl/2/use> <https://example.org/data-sharing/graph/requests> .
20
+ <https://example.org/data-sharing/request/research-eu> <https://example.org/vocab/purpose> <https://w3id.org/dpv#ScientificResearch> <https://example.org/data-sharing/graph/requests> .
21
+ <https://example.org/data-sharing/request/research-eu> <https://example.org/vocab/retentionDays> "120"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/data-sharing/graph/requests> .
22
+ <https://example.org/data-sharing/request/research-eu> <https://example.org/vocab/pseudonymized> <https://example.org/data-sharing/value/yes> <https://example.org/data-sharing/graph/requests> .
23
+ <https://example.org/data-sharing/request/research-eu> <https://example.org/vocab/legalBasis> <https://w3id.org/dpv#Consent> <https://example.org/data-sharing/graph/requests> .
24
+ <https://example.org/data-sharing/request/research-eu> <https://example.org/vocab/standardContractualClauses> <https://example.org/data-sharing/value/yes> <https://example.org/data-sharing/graph/requests> .
25
+ <https://example.org/data-sharing/request/marketing> <https://example.org/vocab/dataset> <https://example.org/data-sharing/dataset/cohort-a> <https://example.org/data-sharing/graph/requests> .
26
+ <https://example.org/data-sharing/request/marketing> <https://example.org/vocab/recipient> <https://example.org/data-sharing/org/ad-network> <https://example.org/data-sharing/graph/requests> .
27
+ <https://example.org/data-sharing/request/marketing> <https://example.org/vocab/action> <http://www.w3.org/ns/odrl/2/distribute> <https://example.org/data-sharing/graph/requests> .
28
+ <https://example.org/data-sharing/request/marketing> <https://example.org/vocab/purpose> <https://w3id.org/dpv#Marketing> <https://example.org/data-sharing/graph/requests> .
29
+ <https://example.org/data-sharing/request/marketing> <https://example.org/vocab/retentionDays> "30"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/data-sharing/graph/requests> .
30
+ <https://example.org/data-sharing/request/marketing> <https://example.org/vocab/pseudonymized> <https://example.org/data-sharing/value/no> <https://example.org/data-sharing/graph/requests> .
31
+ <https://example.org/data-sharing/request/marketing> <https://example.org/vocab/legalBasis> <https://w3id.org/dpv#Consent> <https://example.org/data-sharing/graph/requests> .
32
+ <https://example.org/data-sharing/request/marketing> <https://example.org/vocab/standardContractualClauses> <https://example.org/data-sharing/value/yes> <https://example.org/data-sharing/graph/requests> .
33
+ <https://example.org/data-sharing/request/research-us> <https://example.org/vocab/dataset> <https://example.org/data-sharing/dataset/cohort-a> <https://example.org/data-sharing/graph/requests> .
34
+ <https://example.org/data-sharing/request/research-us> <https://example.org/vocab/recipient> <https://example.org/data-sharing/org/university-us> <https://example.org/data-sharing/graph/requests> .
35
+ <https://example.org/data-sharing/request/research-us> <https://example.org/vocab/action> <http://www.w3.org/ns/odrl/2/use> <https://example.org/data-sharing/graph/requests> .
36
+ <https://example.org/data-sharing/request/research-us> <https://example.org/vocab/purpose> <https://w3id.org/dpv#ScientificResearch> <https://example.org/data-sharing/graph/requests> .
37
+ <https://example.org/data-sharing/request/research-us> <https://example.org/vocab/retentionDays> "90"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/data-sharing/graph/requests> .
38
+ <https://example.org/data-sharing/request/research-us> <https://example.org/vocab/pseudonymized> <https://example.org/data-sharing/value/yes> <https://example.org/data-sharing/graph/requests> .
39
+ <https://example.org/data-sharing/request/research-us> <https://example.org/vocab/legalBasis> <https://w3id.org/dpv#Consent> <https://example.org/data-sharing/graph/requests> .
40
+ <https://example.org/data-sharing/request/research-us> <https://example.org/vocab/standardContractualClauses> <https://example.org/data-sharing/value/no> <https://example.org/data-sharing/graph/requests> .
@@ -0,0 +1,5 @@
1
+ VERSION "1.2"
2
+
3
+ <https://example.org/data-sharing/request/marketing> <https://example.org/vocab/sharingDecision> <https://example.org/data-sharing/decision/deny> <https://example.org/data-sharing/graph/derived> .
4
+ <https://example.org/data-sharing/request/research-us> <https://example.org/vocab/sharingDecision> <https://example.org/data-sharing/decision/review> <https://example.org/data-sharing/graph/derived> .
5
+ <https://example.org/data-sharing/request/research-eu> <https://example.org/vocab/sharingDecision> <https://example.org/data-sharing/decision/permit> <https://example.org/data-sharing/graph/derived> .
@@ -0,0 +1,3 @@
1
+ rdf(iri('https://example.org/data-sharing/request/marketing'),iri('https://example.org/vocab/sharingDecision'),iri('https://example.org/data-sharing/decision/deny'),iri('https://example.org/data-sharing/graph/derived')).
2
+ rdf(iri('https://example.org/data-sharing/request/research-us'),iri('https://example.org/vocab/sharingDecision'),iri('https://example.org/data-sharing/decision/review'),iri('https://example.org/data-sharing/graph/derived')).
3
+ rdf(iri('https://example.org/data-sharing/request/research-eu'),iri('https://example.org/vocab/sharingDecision'),iri('https://example.org/data-sharing/decision/permit'),iri('https://example.org/data-sharing/graph/derived')).
@@ -0,0 +1,77 @@
1
+ % Flagship example: cross-organization data-sharing decisions using RDF,
2
+ % W3C ODRL vocabulary, DPV terms, and portable ISO Prolog policy rules.
3
+
4
+ %% goal: sharing_decision(X0, X1)
5
+ %% goal: obligation(X0, X1)
6
+ %% goal: decision_reason(X0, X1)
7
+
8
+ v(dataset, iri('https://example.org/vocab/dataset')).
9
+ v(recipient, iri('https://example.org/vocab/recipient')).
10
+ v(action, iri('https://example.org/vocab/action')).
11
+ v(purpose, iri('https://example.org/vocab/purpose')).
12
+ v(retention_days, iri('https://example.org/vocab/retentionDays')).
13
+ v(pseudonymized, iri('https://example.org/vocab/pseudonymized')).
14
+ v(legal_basis, iri('https://example.org/vocab/legalBasis')).
15
+ v(scc, iri('https://example.org/vocab/standardContractualClauses')).
16
+ v(region, iri('https://example.org/vocab/region')).
17
+ v(certified, iri('https://example.org/vocab/certifiedResearchOrg')).
18
+ v(max_retention, iri('https://example.org/vocab/maxRetentionDays')).
19
+
20
+ g(requests, iri('https://example.org/data-sharing/graph/requests')).
21
+ g(policy, iri('https://example.org/data-sharing/graph/policy')).
22
+ g(orgs, iri('https://example.org/data-sharing/graph/organizations')).
23
+
24
+ yes(iri('https://example.org/data-sharing/value/yes')).
25
+ no(iri('https://example.org/data-sharing/value/no')).
26
+ eu(iri('https://example.org/data-sharing/region/eu')).
27
+ consent_basis(iri('https://w3id.org/dpv#Consent')).
28
+
29
+ request(research_eu, iri('https://example.org/data-sharing/request/research-eu')).
30
+ request(marketing, iri('https://example.org/data-sharing/request/marketing')).
31
+ request(research_us, iri('https://example.org/data-sharing/request/research-us')).
32
+
33
+ integer_literal(literal(Text, datatype('http://www.w3.org/2001/XMLSchema#integer')), N) :- atom_chars(Text,Cs), number_chars(N,Cs).
34
+
35
+ request_data(Id,R,D,Recipient,Action,Purpose,Retention,Pseudo,Basis,Scc) :-
36
+ request(Id,R), g(requests,G), v(dataset,PD),v(recipient,PR),v(action,PA),v(purpose,PP),v(retention_days,PT),v(pseudonymized,PPs),v(legal_basis,PL),v(scc,PS),
37
+ rdf(R,PD,D,G),rdf(R,PR,Recipient,G),rdf(R,PA,Action,G),rdf(R,PP,Purpose,G),rdf(R,PT,L,G),integer_literal(L,Retention),rdf(R,PPs,Pseudo,G),rdf(R,PL,Basis,G),rdf(R,PS,Scc,G).
38
+
39
+ policy_permission(D,Action,Purpose,MaxRetention) :-
40
+ g(policy,G), rdf(_,iri('http://www.w3.org/ns/odrl/2/permission'),Rule,G),
41
+ rdf(Rule,iri('http://www.w3.org/ns/odrl/2/target'),D,G), rdf(Rule,iri('http://www.w3.org/ns/odrl/2/action'),Action,G), rdf(Rule,iri('http://www.w3.org/ns/odrl/2/purpose'),Purpose,G),
42
+ v(max_retention,PM), rdf(Rule,PM,L,G), integer_literal(L,MaxRetention).
43
+
44
+ policy_prohibition(D,Action,Purpose) :-
45
+ g(policy,G), rdf(_,iri('http://www.w3.org/ns/odrl/2/prohibition'),Rule,G),
46
+ rdf(Rule,iri('http://www.w3.org/ns/odrl/2/target'),D,G), rdf(Rule,iri('http://www.w3.org/ns/odrl/2/action'),Action,G), rdf(Rule,iri('http://www.w3.org/ns/odrl/2/purpose'),Purpose,G).
47
+
48
+ recipient_region(Recipient,Region) :- g(orgs,G),v(region,P),rdf(Recipient,P,Region,G).
49
+ certified(Recipient) :- g(orgs,G),v(certified,P),yes(Y),rdf(Recipient,P,Y,G).
50
+
51
+ sharing_decision(Id, deny) :- request_data(Id,_R,D,_Recip,Action,Purpose,_Ret,_Ps,_B,_S), policy_prohibition(D,Action,Purpose).
52
+ sharing_decision(Id, review) :-
53
+ request_data(Id,_R,D,Recip,Action,Purpose,Retention,Pseudo,Basis,Scc), consent_basis(Basis), policy_permission(D,Action,Purpose,Max), certified(Recip), Retention =< Max, yes(Y), Pseudo=Y,
54
+ recipient_region(Recip,Region), eu(EU), Region \= EU, no(N), Scc=N.
55
+ sharing_decision(Id, permit) :-
56
+ request_data(Id,_R,D,Recip,Action,Purpose,Retention,Pseudo,Basis,_Scc), consent_basis(Basis), policy_permission(D,Action,Purpose,Max), certified(Recip), Retention =< Max, yes(Y), Pseudo=Y,
57
+ recipient_region(Recip,Region), eu(EU), Region=EU.
58
+ sharing_decision(Id, permit) :-
59
+ request_data(Id,_R,D,Recip,Action,Purpose,Retention,Pseudo,Basis,Scc), consent_basis(Basis), policy_permission(D,Action,Purpose,Max), certified(Recip), Retention =< Max, yes(Y), Pseudo=Y,
60
+ recipient_region(Recip,Region), eu(EU), Region \= EU, Scc=Y.
61
+
62
+ obligation(research_eu, delete_after_days(120)) :- sharing_decision(research_eu,permit).
63
+ obligation(research_eu, retain_audit_log) :- sharing_decision(research_eu,permit).
64
+
65
+ decision_reason(research_eu, "ODRL permission matches; recipient is certified, data is pseudonymized, retention is within 180 days, and the transfer stays in-region.") :- sharing_decision(research_eu,permit).
66
+ decision_reason(marketing, "The requested marketing distribution matches an explicit ODRL prohibition.") :- sharing_decision(marketing,deny).
67
+ decision_reason(research_us, "The research purpose is permitted, but the out-of-region transfer lacks the required contractual safeguard and must be reviewed.") :- sharing_decision(research_us,review).
68
+
69
+ result_rdf(R, iri('https://example.org/vocab/sharingDecision'), D, iri('https://example.org/data-sharing/graph/derived')) :-
70
+ sharing_decision(Id,Decision), request(Id,R), decision_iri(Decision,D).
71
+ decision_iri(permit,iri('https://example.org/data-sharing/decision/permit')).
72
+ decision_iri(deny,iri('https://example.org/data-sharing/decision/deny')).
73
+ decision_iri(review,iri('https://example.org/data-sharing/decision/review')).
74
+
75
+ write_results :- result_rdf(S,P,O,G), write_term(rdf(S,P,O,G),[quoted(true)]), write('.'), nl, fail.
76
+ write_results.
77
+ :- set_prolog_flag(unknown, fail).
@@ -0,0 +1,22 @@
1
+ VERSION "1.2"
2
+
3
+ <https://example.org/ev-depot/site/depot-a> <https://example.org/vocab/availablePowerKw> "60"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/ev-depot/graph/site> .
4
+ <https://example.org/ev-depot/site/depot-a> <https://example.org/vocab/requiredChargeKw> "22"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/ev-depot/graph/site> .
5
+ <https://example.org/ev-depot/site/depot-a> <https://example.org/vocab/requiredConnector> <https://example.org/ev-depot/connector/ccs2> <https://example.org/ev-depot/graph/site> .
6
+ <https://example.org/ev-depot/site/depot-a> <https://example.org/vocab/supply> <https://example.org/ev-depot/supply/three-phase> <https://example.org/ev-depot/graph/site> .
7
+ <https://example.org/ev-depot/charger/fleet22> <https://example.org/vocab/chargeKw> "22"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/ev-depot/graph/catalog> .
8
+ <https://example.org/ev-depot/charger/fleet22> <https://example.org/vocab/sitePowerRequirementKw> "45"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/ev-depot/graph/catalog> .
9
+ <https://example.org/ev-depot/charger/fleet22> <https://example.org/vocab/connector> <https://example.org/ev-depot/connector/ccs2> <https://example.org/ev-depot/graph/catalog> .
10
+ <https://example.org/ev-depot/charger/fleet22> <https://example.org/vocab/supply> <https://example.org/ev-depot/supply/three-phase> <https://example.org/ev-depot/graph/catalog> .
11
+ <https://example.org/ev-depot/charger/rapid50> <https://example.org/vocab/chargeKw> "50"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/ev-depot/graph/catalog> .
12
+ <https://example.org/ev-depot/charger/rapid50> <https://example.org/vocab/sitePowerRequirementKw> "80"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/ev-depot/graph/catalog> .
13
+ <https://example.org/ev-depot/charger/rapid50> <https://example.org/vocab/connector> <https://example.org/ev-depot/connector/ccs2> <https://example.org/ev-depot/graph/catalog> .
14
+ <https://example.org/ev-depot/charger/rapid50> <https://example.org/vocab/supply> <https://example.org/ev-depot/supply/three-phase> <https://example.org/ev-depot/graph/catalog> .
15
+ <https://example.org/ev-depot/charger/budget11> <https://example.org/vocab/chargeKw> "11"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/ev-depot/graph/catalog> .
16
+ <https://example.org/ev-depot/charger/budget11> <https://example.org/vocab/sitePowerRequirementKw> "25"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/ev-depot/graph/catalog> .
17
+ <https://example.org/ev-depot/charger/budget11> <https://example.org/vocab/connector> <https://example.org/ev-depot/connector/ccs2> <https://example.org/ev-depot/graph/catalog> .
18
+ <https://example.org/ev-depot/charger/budget11> <https://example.org/vocab/supply> <https://example.org/ev-depot/supply/three-phase> <https://example.org/ev-depot/graph/catalog> .
19
+ <https://example.org/ev-depot/charger/legacy22> <https://example.org/vocab/chargeKw> "22"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/ev-depot/graph/catalog> .
20
+ <https://example.org/ev-depot/charger/legacy22> <https://example.org/vocab/sitePowerRequirementKw> "45"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/ev-depot/graph/catalog> .
21
+ <https://example.org/ev-depot/charger/legacy22> <https://example.org/vocab/connector> <https://example.org/ev-depot/connector/type2> <https://example.org/ev-depot/graph/catalog> .
22
+ <https://example.org/ev-depot/charger/legacy22> <https://example.org/vocab/supply> <https://example.org/ev-depot/supply/three-phase> <https://example.org/ev-depot/graph/catalog> .
@@ -0,0 +1,4 @@
1
+ VERSION "1.2"
2
+
3
+ <https://example.org/ev-depot/site/depot-a> <https://example.org/vocab/recommendedCharger> <https://example.org/ev-depot/charger/fleet22> <https://example.org/ev-depot/graph/derived> .
4
+ <https://example.org/ev-depot/charger/fleet22> <https://example.org/vocab/configurationStatus> <https://example.org/ev-depot/state/compatible> <https://example.org/ev-depot/graph/derived> .
@@ -0,0 +1,2 @@
1
+ rdf(iri('https://example.org/ev-depot/site/depot-a'),iri('https://example.org/vocab/recommendedCharger'),iri('https://example.org/ev-depot/charger/fleet22'),iri('https://example.org/ev-depot/graph/derived')).
2
+ rdf(iri('https://example.org/ev-depot/charger/fleet22'),iri('https://example.org/vocab/configurationStatus'),iri('https://example.org/ev-depot/state/compatible'),iri('https://example.org/ev-depot/graph/derived')).
@@ -0,0 +1,52 @@
1
+ % Flagship example: explainable configuration rather than opaque filtering.
2
+ % The same relational model answers: what fits, why does an option fail, and
3
+ % what would have to change to make a rejected option viable?
4
+
5
+ %% goal: compatible(X0, X1)
6
+ %% goal: recommendation(X0, X1)
7
+ %% goal: blocker(X0, X1, X2)
8
+ %% goal: required_change(X0, X1, X2)
9
+
10
+ v(available_power,iri('https://example.org/vocab/availablePowerKw')).
11
+ v(required_charge,iri('https://example.org/vocab/requiredChargeKw')).
12
+ v(required_connector,iri('https://example.org/vocab/requiredConnector')).
13
+ v(supply,iri('https://example.org/vocab/supply')).
14
+ v(charge_kw,iri('https://example.org/vocab/chargeKw')).
15
+ v(site_power_requirement,iri('https://example.org/vocab/sitePowerRequirementKw')).
16
+ v(connector,iri('https://example.org/vocab/connector')).
17
+
18
+ g(site,iri('https://example.org/ev-depot/graph/site')). g(catalog,iri('https://example.org/ev-depot/graph/catalog')).
19
+ resource(depot_a,iri('https://example.org/ev-depot/site/depot-a')).
20
+ resource(fleet22,iri('https://example.org/ev-depot/charger/fleet22')).
21
+ resource(rapid50,iri('https://example.org/ev-depot/charger/rapid50')).
22
+ resource(budget11,iri('https://example.org/ev-depot/charger/budget11')).
23
+ resource(legacy22,iri('https://example.org/ev-depot/charger/legacy22')).
24
+ product(fleet22). product(rapid50). product(budget11). product(legacy22).
25
+ integer_literal(literal(Text,datatype('http://www.w3.org/2001/XMLSchema#integer')),N):-atom_chars(Text,Cs),number_chars(N,Cs).
26
+
27
+ site_number(Key,N):-resource(depot_a,S),v(Key,P),g(site,G),rdf(S,P,L,G),integer_literal(L,N).
28
+ site_term(Key,V):-resource(depot_a,S),v(Key,P),g(site,G),rdf(S,P,V,G).
29
+ product_number(Product,Key,N):-resource(Product,R),v(Key,P),g(catalog,G),rdf(R,P,L,G),integer_literal(L,N).
30
+ product_term(Product,Key,V):-resource(Product,R),v(Key,P),g(catalog,G),rdf(R,P,V,G).
31
+
32
+ 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.
33
+ blocker(depot_a,Product,insufficient_charge_rate(Offered,Required)):-product(Product),product_number(Product,charge_kw,Offered),site_number(required_charge,Required),Offered < Required.
34
+ 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).
35
+ blocker(depot_a,Product,supply_mismatch):-product(Product),product_term(Product,supply,S),site_term(supply,SiteS),S \= SiteS.
36
+
37
+ connector_name(iri('https://example.org/ev-depot/connector/ccs2'),ccs2).
38
+ connector_name(iri('https://example.org/ev-depot/connector/type2'),type2).
39
+
40
+ compatible(depot_a,Product):-product(Product),\+ blocker(depot_a,Product,_).
41
+ recommendation(depot_a,fleet22):-compatible(depot_a,fleet22).
42
+
43
+ required_change(depot_a,Product,increase_site_power_to(Needed)):-blocker(depot_a,Product,insufficient_site_power(_,Needed)).
44
+ required_change(depot_a,Product,choose_charger_at_least_kw(Required)):-blocker(depot_a,Product,insufficient_charge_rate(_,Required)).
45
+ required_change(depot_a,Product,use_connector(Required)):-blocker(depot_a,Product,connector_mismatch(_,Required)).
46
+
47
+ 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).
48
+ 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).
49
+
50
+ write_results:-result_rdf(S,P,O,G),write_term(rdf(S,P,O,G),[quoted(true)]),write('.'),nl,fail.
51
+ write_results.
52
+ :- set_prolog_flag(unknown, fail).
@@ -0,0 +1,17 @@
1
+ VERSION "1.2"
2
+
3
+ <https://example.org/operations/service/storefront> <https://example.org/vocab/dependsOn> <https://example.org/operations/service/checkout-api> <https://example.org/operations/graph/topology> .
4
+ <https://example.org/operations/service/mobile-app> <https://example.org/vocab/dependsOn> <https://example.org/operations/service/checkout-api> <https://example.org/operations/graph/topology> .
5
+ <https://example.org/operations/service/checkout-api> <https://example.org/vocab/dependsOn> <https://example.org/operations/service/payment-api> <https://example.org/operations/graph/topology> .
6
+ <https://example.org/operations/service/payment-api> <https://example.org/vocab/dependsOn> <https://example.org/operations/db/primary> <https://example.org/operations/graph/topology> .
7
+ <https://example.org/operations/service/payment-api> <https://example.org/vocab/dependsOn> <https://example.org/operations/service/auth-service> <https://example.org/operations/graph/topology> .
8
+ <https://example.org/operations/service/auth-service> <https://example.org/vocab/dependsOn> <https://example.org/operations/db/identity> <https://example.org/operations/graph/topology> .
9
+ <https://example.org/operations/incident/inc-900> <https://example.org/vocab/symptom> <https://example.org/operations/symptom/db-timeout> <https://example.org/operations/graph/incident> .
10
+ <https://example.org/operations/incident/inc-900> <https://example.org/vocab/observedOn> <https://example.org/operations/service/payment-api> <https://example.org/operations/graph/incident> .
11
+ <https://example.org/operations/db/primary> <https://example.org/vocab/status> <https://example.org/operations/state/unhealthy> <https://example.org/operations/graph/telemetry> .
12
+ <https://example.org/operations/db/primary> <https://example.org/vocab/diskUsagePercent> "100"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/operations/graph/telemetry> .
13
+ <https://example.org/operations/db/replica> <https://example.org/vocab/status> <https://example.org/operations/state/healthy> <https://example.org/operations/graph/telemetry> .
14
+ <https://example.org/operations/service/auth-service> <https://example.org/vocab/status> <https://example.org/operations/state/healthy> <https://example.org/operations/graph/telemetry> .
15
+ <https://example.org/operations/service/payment-api> <https://example.org/vocab/errorRatePercent> "72"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/operations/graph/telemetry> .
16
+ <https://example.org/operations/runbook/db-failover> <https://example.org/vocab/whenCause> <https://example.org/operations/cause/disk-full> <https://example.org/operations/graph/runbook> .
17
+ <https://example.org/operations/runbook/db-failover> <https://example.org/vocab/action> <https://example.org/operations/action/failover-to-replica> <https://example.org/operations/graph/runbook> .
@@ -0,0 +1,9 @@
1
+ VERSION "1.2"
2
+
3
+ <https://example.org/operations/incident/inc-900> <https://example.org/vocab/rootCause> <https://example.org/operations/db/primary> <https://example.org/operations/graph/derived> .
4
+ <https://example.org/operations/incident/inc-900> <https://example.org/vocab/recommendedAction> <https://example.org/operations/action/failover-to-replica> <https://example.org/operations/graph/derived> .
5
+ <https://example.org/operations/incident/inc-900> <https://example.org/vocab/impacts> <https://example.org/operations/db/primary> <https://example.org/operations/graph/derived> .
6
+ <https://example.org/operations/incident/inc-900> <https://example.org/vocab/impacts> <https://example.org/operations/service/payment-api> <https://example.org/operations/graph/derived> .
7
+ <https://example.org/operations/incident/inc-900> <https://example.org/vocab/impacts> <https://example.org/operations/service/storefront> <https://example.org/operations/graph/derived> .
8
+ <https://example.org/operations/incident/inc-900> <https://example.org/vocab/impacts> <https://example.org/operations/service/mobile-app> <https://example.org/operations/graph/derived> .
9
+ <https://example.org/operations/incident/inc-900> <https://example.org/vocab/impacts> <https://example.org/operations/service/checkout-api> <https://example.org/operations/graph/derived> .
@@ -0,0 +1,7 @@
1
+ rdf(iri('https://example.org/operations/incident/inc-900'),iri('https://example.org/vocab/rootCause'),iri('https://example.org/operations/db/primary'),iri('https://example.org/operations/graph/derived')).
2
+ rdf(iri('https://example.org/operations/incident/inc-900'),iri('https://example.org/vocab/recommendedAction'),iri('https://example.org/operations/action/failover-to-replica'),iri('https://example.org/operations/graph/derived')).
3
+ rdf(iri('https://example.org/operations/incident/inc-900'),iri('https://example.org/vocab/impacts'),iri('https://example.org/operations/db/primary'),iri('https://example.org/operations/graph/derived')).
4
+ rdf(iri('https://example.org/operations/incident/inc-900'),iri('https://example.org/vocab/impacts'),iri('https://example.org/operations/service/payment-api'),iri('https://example.org/operations/graph/derived')).
5
+ rdf(iri('https://example.org/operations/incident/inc-900'),iri('https://example.org/vocab/impacts'),iri('https://example.org/operations/service/storefront'),iri('https://example.org/operations/graph/derived')).
6
+ rdf(iri('https://example.org/operations/incident/inc-900'),iri('https://example.org/vocab/impacts'),iri('https://example.org/operations/service/mobile-app'),iri('https://example.org/operations/graph/derived')).
7
+ rdf(iri('https://example.org/operations/incident/inc-900'),iri('https://example.org/vocab/impacts'),iri('https://example.org/operations/service/checkout-api'),iri('https://example.org/operations/graph/derived')).
@@ -0,0 +1,68 @@
1
+ % Flagship example: operational incident diagnosis and response.
2
+ % The topology, incident observations, telemetry, and runbook are RDF data.
3
+ % Prolog correlates evidence, traverses service dependencies, and recommends a
4
+ % bounded mitigation with an inspectable evidence chain.
5
+
6
+ %% goal: root_cause(X0, X1, X2)
7
+ %% goal: impacted_service(X0, X1)
8
+ %% goal: recommended_action(X0, X1)
9
+ %% goal: evidence_chain(X0, X1)
10
+
11
+ v(depends_on,iri('https://example.org/vocab/dependsOn')).
12
+ v(symptom,iri('https://example.org/vocab/symptom')).
13
+ v(observed_on,iri('https://example.org/vocab/observedOn')).
14
+ v(status,iri('https://example.org/vocab/status')).
15
+ v(disk_usage,iri('https://example.org/vocab/diskUsagePercent')).
16
+ v(error_rate,iri('https://example.org/vocab/errorRatePercent')).
17
+ v(when_cause,iri('https://example.org/vocab/whenCause')).
18
+ v(action,iri('https://example.org/vocab/action')).
19
+
20
+ g(topology,iri('https://example.org/operations/graph/topology')).
21
+ g(telemetry,iri('https://example.org/operations/graph/telemetry')).
22
+ g(incident,iri('https://example.org/operations/graph/incident')).
23
+ g(runbook,iri('https://example.org/operations/graph/runbook')).
24
+
25
+ resource(inc900,iri('https://example.org/operations/incident/inc-900')).
26
+ resource(storefront,iri('https://example.org/operations/service/storefront')).
27
+ resource(mobile_app,iri('https://example.org/operations/service/mobile-app')).
28
+ resource(checkout_api,iri('https://example.org/operations/service/checkout-api')).
29
+ resource(payment_api,iri('https://example.org/operations/service/payment-api')).
30
+ resource(auth_service,iri('https://example.org/operations/service/auth-service')).
31
+ resource(primary_db,iri('https://example.org/operations/db/primary')).
32
+ resource(replica_db,iri('https://example.org/operations/db/replica')).
33
+
34
+ integer_literal(literal(Text,datatype('http://www.w3.org/2001/XMLSchema#integer')),N):-atom_chars(Text,Cs),number_chars(N,Cs).
35
+
36
+ depends(A,B):-resource(A,RA),resource(B,RB),v(depends_on,P),g(topology,G),rdf(RA,P,RB,G).
37
+ transitively_depends(A,B):-depends(A,B).
38
+ transitively_depends(A,B):-depends(A,C),transitively_depends(C,B).
39
+
40
+ telemetry(Resource,Key,Value):-resource(Resource,R),v(Key,P),g(telemetry,G),rdf(R,P,Value,G).
41
+ incident_fact(Key,Value):-resource(inc900,I),v(Key,P),g(incident,G),rdf(I,P,Value,G).
42
+
43
+ root_cause(inc900,primary_db,disk_full):-
44
+ incident_fact(symptom,iri('https://example.org/operations/symptom/db-timeout')),
45
+ telemetry(primary_db,status,iri('https://example.org/operations/state/unhealthy')),
46
+ telemetry(primary_db,disk_usage,L),integer_literal(L,100),
47
+ telemetry(payment_api,error_rate,E),integer_literal(E,Rate),Rate >= 50,
48
+ telemetry(auth_service,status,iri('https://example.org/operations/state/healthy')).
49
+
50
+ impacted_service(inc900,primary_db):-root_cause(inc900,primary_db,_).
51
+ impacted_service(inc900,Service):-root_cause(inc900,primary_db,_),transitively_depends(Service,primary_db).
52
+
53
+ cause_iri(disk_full,iri('https://example.org/operations/cause/disk-full')).
54
+ action_iri(failover_to_replica,iri('https://example.org/operations/action/failover-to-replica')).
55
+ 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).
56
+
57
+ recommended_action(inc900,failover(primary_db,replica_db)):-
58
+ 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')).
59
+
60
+ evidence_chain(inc900,[payment_api_db_timeout,primary_db_unhealthy,primary_db_disk_100_percent,auth_service_healthy,replica_db_healthy]):-recommended_action(inc900,_).
61
+
62
+ 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).
63
+ 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).
64
+ 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).
65
+
66
+ write_results:-result_rdf(S,P,O,G),write_term(rdf(S,P,O,G),[quoted(true)]),write('.'),nl,fail.
67
+ write_results.
68
+ :- set_prolog_flag(unknown, fail).
@@ -0,0 +1,19 @@
1
+ VERSION "1.2"
2
+
3
+ <https://example.org/supply-chain/service/checkout-prod> <https://example.org/vocab/rootComponent> <https://example.org/supply-chain/component/shop-app> <https://example.org/supply-chain/graph/sbom> .
4
+ <https://example.org/supply-chain/component/shop-app> <https://example.org/vocab/dependsOn> <https://example.org/supply-chain/component/payments-sdk> <https://example.org/supply-chain/graph/sbom> .
5
+ <https://example.org/supply-chain/component/payments-sdk> <https://example.org/vocab/dependsOn> <https://example.org/supply-chain/component/crypto-wrapper> <https://example.org/supply-chain/graph/sbom> .
6
+ <https://example.org/supply-chain/component/crypto-wrapper> <https://example.org/vocab/dependsOn> <https://example.org/supply-chain/component/openssl-3.0.12> <https://example.org/supply-chain/graph/sbom> .
7
+ <https://example.org/supply-chain/component/shop-app> <https://example.org/vocab/dependsOn> <https://example.org/supply-chain/component/log-agent> <https://example.org/supply-chain/graph/sbom> .
8
+ <https://example.org/supply-chain/component/log-agent> <https://example.org/vocab/dependsOn> <https://example.org/supply-chain/component/log-core-2.1> <https://example.org/supply-chain/graph/sbom> .
9
+ <https://example.org/supply-chain/component/openssl-3.0.12> <https://example.org/vocab/affectedBy> <https://example.org/supply-chain/cve/CVE-2026-7777> <https://example.org/supply-chain/graph/vulnerabilities> .
10
+ <https://example.org/supply-chain/cve/CVE-2026-7777> <https://example.org/vocab/severityScore> "98"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/supply-chain/graph/vulnerabilities> .
11
+ <https://example.org/supply-chain/cve/CVE-2026-7777> <https://example.org/vocab/fixedComponent> <https://example.org/supply-chain/component/openssl-3.0.14> <https://example.org/supply-chain/graph/vulnerabilities> .
12
+ <https://example.org/supply-chain/component/log-core-2.1> <https://example.org/vocab/affectedBy> <https://example.org/supply-chain/cve/CVE-2026-2222> <https://example.org/supply-chain/graph/vulnerabilities> .
13
+ <https://example.org/supply-chain/cve/CVE-2026-2222> <https://example.org/vocab/severityScore> "54"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/supply-chain/graph/vulnerabilities> .
14
+ <https://example.org/supply-chain/cve/CVE-2026-2222> <https://example.org/vocab/fixedComponent> <https://example.org/supply-chain/component/log-core-2.2> <https://example.org/supply-chain/graph/vulnerabilities> .
15
+ <https://example.org/supply-chain/service/checkout-prod> <https://example.org/vocab/criticalService> <https://example.org/supply-chain/value/yes> <https://example.org/supply-chain/graph/policy> .
16
+ <https://example.org/supply-chain/service/checkout-prod> <https://example.org/vocab/currentDate> "20260828"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/supply-chain/graph/policy> .
17
+ <https://example.org/supply-chain/waiver/logging> <https://example.org/vocab/waivesForService> <https://example.org/supply-chain/service/checkout-prod> <https://example.org/supply-chain/graph/policy> .
18
+ <https://example.org/supply-chain/waiver/logging> <https://example.org/vocab/waivesVulnerability> <https://example.org/supply-chain/cve/CVE-2026-2222> <https://example.org/supply-chain/graph/policy> .
19
+ <https://example.org/supply-chain/waiver/logging> <https://example.org/vocab/expiresOn> "20261231"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/supply-chain/graph/policy> .
@@ -0,0 +1,5 @@
1
+ VERSION "1.2"
2
+
3
+ <https://example.org/supply-chain/service/checkout-prod> <https://example.org/vocab/deploymentDecision> <https://example.org/supply-chain/decision/block> <https://example.org/supply-chain/graph/derived> .
4
+ <https://example.org/supply-chain/service/checkout-prod> <https://example.org/vocab/exposedTo> <https://example.org/supply-chain/cve/CVE-2026-7777> <https://example.org/supply-chain/graph/derived> .
5
+ <https://example.org/supply-chain/component/openssl-3.0.12> <https://example.org/vocab/upgradeTo> <https://example.org/supply-chain/component/openssl-3.0.14> <https://example.org/supply-chain/graph/derived> .
@@ -0,0 +1,3 @@
1
+ rdf(iri('https://example.org/supply-chain/service/checkout-prod'),iri('https://example.org/vocab/deploymentDecision'),iri('https://example.org/supply-chain/decision/block'),iri('https://example.org/supply-chain/graph/derived')).
2
+ rdf(iri('https://example.org/supply-chain/service/checkout-prod'),iri('https://example.org/vocab/exposedTo'),iri('https://example.org/supply-chain/cve/CVE-2026-7777'),iri('https://example.org/supply-chain/graph/derived')).
3
+ rdf(iri('https://example.org/supply-chain/component/openssl-3.0.12'),iri('https://example.org/vocab/upgradeTo'),iri('https://example.org/supply-chain/component/openssl-3.0.14'),iri('https://example.org/supply-chain/graph/derived')).