eyeling 1.24.0 → 1.24.2

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 (165) hide show
  1. package/HANDBOOK.md +98 -0
  2. package/README.md +4 -4
  3. package/dist/browser/eyeling.browser.js +103 -0
  4. package/eyeling.js +103 -0
  5. package/lib/lexer.js +103 -0
  6. package/package.json +1 -1
  7. package/see/README.md +13 -11
  8. package/see/examples/_see.js +33 -2
  9. package/see/examples/age.js +37 -11
  10. package/see/examples/annotation.js +37 -11
  11. package/see/examples/backward.js +37 -11
  12. package/see/examples/backward_recursion.js +37 -11
  13. package/see/examples/bayes_diagnosis.js +37 -11
  14. package/see/examples/bayes_therapy.js +37 -11
  15. package/see/examples/bmi.js +37 -11
  16. package/see/examples/builtin_coverage.js +37 -11
  17. package/see/examples/collection.js +37 -11
  18. package/see/examples/complex.js +37 -11
  19. package/see/examples/complex_matrix_stability.js +37 -11
  20. package/see/examples/composition_of_injective_functions_is_injective.js +37 -11
  21. package/see/examples/control_system.js +37 -11
  22. package/see/examples/crypto_builtins_tests.js +37 -11
  23. package/see/examples/delfour.js +37 -11
  24. package/see/examples/digital_product_passport.js +37 -11
  25. package/see/examples/dijkstra.js +37 -11
  26. package/see/examples/dijkstra_risk_path.js +37 -11
  27. package/see/examples/doc/age.md +1 -1
  28. package/see/examples/doc/annotation.md +1 -1
  29. package/see/examples/doc/backward.md +1 -1
  30. package/see/examples/doc/backward_recursion.md +1 -1
  31. package/see/examples/doc/bayes_diagnosis.md +1 -1
  32. package/see/examples/doc/bayes_therapy.md +1 -1
  33. package/see/examples/doc/bmi.md +1 -1
  34. package/see/examples/doc/builtin_coverage.md +1 -1
  35. package/see/examples/doc/collection.md +1 -1
  36. package/see/examples/doc/complex.md +1 -1
  37. package/see/examples/doc/complex_matrix_stability.md +1 -1
  38. package/see/examples/doc/composition_of_injective_functions_is_injective.md +1 -1
  39. package/see/examples/doc/control_system.md +1 -1
  40. package/see/examples/doc/crypto_builtins_tests.md +1 -1
  41. package/see/examples/doc/delfour.md +1 -1
  42. package/see/examples/doc/digital_product_passport.md +1 -1
  43. package/see/examples/doc/dijkstra.md +1 -1
  44. package/see/examples/doc/dijkstra_risk_path.md +1 -1
  45. package/see/examples/doc/dog.md +1 -1
  46. package/see/examples/doc/eco_route_insight.md +1 -1
  47. package/see/examples/doc/equals.md +1 -1
  48. package/see/examples/doc/equivalence_classes_overlap_implies_same_class.md +1 -1
  49. package/see/examples/doc/euler_identity.md +1 -1
  50. package/see/examples/doc/ev_roundtrip_planner.md +1 -1
  51. package/see/examples/doc/existential_rule.md +1 -1
  52. package/see/examples/doc/expression_eval.md +1 -1
  53. package/see/examples/doc/family_cousins.md +1 -1
  54. package/see/examples/doc/fastpow.md +1 -1
  55. package/see/examples/doc/fibonacci.md +1 -1
  56. package/see/examples/doc/french_cities.md +1 -1
  57. package/see/examples/doc/fundamental_theorem_arithmetic.md +1 -1
  58. package/see/examples/doc/genetic_knapsack_selection.md +1 -1
  59. package/see/examples/doc/goldbach_1000.md +1 -1
  60. package/see/examples/doc/good_cobbler.md +1 -1
  61. package/see/examples/doc/gps.md +1 -1
  62. package/see/examples/doc/gray_code_counter.md +1 -1
  63. package/see/examples/doc/greatest_lower_bound_uniqueness.md +1 -1
  64. package/see/examples/doc/group_inverse_uniqueness.md +1 -1
  65. package/see/examples/doc/hadamard_approx.md +1 -1
  66. package/see/examples/doc/hanoi.md +1 -1
  67. package/see/examples/doc/odrl_dpv_risk_ranked.md +1 -1
  68. package/see/examples/doc/path_discovery.md +1 -1
  69. package/see/examples/doc/rc_discharge_envelope.md +1 -1
  70. package/see/examples/doc/rdf_message_flow.md +1 -1
  71. package/see/examples/doc/rdf_messages.md +1 -1
  72. package/see/examples/doc/school_placement_audit.md +1 -1
  73. package/see/examples/doc/smoke_arithmetic.md +1 -1
  74. package/see/examples/doc/socrates.md +1 -1
  75. package/see/examples/doc/triple_terms.md +26 -0
  76. package/see/examples/doc/wind_turbine.md +1 -1
  77. package/see/examples/doc/witch.md +1 -1
  78. package/see/examples/dog.js +37 -11
  79. package/see/examples/eco_route_insight.js +37 -11
  80. package/see/examples/equals.js +37 -11
  81. package/see/examples/equivalence_classes_overlap_implies_same_class.js +37 -11
  82. package/see/examples/euler_identity.js +37 -11
  83. package/see/examples/ev_roundtrip_planner.js +37 -11
  84. package/see/examples/existential_rule.js +37 -11
  85. package/see/examples/expression_eval.js +37 -11
  86. package/see/examples/family_cousins.js +37 -11
  87. package/see/examples/fastpow.js +37 -11
  88. package/see/examples/fibonacci.js +37 -11
  89. package/see/examples/french_cities.js +37 -11
  90. package/see/examples/fundamental_theorem_arithmetic.js +37 -11
  91. package/see/examples/genetic_knapsack_selection.js +37 -11
  92. package/see/examples/goldbach_1000.js +37 -11
  93. package/see/examples/good_cobbler.js +37 -11
  94. package/see/examples/gps.js +37 -11
  95. package/see/examples/gray_code_counter.js +37 -11
  96. package/see/examples/greatest_lower_bound_uniqueness.js +37 -11
  97. package/see/examples/group_inverse_uniqueness.js +37 -11
  98. package/see/examples/hadamard_approx.js +37 -11
  99. package/see/examples/hanoi.js +37 -11
  100. package/see/examples/input/triple_terms.trig +28 -0
  101. package/see/examples/n3/triple_terms.n3 +23 -0
  102. package/see/examples/odrl_dpv_risk_ranked.js +37 -11
  103. package/see/examples/output/age.md +3 -3
  104. package/see/examples/output/annotation.md +4 -4
  105. package/see/examples/output/backward.md +3 -3
  106. package/see/examples/output/backward_recursion.md +3 -3
  107. package/see/examples/output/bayes_diagnosis.md +1 -1
  108. package/see/examples/output/bayes_therapy.md +1 -1
  109. package/see/examples/output/bmi.md +1 -1
  110. package/see/examples/output/builtin_coverage.md +3 -3
  111. package/see/examples/output/collection.md +3 -3
  112. package/see/examples/output/complex.md +4 -4
  113. package/see/examples/output/complex_matrix_stability.md +1 -1
  114. package/see/examples/output/composition_of_injective_functions_is_injective.md +3 -3
  115. package/see/examples/output/control_system.md +3 -3
  116. package/see/examples/output/crypto_builtins_tests.md +3 -3
  117. package/see/examples/output/delfour.md +1 -1
  118. package/see/examples/output/digital_product_passport.md +1 -1
  119. package/see/examples/output/dijkstra.md +3 -3
  120. package/see/examples/output/dijkstra_risk_path.md +1 -1
  121. package/see/examples/output/dog.md +3 -3
  122. package/see/examples/output/eco_route_insight.md +1 -1
  123. package/see/examples/output/equals.md +3 -3
  124. package/see/examples/output/equivalence_classes_overlap_implies_same_class.md +3 -3
  125. package/see/examples/output/euler_identity.md +3 -3
  126. package/see/examples/output/ev_roundtrip_planner.md +1 -1
  127. package/see/examples/output/existential_rule.md +3 -3
  128. package/see/examples/output/expression_eval.md +3 -3
  129. package/see/examples/output/family_cousins.md +3 -3
  130. package/see/examples/output/fastpow.md +1 -1
  131. package/see/examples/output/fibonacci.md +1 -1
  132. package/see/examples/output/french_cities.md +3 -3
  133. package/see/examples/output/fundamental_theorem_arithmetic.md +1 -1
  134. package/see/examples/output/genetic_knapsack_selection.md +1 -1
  135. package/see/examples/output/goldbach_1000.md +1 -1
  136. package/see/examples/output/good_cobbler.md +4 -4
  137. package/see/examples/output/gps.md +1 -1
  138. package/see/examples/output/gray_code_counter.md +1 -1
  139. package/see/examples/output/greatest_lower_bound_uniqueness.md +3 -3
  140. package/see/examples/output/group_inverse_uniqueness.md +3 -3
  141. package/see/examples/output/hadamard_approx.md +3 -3
  142. package/see/examples/output/hanoi.md +3 -3
  143. package/see/examples/output/odrl_dpv_risk_ranked.md +3 -3
  144. package/see/examples/output/path_discovery.md +3 -3
  145. package/see/examples/output/rc_discharge_envelope.md +1 -1
  146. package/see/examples/output/rdf_message_flow.md +1 -1
  147. package/see/examples/output/rdf_messages.md +1 -1
  148. package/see/examples/output/school_placement_audit.md +1 -1
  149. package/see/examples/output/smoke_arithmetic.md +1 -1
  150. package/see/examples/output/socrates.md +3 -3
  151. package/see/examples/output/triple_terms.md +53 -0
  152. package/see/examples/output/wind_turbine.md +1 -1
  153. package/see/examples/output/witch.md +3 -3
  154. package/see/examples/path_discovery.js +37 -11
  155. package/see/examples/rc_discharge_envelope.js +37 -11
  156. package/see/examples/rdf_message_flow.js +37 -11
  157. package/see/examples/rdf_messages.js +37 -11
  158. package/see/examples/school_placement_audit.js +37 -11
  159. package/see/examples/smoke_arithmetic.js +37 -11
  160. package/see/examples/socrates.js +37 -11
  161. package/see/examples/triple_terms.js +1442 -0
  162. package/see/examples/wind_turbine.js +37 -11
  163. package/see/examples/witch.js +37 -11
  164. package/see/see.js +455 -94
  165. package/test/api.test.js +20 -0
@@ -8,6 +8,7 @@ const crypto = require('crypto');
8
8
 
9
9
  function canonical(term) {
10
10
  if (term.kind === 'list') return ['list', term.items.map(canonical)];
11
+ if (term.kind === 'triple') return ['triple', canonical(term.s), canonical(term.p), canonical(term.o)];
11
12
  if (term.kind === 'formula') return ['formula', term.atoms.map((a) => [canonical(a.s), canonical(a.p), canonical(a.o)])];
12
13
  return [term.kind, term.value];
13
14
  }
@@ -17,6 +18,7 @@ function compoundIndexKey() { return Array.from(arguments).map(termIndexKey).joi
17
18
  function termIsConcrete(t) {
18
19
  if (!t || t.kind === 'var') return false;
19
20
  if (t.kind === 'list') return t.items.every(termIsConcrete);
21
+ if (t.kind === 'triple') return termIsConcrete(t.s) && termIsConcrete(t.p) && termIsConcrete(t.o);
20
22
  if (t.kind === 'formula') return t.atoms.every((a) => termIsConcrete(a.s) && termIsConcrete(a.p) && termIsConcrete(a.o));
21
23
  return true;
22
24
  }
@@ -32,6 +34,7 @@ function primitive(t) {
32
34
  if (t.kind === 'iri') return t.value.replace(/^:/, '');
33
35
  if (t.kind === 'blank') return t.value;
34
36
  if (t.kind === 'list') return t.items.map(primitive);
37
+ if (t.kind === 'triple') return termToN3(t);
35
38
  if (t.kind === 'formula') return termToN3(t);
36
39
  return undefined;
37
40
  }
@@ -52,6 +55,7 @@ function termToN3(t) {
52
55
  if (t.kind === 'var') return '?' + t.value;
53
56
  if (t.kind === 'blank') return t.value.startsWith('_:') ? t.value : '_:' + t.value.replace(/^_+/, '');
54
57
  if (t.kind === 'list') return '(' + t.items.map(termToN3).join(' ') + ')';
58
+ if (t.kind === 'triple') return '<<( ' + termToN3(t.s) + ' ' + termToN3(t.p) + ' ' + termToN3(t.o) + ' )>>';
55
59
  if (t.kind === 'formula') return '{ ' + t.atoms.map(atomToN3).join(' . ') + ' }';
56
60
  return String(t.value ?? t);
57
61
  }
@@ -74,6 +78,7 @@ function resolve(term, env, seen = new Set()) {
74
78
  return resolve(env[term.value], env, seen);
75
79
  }
76
80
  if (term.kind === 'list') return list(term.items.map((item) => resolve(item, env, seen)));
81
+ if (term.kind === 'triple') return { kind: 'triple', s: resolve(term.s, env), p: resolve(term.p, env), o: resolve(term.o, env) };
77
82
  if (term.kind === 'formula') return { kind: 'formula', atoms: term.atoms.map((a) => ({ s: resolve(a.s, env), p: resolve(a.p, env), o: resolve(a.o, env) })) };
78
83
  return term;
79
84
  }
@@ -91,6 +96,14 @@ function unify(a, b, env) {
91
96
  }
92
97
  return out;
93
98
  }
99
+ if (a.kind === 'triple' || b.kind === 'triple') {
100
+ if (a.kind !== 'triple' || b.kind !== 'triple') return null;
101
+ let out = unify(a.s, b.s, env);
102
+ if (!out) return null;
103
+ out = unify(a.p, b.p, out);
104
+ if (!out) return null;
105
+ return unify(a.o, b.o, out);
106
+ }
94
107
  return deepEqual(a, b) ? env : null;
95
108
  }
96
109
  function bind(pattern, value, env) { return unify(pattern, value, env); }
@@ -106,6 +119,7 @@ function termIsGround(t, env) {
106
119
  const r = resolve(t, env);
107
120
  if (r.kind === 'var') return false;
108
121
  if (r.kind === 'list') return r.items.every((item) => termIsGround(item, env));
122
+ if (r.kind === 'triple') return termIsGround(r.s, env) && termIsGround(r.p, env) && termIsGround(r.o, env);
109
123
  if (r.kind === 'formula') return r.atoms.every((atom) => atomIsGround(atom, env));
110
124
  return true;
111
125
  }
@@ -665,6 +679,7 @@ function instantiate(term, env, ruleId) {
665
679
  }
666
680
  if (term.kind === 'blank') return blank('_:r' + ruleId + '_' + envSignature(env) + '_' + term.value.replace(/^_/, ''));
667
681
  if (term.kind === 'list') return list(term.items.map((item) => instantiate(item, env, ruleId)));
682
+ if (term.kind === 'triple') return { kind: 'triple', s: instantiate(term.s, env, ruleId), p: instantiate(term.p, env, ruleId), o: instantiate(term.o, env, ruleId) };
668
683
  if (term.kind === 'formula') return { kind: 'formula', atoms: term.atoms.map((a) => ({ s: instantiate(a.s, env, ruleId), p: instantiate(a.p, env, ruleId), o: instantiate(a.o, env, ruleId) })) };
669
684
  return cloneTerm(term);
670
685
  }
@@ -1040,19 +1055,19 @@ function renderStructuredOutput({ title, graph, queries = [], rules = [], initia
1040
1055
  const lines = [];
1041
1056
  lines.push('# ' + title);
1042
1057
  lines.push('');
1043
- lines.push('## Insight');
1058
+ lines.push('## Entailment');
1044
1059
  if (mode === 'query') {
1045
1060
  lines.push('The compiled query selected ' + selected.length + ' fact(s) after the rule closure was computed.');
1046
1061
  } else if (mode === 'formula') {
1047
- lines.push('The derivation produced ' + selected.length + ' formula-valued conclusion(s).');
1062
+ lines.push('The derivation produced ' + selected.length + ' formula-valued entailment(s).');
1048
1063
  } else {
1049
1064
  lines.push('The derivation produced ' + derived.length + ' new fact(s) from ' + initialFacts.length + ' stated fact(s).');
1050
1065
  }
1051
- if (keyFact) lines.push('Main conclusion: **' + factSentence(keyFact) + '**');
1066
+ if (keyFact) lines.push('Main entailment: **' + factSentence(keyFact) + '**');
1052
1067
  const bullets = selected.slice(-6).reverse();
1053
1068
  if (bullets.length) {
1054
1069
  lines.push('');
1055
- lines.push('Selected conclusions:');
1070
+ lines.push('Selected entailments:');
1056
1071
  for (const fact of bullets) lines.push('- ' + codeFact(fact));
1057
1072
  }
1058
1073
  lines.push('');
@@ -1114,15 +1129,15 @@ function dedupeExplanationHeadings(text) {
1114
1129
  function normalizePublicReport(markdown, title) {
1115
1130
  let text = String(markdown || '').trimEnd();
1116
1131
  if (!/^\s*#\s+/m.test(text)) text = '# ' + title + '\n\n' + text;
1117
- if (!/^##\s+Insight\s*$/mi.test(text)) {
1118
- text = text.replace(/^(#\s+[^\n]+\n*)/, '$1\n## Insight\n');
1132
+ if (!/^##\s+Entailment\s*$/mi.test(text)) {
1133
+ text = text.replace(/^(#\s+[^\n]+\n*)/, '$1\n## Entailment\n');
1119
1134
  }
1120
1135
  if (!/^##\s+Explanation\s*$/mi.test(text)) {
1121
1136
  text += '\n\n## Explanation\nNo additional explanation was provided by the generated output.';
1122
1137
  }
1123
1138
  text = text.replace(/^##\s+([^\n]+?)\s*$/gm, (line, heading) => {
1124
1139
  const normalized = heading.trim().toLowerCase();
1125
- if (normalized === 'insight' || normalized === 'explanation') return '## ' + (normalized === 'insight' ? 'Insight' : 'Explanation');
1140
+ if (normalized === 'insight' || normalized === 'conclusion' || normalized === 'entailment' || normalized === 'explanation') return '## ' + (normalized === 'explanation' ? 'Explanation' : 'Entailment');
1126
1141
  return '**' + heading.trim() + '**';
1127
1142
  });
1128
1143
  text = dedupeExplanationHeadings(text);
@@ -1131,13 +1146,13 @@ function normalizePublicReport(markdown, title) {
1131
1146
  function markdownize(raw, title) {
1132
1147
  let text = String(raw || '');
1133
1148
  text = text
1134
- .replace(/===\s*Answer\s*===/g, '## Insight')
1149
+ .replace(/===\s*Answer\s*===/g, '## Entailment')
1135
1150
  .replace(/===\s*Reason\s+Why\s*===/gi, '## Explanation')
1136
1151
  .replace(/===\s*Explanation\s*===/gi, '## Explanation')
1137
1152
  .replace(/===\s*([^=]+?)\s*===/g, (_, h) => '**' + h.trim() + '**');
1138
1153
  text = text.replace(/^C(\d+)\s+OK\s*-\s*/gm, 'C$1: ');
1139
1154
  text = dedupeExplanationHeadings(text);
1140
- if (!text.trim()) text = '## Insight\nNo log:outputString facts were derived.\n\n## Explanation\nThe compiled derivation did not produce authored report text.';
1155
+ if (!text.trim()) text = '## Entailment\nNo log:outputString facts were derived.\n\n## Explanation\nThe compiled derivation did not produce authored report text.';
1141
1156
  return normalizePublicReport(text, title);
1142
1157
  }
1143
1158
  function authoredSupportAppendix(graph, queries, rules, initialFacts, trace) {
@@ -5003,7 +5018,7 @@ const QUERIES = [
5003
5018
  ]
5004
5019
  }
5005
5020
  ];
5006
- const DOC_MARKDOWN = "# ODRL + DPV risk assessment with ranked, explainable output.\n\nGenerated by `see.js` from a Notation3 source file.\n\nWhat this file does\n- Models an agreement as an ODRL policy (odrl:Policy) containing permissions,\nprohibitions, duties, and constraints. ODRL is expressive enough to encode the\nnormative “may/must/must-not” structure of TOS clauses as RDF.\n- Links each ODRL rule to a clause resource (:Clause) to keep human-readable text\nwhile preserving machine-readable structure for reasoning.\n- Uses N3 rules with log:includes / log:notIncludes to detect missing safeguards\n(e.g., missing notice constraints, missing inform duties, missing consent constraints).\n- Generates DPV risks (dpv:Risk) and classifies them using DPV-RISK concepts:\nrisk:hasRiskSource, dpv:hasConsequence, dpv:hasImpact, dpv:hasSeverity, dpv:hasRiskLevel.\n- Produces mitigations as dpv:RiskMitigationMeasure resources and attaches them\nto risks with dpv:isMitigatedByMeasure.\n- Computes a numeric score for each risk and prints a ranked, explainable report.\nRanking / output\n- Output strings are emitted as log:outputString triples.\n- When running with Eyeling “strings” mode (-r), strings are printed in deterministic\norder based on their subject key. The program encodes ranking via an “inverse score”\nkey (e.g., 1000 - score) so higher-risk items appear first.\nReferences\n- N3 spec: https://w3c.github.io/N3/spec/\n- Eyeling builtins: https://eyereasoner.github.io/eyeling/HANDBOOK#ch11\n- ODRL vocab: https://www.w3.org/TR/odrl-vocab/\n- DPV risk module: https://dev.dpvcg.org/dpv/modules/risk\n- DPV-RISK: https://w3id.org/dpv/risk\n\n## Compilation summary\n\n- Example name: `odrl_dpv_risk_ranked`\n- Input facts emitted: 38\n- Forward rules compiled: 9\n- Backward predicate rules compiled: 0\n- Fuses compiled: 0\n- Predicate count: 32\n\n## Built-ins used\n\n- `log:includes`\n- `log:notIncludes`\n- `log:outputString`\n- `math:difference`\n- `math:greaterThan`\n- `math:lessThan`\n- `math:notLessThan`\n- `math:sum`\n- `string:format`\n\n## Runtime model\n\nThe generated `examples/odrl_dpv_risk_ranked.js` is a specialized JavaScript derivation program. For ordinary sources, `see.js` emits the source facts as `examples/input/odrl_dpv_risk_ranked.trig`. For rules-only sources, generation can reuse an existing external evidence file such as `examples/input/odrl-dpv-risk-ranked.trig` or `examples/input/odrl_dpv_risk_ranked.trig`. The runner reads that TriG evidence directly and performs a local fixpoint derivation; it does not parse the program source or call an external reasoner.\n\n## Output model\n\nRunning `node examples/odrl_dpv_risk_ranked.js` produces a SEE-style Markdown report with an **Insight** section, an **Explanation** section, and a **Formal TriG Output** section containing the selected derived/query facts.\n";
5021
+ const DOC_MARKDOWN = "# ODRL + DPV risk assessment with ranked, explainable output.\n\nGenerated by `see.js` from a Notation3 source file.\n\nWhat this file does\n- Models an agreement as an ODRL policy (odrl:Policy) containing permissions,\nprohibitions, duties, and constraints. ODRL is expressive enough to encode the\nnormative “may/must/must-not” structure of TOS clauses as RDF.\n- Links each ODRL rule to a clause resource (:Clause) to keep human-readable text\nwhile preserving machine-readable structure for reasoning.\n- Uses N3 rules with log:includes / log:notIncludes to detect missing safeguards\n(e.g., missing notice constraints, missing inform duties, missing consent constraints).\n- Generates DPV risks (dpv:Risk) and classifies them using DPV-RISK concepts:\nrisk:hasRiskSource, dpv:hasConsequence, dpv:hasImpact, dpv:hasSeverity, dpv:hasRiskLevel.\n- Produces mitigations as dpv:RiskMitigationMeasure resources and attaches them\nto risks with dpv:isMitigatedByMeasure.\n- Computes a numeric score for each risk and prints a ranked, explainable report.\nRanking / output\n- Output strings are emitted as log:outputString triples.\n- When running with Eyeling “strings” mode (-r), strings are printed in deterministic\norder based on their subject key. The program encodes ranking via an “inverse score”\nkey (e.g., 1000 - score) so higher-risk items appear first.\nReferences\n- N3 spec: https://w3c.github.io/N3/spec/\n- Eyeling builtins: https://eyereasoner.github.io/eyeling/HANDBOOK#ch11\n- ODRL vocab: https://www.w3.org/TR/odrl-vocab/\n- DPV risk module: https://dev.dpvcg.org/dpv/modules/risk\n- DPV-RISK: https://w3id.org/dpv/risk\n\n## Compilation summary\n\n- Example name: `odrl_dpv_risk_ranked`\n- Input facts emitted: 38\n- Forward rules compiled: 9\n- Backward predicate rules compiled: 0\n- Fuses compiled: 0\n- Predicate count: 32\n\n## Built-ins used\n\n- `log:includes`\n- `log:notIncludes`\n- `log:outputString`\n- `math:difference`\n- `math:greaterThan`\n- `math:lessThan`\n- `math:notLessThan`\n- `math:sum`\n- `string:format`\n\n## Runtime model\n\nThe generated `examples/odrl_dpv_risk_ranked.js` is a specialized JavaScript derivation program. For ordinary sources, `see.js` emits the source facts as `examples/input/odrl_dpv_risk_ranked.trig`. For rules-only sources, generation can reuse an existing external evidence file such as `examples/input/odrl-dpv-risk-ranked.trig` or `examples/input/odrl_dpv_risk_ranked.trig`. The runner reads that TriG evidence directly and performs a local fixpoint derivation; it does not parse the program source or call an external reasoner.\n\n## Output model\n\nRunning `node examples/odrl_dpv_risk_ranked.js` produces a SEE-style Markdown report with an **Entailment** section, an **Explanation** section, and a **Formal TriG Output** section containing the selected derived/query facts.\n";
5007
5022
  function seeMetadata(data) { return (data && data.__see) || {}; }
5008
5023
  function trustedDerivation(data) { const meta = seeMetadata(data); const facts = data && Array.isArray(data.facts) ? data.facts : []; const expectedFacts = EXPECTED_INPUT_FACTS || Number(meta.InputFacts || 0); if (meta.SourceSHA256 && meta.SourceSHA256 !== "e3360556d6e82bda9f502d362cc110e2cd681608ae1388cf8071660f6fbe6200") throw new Error('input evidence does not match the N3 source compiled into this example'); const result = saturate(facts, RULES); const rawOutput = renderRawOutput(result.graph, QUERIES, RULES, facts); fail('Compiled N3 derivation failed', { 'input evidence metadata is present and matches compiled source': meta.SourceSHA256 === "e3360556d6e82bda9f502d362cc110e2cd681608ae1388cf8071660f6fbe6200", 'input evidence facts were loaded': expectedFacts > 0 ? facts.length === expectedFacts : facts.length >= 0, 'compiled rules were loaded': RULES.length === 9, 'compiled query directives were loaded': QUERIES.length === 3, 'a derivation fixpoint was reached': result.graph.facts.length >= facts.length, 'query or output facts were produced': rawOutput.length > 0 }); return { ...result, rawOutput, inputFacts: facts }; }
5009
5024
  function snapshotMarkdown(markdown) { return markdown.split(/\n/).map((line) => line ? line + ' \n' : '\n').join(''); }
@@ -5037,6 +5052,16 @@ function formalOutputFacts(graph, queries, rules, initialFacts) {
5037
5052
  }
5038
5053
  return out;
5039
5054
  }
5055
+ function termHasTripleTerm(term) {
5056
+ if (!term) return false;
5057
+ if (term.kind === 'triple') return true;
5058
+ if (term.kind === 'list') return term.items.some(termHasTripleTerm);
5059
+ if (term.kind === 'formula') return term.atoms.some(atomHasTripleTerm);
5060
+ return false;
5061
+ }
5062
+ function atomHasTripleTerm(atom) { return termHasTripleTerm(atom.s) || termHasTripleTerm(atom.p) || termHasTripleTerm(atom.o); }
5063
+ function factsHaveTripleTerms(facts) { return (facts || []).some(atomHasTripleTerm); }
5064
+ function trigHasVersion12(trig) { return /^s*(?:@version|VERSION)s+["']1.2["']/mi.test(String(trig || '')); }
5040
5065
  function trigGraphBlock(label, atoms) {
5041
5066
  const lines = [label + ' {'];
5042
5067
  for (const atom of atoms || []) lines.push(' ' + atomToN3(atom) + ' .');
@@ -5084,7 +5109,8 @@ function formalOutputToTrig(facts, trig) {
5084
5109
  const prefixes = prefixLinesFromTrig(trig);
5085
5110
  if (state.needOutPrefix && !prefixes.some((line) => line.toLowerCase().startsWith('@prefix out:'))) prefixes.push('@prefix out: <https://example.org/see/output#> .');
5086
5111
  const nl = String.fromCharCode(10);
5087
- return prefixes.join(nl) + nl + nl + body.join(nl);
5112
+ const version = factsHaveTripleTerms(facts) ? 'VERSION "1.2"' + nl + nl : '';
5113
+ return version + prefixes.join(nl) + nl + nl + body.join(nl);
5088
5114
  }
5089
5115
  function appendFormalTrigOutput(markdown, graph, queries, rules, initialFacts, data) {
5090
5116
  const trig = formalOutputToTrig(formalOutputFacts(graph, queries, rules, initialFacts), data && data.trig);
@@ -1,10 +1,10 @@
1
1
  # Age checker
2
2
 
3
- ## Insight
3
+ ## Entailment
4
4
  The compiled query selected 1 fact(s) after the rule closure was computed.
5
- Main conclusion: **:test is true.**
5
+ Main entailment: **:test is true.**
6
6
 
7
- Selected conclusions:
7
+ Selected entailments:
8
8
  - :test :is true .
9
9
 
10
10
  ## Explanation
@@ -1,10 +1,10 @@
1
1
  # Annotation
2
2
 
3
- ## Insight
4
- The derivation produced 1 formula-valued conclusion(s).
5
- Main conclusion: **:t log:nameOf { :a :name "Alice" }.**
3
+ ## Entailment
4
+ The derivation produced 1 formula-valued entailment(s).
5
+ Main entailment: **:t log:nameOf { :a :name "Alice" }.**
6
6
 
7
- Selected conclusions:
7
+ Selected entailments:
8
8
  - :t log:nameOf { :a :name "Alice" } .
9
9
 
10
10
  ## Explanation
@@ -1,10 +1,10 @@
1
1
  # Backward rule example
2
2
 
3
- ## Insight
3
+ ## Entailment
4
4
  The derivation produced 1 new fact(s) from 0 stated fact(s).
5
- Main conclusion: **5 :isIndeedMoreInterestingThan 3.**
5
+ Main entailment: **5 :isIndeedMoreInterestingThan 3.**
6
6
 
7
- Selected conclusions:
7
+ Selected entailments:
8
8
  - 5 :isIndeedMoreInterestingThan 3 .
9
9
 
10
10
  ## Explanation
@@ -1,10 +1,10 @@
1
1
  # Backward recursion coverage
2
2
 
3
- ## Insight
3
+ ## Entailment
4
4
  The compiled query selected 2 fact(s) after the rule closure was computed.
5
- Main conclusion: **:a :reaches :c.**
5
+ Main entailment: **:a :reaches :c.**
6
6
 
7
- Selected conclusions:
7
+ Selected entailments:
8
8
  - :a :reaches :c .
9
9
  - :a :reaches :b .
10
10
 
@@ -1,6 +1,6 @@
1
1
  # Bayes Diagnosis
2
2
 
3
- ## Insight
3
+ ## Entailment
4
4
  The most likely disease is COVID-19 (posterior = 0.941209).
5
5
 
6
6
  Full posterior distribution:
@@ -1,6 +1,6 @@
1
1
  # Bayes Therapy
2
2
 
3
- ## Insight
3
+ ## Entailment
4
4
  Recommended therapy: Paxlovid (utility = 3.585174).
5
5
  expected success : 0.388517
6
6
  adverse probability : 0.100000
@@ -1,6 +1,6 @@
1
1
  # BMI — Body Mass Index example.
2
2
 
3
- ## Insight
3
+ ## Entailment
4
4
  BMI = 22.72
5
5
  Category = Normal
6
6
  At height 178 cm, a healthy-weight range is about 58.6–78.9 kg (BMI 18.5–24.9).
@@ -1,10 +1,10 @@
1
1
  # Builtin coverage smoke
2
2
 
3
- ## Insight
3
+ ## Entailment
4
4
  The compiled query selected 29 fact(s) after the rule closure was computed.
5
- Main conclusion: **:assurance :member "c".**
5
+ Main entailment: **:assurance :member "c".**
6
6
 
7
- Selected conclusions:
7
+ Selected entailments:
8
8
  - :assurance :member "c" .
9
9
  - :assurance :member "b" .
10
10
  - :assurance :formula { :x :p :y . :a :b :c } .
@@ -1,10 +1,10 @@
1
1
  # Collection
2
2
 
3
- ## Insight
3
+ ## Entailment
4
4
  The derivation produced 0 new fact(s) from 2 stated fact(s).
5
- Main conclusion: **_:b2 :p :q.**
5
+ Main entailment: **_:b2 :p :q.**
6
6
 
7
- Selected conclusions:
7
+ Selected entailments:
8
8
  - _:b2 :p :q .
9
9
  - (1 _:b2 (2)) :p2 :q2 .
10
10
 
@@ -1,10 +1,10 @@
1
1
  # Complex numbers
2
2
 
3
- ## Insight
4
- The derivation produced 1 formula-valued conclusion(s).
5
- Main conclusion: **:test is { ((-1 0) (0.5 0)) complex:exponentiation (-3.49148133884313e-15 1) . ((2.71828182845905 0) (0 3.14159265358979)) complex:exponentiation (-1 3.23108914886517e-15) . ((0 1) (0 1)) complex:exponentiation (0.207879576350761 0) . ((2.71828182845905 0) (-1.57079632679 0)) complex:exponentiation (0.207879576351779 0) . (2 0) complex:asin (1.5707963267949 1.31695789692482) . (2 0) complex:acos (0 -1.31695789692482) }.**
3
+ ## Entailment
4
+ The derivation produced 1 formula-valued entailment(s).
5
+ Main entailment: **:test is { ((-1 0) (0.5 0)) complex:exponentiation (-3.49148133884313e-15 1) . ((2.71828182845905 0) (0 3.14159265358979)) complex:exponentiation (-1 3.23108914886517e-15) . ((0 1) (0 1)) complex:exponentiation (0.207879576350761 0) . ((2.71828182845905 0) (-1.57079632679 0)) complex:exponentiation (0.207879576351779 0) . (2 0) complex:asin (1.5707963267949 1.31695789692482) . (2 0) complex:acos (0 -1.31695789692482) }.**
6
6
 
7
- Selected conclusions:
7
+ Selected entailments:
8
8
  - :test :is { ((-1 0) (0.5 0)) complex:exponentiation (-3.49148133884313e-15 1) . ((2.71828182845905 0) (0 3.14159265358979)) complex:exponentiation (-1 3.23108914886517e-15) . ((0 1) (0 1)) complex:exponentiation (0.207879576350761 0) . ((2.71828182845905 0) (-1.57079632679 0)) complex:exponentiation (0.207879576351779 0) . (2 0) complex:asin (1.5707963267949 1.31695789692482) . (2 0) complex:acos (0 -1.31695789692482) } .
9
9
 
10
10
  ## Explanation
@@ -1,6 +1,6 @@
1
1
  # Complex Matrix Stability
2
2
 
3
- ## Insight
3
+ ## Entailment
4
4
  A_unstable = [[(1,1),(0,0)],[(0,0),(2,0)]] has spectral radius 2 and is unstable. A_stable = [[(1,0),(0,0)],[(0,0),(-1,0)]] has spectral radius 1 and is marginally stable. A_damped = [[(0,0),(0,0)],[(0,0),(0,0)]] has spectral radius 0 and is damped.
5
5
 
6
6
  ## Explanation
@@ -1,10 +1,10 @@
1
1
  # Composition of injective functions is injective.
2
2
 
3
- ## Insight
3
+ ## Entailment
4
4
  The compiled query selected 2 fact(s) after the rule closure was computed.
5
- Main conclusion: **:result :sameInputByCompositeInjectivity (:h :b :a).**
5
+ Main entailment: **:result :sameInputByCompositeInjectivity (:h :b :a).**
6
6
 
7
- Selected conclusions:
7
+ Selected entailments:
8
8
  - :result :sameInputByCompositeInjectivity (:h :b :a) .
9
9
  - :result :sameInputByCompositeInjectivity (:h :a :b) .
10
10
 
@@ -1,10 +1,10 @@
1
1
  # Control System
2
2
 
3
- ## Insight
3
+ ## Entailment
4
4
  The compiled query selected 2 fact(s) after the rule closure was computed.
5
- Main conclusion: **:actuator2 :control1 26.08.**
5
+ Main entailment: **:actuator2 :control1 26.08.**
6
6
 
7
- Selected conclusions:
7
+ Selected entailments:
8
8
  - :actuator2 :control1 26.08 .
9
9
  - :actuator1 :control1 39.2734619867828 .
10
10
 
@@ -1,10 +1,10 @@
1
1
  # crypto builtins tests
2
2
 
3
- ## Insight
3
+ ## Entailment
4
4
  The derivation produced 4 new fact(s) from 0 stated fact(s).
5
- Main conclusion: **:ok_crypto_sha512_1 is a :Pass.**
5
+ Main entailment: **:ok_crypto_sha512_1 is a :Pass.**
6
6
 
7
- Selected conclusions:
7
+ Selected entailments:
8
8
  - :ok_crypto_sha512_1 rdf:type :Pass .
9
9
  - :ok_crypto_sha256_1 rdf:type :Pass .
10
10
  - :ok_crypto_md5_1 rdf:type :Pass .
@@ -1,6 +1,6 @@
1
1
  # Delfour
2
2
 
3
- ## Insight
3
+ ## Entailment
4
4
  The scanner is allowed to use a neutral shopping insight and recommends Low-Sugar Tea Biscuits instead of Classic Tea Biscuits.
5
5
  case : delfour
6
6
  decision : Allowed
@@ -1,6 +1,6 @@
1
1
  # Digital Product Passport
2
2
 
3
- ## Insight
3
+ ## Entailment
4
4
  Passport decision : PASS for ACME X1000 SN123.
5
5
  recycled content : 13%
6
6
  lifecycle footprint : 52500 gCO2e
@@ -1,10 +1,10 @@
1
1
  # Dijkstra's algorithm to find the shortest path
2
2
 
3
- ## Insight
3
+ ## Entailment
4
4
  The derivation produced 9 new fact(s) from 9 stated fact(s).
5
- Main conclusion: **(:f :e) :edge 3.**
5
+ Main entailment: **(:f :e) :edge 3.**
6
6
 
7
- Selected conclusions:
7
+ Selected entailments:
8
8
  - (:f :e) :edge 3 .
9
9
  - (:f :d) :edge 6 .
10
10
  - (:e :d) :edge 2 .
@@ -1,6 +1,6 @@
1
1
  # Dijkstra Risk Path
2
2
 
3
- ## Insight
3
+ ## Entailment
4
4
  selected path : ClinicA -> DepotB -> LabD -> HubZ
5
5
  raw cost : 10.00
6
6
  risk sum : 0.55
@@ -1,10 +1,10 @@
1
1
  # Dog license example
2
2
 
3
- ## Insight
3
+ ## Entailment
4
4
  The derivation produced 1 new fact(s) from 7 stated fact(s).
5
- Main conclusion: **:alice :mustHave :dogLicense.**
5
+ Main entailment: **:alice :mustHave :dogLicense.**
6
6
 
7
- Selected conclusions:
7
+ Selected entailments:
8
8
  - :alice :mustHave :dogLicense .
9
9
 
10
10
  ## Explanation
@@ -1,6 +1,6 @@
1
1
  # Eco Route Insight
2
2
 
3
- ## Insight
3
+ ## Entailment
4
4
  insight status : issue
5
5
  show eco banner : yes
6
6
  audience : Depot X
@@ -1,10 +1,10 @@
1
1
  # Equals test
2
2
 
3
- ## Insight
3
+ ## Entailment
4
4
  The derivation produced 1 new fact(s) from 1 stated fact(s).
5
- Main conclusion: **:test is true.**
5
+ Main entailment: **:test is true.**
6
6
 
7
- Selected conclusions:
7
+ Selected entailments:
8
8
  - :test :is true .
9
9
 
10
10
  ## Explanation
@@ -1,10 +1,10 @@
1
1
  # If two equivalence classes share an element, they are the same class.
2
2
 
3
- ## Insight
3
+ ## Entailment
4
4
  The compiled query selected 18 fact(s) after the rule closure was computed.
5
- Main conclusion: **:result :sameClassBecauseOfSharedMember (:a :b :c).**
5
+ Main entailment: **:result :sameClassBecauseOfSharedMember (:a :b :c).**
6
6
 
7
- Selected conclusions:
7
+ Selected entailments:
8
8
  - :result :sameClassBecauseOfSharedMember (:a :b :c) .
9
9
  - :result :sameClassBecauseOfSharedMember (:a :c :c) .
10
10
  - :result :sameClassBecauseOfSharedMember (:c :b :a) .
@@ -1,10 +1,10 @@
1
1
  # Euler identity (exact, certificate-friendly):
2
2
 
3
- ## Insight
3
+ ## Entailment
4
4
  The compiled query selected 6 fact(s) after the rule closure was computed.
5
- Main conclusion: **:result :identityHolds true.**
5
+ Main entailment: **:result :identityHolds true.**
6
6
 
7
- Selected conclusions:
7
+ Selected entailments:
8
8
  - :result :identityHolds true .
9
9
  - :result :phaseModSqIsOne true .
10
10
  - :result :phaseModSq 1 .
@@ -1,6 +1,6 @@
1
1
  # EV Roadtrip Planner
2
2
 
3
- ## Insight
3
+ ## Entailment
4
4
  Select plan : drive_bru_liege -> drive_liege_aachen -> shuttle_aachen_cologne.
5
5
  route result : Cologne battery=low pass=none
6
6
  duration : 210.0 minutes
@@ -1,10 +1,10 @@
1
1
  # Existential rule
2
2
 
3
- ## Insight
3
+ ## Entailment
4
4
  The derivation produced 2 new fact(s) from 2 stated fact(s).
5
- Main conclusion: **:Plato is _:B.**
5
+ Main entailment: **:Plato is _:B.**
6
6
 
7
- Selected conclusions:
7
+ Selected entailments:
8
8
  - :Plato :is _:B .
9
9
  - :Socrates :is _:B .
10
10
 
@@ -1,10 +1,10 @@
1
1
  # A tiny expression evaluator in N3
2
2
 
3
- ## Insight
3
+ ## Entailment
4
4
  The derivation produced 1 new fact(s) from 17 stated fact(s).
5
- Main conclusion: **:Root :result 12.**
5
+ Main entailment: **:Root :result 12.**
6
6
 
7
- Selected conclusions:
7
+ Selected entailments:
8
8
  - :Root :result 12 .
9
9
 
10
10
  ## Explanation
@@ -1,10 +1,10 @@
1
1
  # Family cousins
2
2
 
3
- ## Insight
3
+ ## Entailment
4
4
  The derivation produced 25 new fact(s) from 15 stated fact(s).
5
- Main conclusion: **:Judy :cousin :Ivan.**
5
+ Main entailment: **:Judy :cousin :Ivan.**
6
6
 
7
- Selected conclusions:
7
+ Selected entailments:
8
8
  - :Judy :cousin :Ivan .
9
9
  - :Judy :cousin :Heidi .
10
10
  - :Ivan :cousin :Judy .
@@ -1,6 +1,6 @@
1
1
  # Fast exponentiation demo
2
2
 
3
- ## Insight
3
+ ## Entailment
4
4
  The derivation produced 0 new fact(s) from 0 stated fact(s).
5
5
 
6
6
  ## Explanation
@@ -1,6 +1,6 @@
1
1
  # Fibonacci Example (Big)
2
2
 
3
- ## Insight
3
+ ## Entailment
4
4
  The Fibonacci number for index 10000 is:
5
5
  33644764876431783266621612005107543310302148460680063906564769974680081442166662368155595513633734025582065332680836159373734790483865268263040892463056431887354544369559827491606602099884183933864652731300088830269235673613135117579297437854413752130520504347701602264758318906527890855154366159582987279682987510631200575428783453215515103870818298969791613127856265033195487140214287532698187962046936097879900350962302291026368131493195275630227837628441540360584402572114334961180023091208287046088923962328835461505776583271252546093591128203925285393434620904245248929403901706233888991085841065183173360437470737908552631764325733993712871937587746897479926305837065742830161637408969178426378624212835258112820516370298089332099905707920064367426202389783111470054074998459250360633560933883831923386783056136435351892133279732908133732642652633989763922723407882928177953580570993691049175470808931841056146322338217465637321248226383092103297701648054726243842374862411453093812206564914032751086643394517512161526545361333111314042436854805106765843493523836959653428071768775328348234345557366719731392746273629108210679280784718035329131176778924659089938635459327894523777674406192240337638674004021330343297496902028328145933418826817683893072003634795623117103101291953169794607632737589253530772552375943788434504067715555779056450443016640119462580972216729758615026968443146952034614932291105970676243268515992834709891284706740862008587135016260312071903172086094081298321581077282076353186624611278245537208532365305775956430072517744315051539600905168603220349163222640885248852433158051534849622434848299380905070483482449327453732624567755879089187190803662058009594743150052402532709746995318770724376825907419939632265984147498193609285223945039707165443156421328157688908058783183404917434556270520223564846495196112460268313970975069382648706613264507665074611512677522748621598642530711298441182622661057163515069260029861704945425047491378115154139941550671256271197133252763631939606902895650288268608362241082050562430701794976171121233066073310059947366875
6
6
 
@@ -1,10 +1,10 @@
1
1
  # French cities — graph path traversal.
2
2
 
3
- ## Insight
3
+ ## Entailment
4
4
  The compiled query selected 1 fact(s) after the rule closure was computed.
5
- Main conclusion: **:paris :path :nantes.**
5
+ Main entailment: **:paris :path :nantes.**
6
6
 
7
- Selected conclusions:
7
+ Selected entailments:
8
8
  - :paris :path :nantes .
9
9
 
10
10
  ## Explanation
@@ -1,6 +1,6 @@
1
1
  # Fundamental Theorem Arithmetic
2
2
 
3
- ## Insight
3
+ ## Entailment
4
4
  Primary N3 case: n = 202692987 has prime factors 3 * 3 * 7 * 829 * 3881.
5
5
  primary prime-power form : 3^2 * 7 * 829 * 3881
6
6
  sample count : 6
@@ -1,6 +1,6 @@
1
1
  # Genetic Knapsack Selection
2
2
 
3
- ## Insight
3
+ ## Entailment
4
4
  final genome : 101000000101
5
5
  selected items : item01, item03, item10, item12
6
6
  weight : 50 / 50
@@ -1,6 +1,6 @@
1
1
  # Goldbach 1000
2
2
 
3
- ## Insight
3
+ ## Entailment
4
4
  All 499 even integers from 4 through 1000 have a Goldbach witness.
5
5
  sample witnesses : 4=2+2; 28=5+23; 100=3+97; 998=7+991; 1000=3+997
6
6
 
@@ -1,10 +1,10 @@
1
1
  # Good cobbler
2
2
 
3
- ## Insight
4
- The derivation produced 1 formula-valued conclusion(s).
5
- Main conclusion: **:test is { :joe :is (:good :Cobbler) }.**
3
+ ## Entailment
4
+ The derivation produced 1 formula-valued entailment(s).
5
+ Main entailment: **:test is { :joe :is (:good :Cobbler) }.**
6
6
 
7
- Selected conclusions:
7
+ Selected entailments:
8
8
  - :test :is { :joe :is (:good :Cobbler) } .
9
9
 
10
10
  ## Explanation
@@ -1,6 +1,6 @@
1
1
  # GPS route planning
2
2
 
3
- ## Insight
3
+ ## Entailment
4
4
  Take the direct route via Brugge.
5
5
  Recommended route: Gent -> Brugge -> Oostende
6
6
 
@@ -1,6 +1,6 @@
1
1
  # Gray Code Counter
2
2
 
3
- ## Insight
3
+ ## Entailment
4
4
  bits : 4
5
5
  states visited : 16
6
6
  unique states : 16