@unrdf/hooks 26.4.2 → 26.4.4

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 (60) hide show
  1. package/LICENSE +24 -0
  2. package/README.md +562 -53
  3. package/examples/atomvm-fibo-hooks-demo.mjs +323 -0
  4. package/examples/delta-monitoring-example.mjs +213 -0
  5. package/examples/fibo-jtbd-governance.mjs +388 -0
  6. package/examples/hook-chains/node_modules/.bin/jiti +21 -0
  7. package/examples/hook-chains/node_modules/.bin/msw +21 -0
  8. package/examples/hook-chains/node_modules/.bin/terser +21 -0
  9. package/examples/hook-chains/node_modules/.bin/tsc +21 -0
  10. package/examples/hook-chains/node_modules/.bin/tsserver +21 -0
  11. package/examples/hook-chains/node_modules/.bin/tsx +21 -0
  12. package/examples/hook-chains/node_modules/.bin/vite +21 -0
  13. package/examples/hook-chains/node_modules/.bin/vitest +2 -2
  14. package/examples/hook-chains/node_modules/.bin/yaml +21 -0
  15. package/examples/hook-chains/package.json +2 -2
  16. package/examples/hook-chains/unrdf-hooks-example-chains-5.0.0.tgz +0 -0
  17. package/examples/hooks-marketplace.mjs +261 -0
  18. package/examples/n3-reasoning-example.mjs +279 -0
  19. package/examples/policy-hooks/node_modules/.bin/jiti +21 -0
  20. package/examples/policy-hooks/node_modules/.bin/msw +21 -0
  21. package/examples/policy-hooks/node_modules/.bin/terser +21 -0
  22. package/examples/policy-hooks/node_modules/.bin/tsc +21 -0
  23. package/examples/policy-hooks/node_modules/.bin/tsserver +21 -0
  24. package/examples/policy-hooks/node_modules/.bin/tsx +21 -0
  25. package/examples/policy-hooks/node_modules/.bin/vite +21 -0
  26. package/examples/policy-hooks/node_modules/.bin/vitest +2 -2
  27. package/examples/policy-hooks/node_modules/.bin/yaml +21 -0
  28. package/examples/policy-hooks/package.json +2 -2
  29. package/examples/policy-hooks/unrdf-hooks-example-policy-5.0.0.tgz +0 -0
  30. package/examples/shacl-repair-example.mjs +191 -0
  31. package/examples/window-condition-example.mjs +285 -0
  32. package/package.json +6 -3
  33. package/src/atomvm.mjs +9 -0
  34. package/src/define.mjs +114 -0
  35. package/src/executor.mjs +23 -0
  36. package/src/hooks/atomvm-bridge.mjs +332 -0
  37. package/src/hooks/builtin-hooks.mjs +13 -7
  38. package/src/hooks/condition-evaluator.mjs +684 -77
  39. package/src/hooks/define-hook.mjs +23 -21
  40. package/src/hooks/effect-executor.mjs +630 -0
  41. package/src/hooks/effect-sandbox.mjs +19 -9
  42. package/src/hooks/file-resolver.mjs +155 -1
  43. package/src/hooks/hook-chain-compiler.mjs +11 -1
  44. package/src/hooks/hook-executor.mjs +98 -73
  45. package/src/hooks/knowledge-hook-engine.mjs +133 -7
  46. package/src/hooks/ontology-learner.mjs +190 -0
  47. package/src/hooks/policy-pack.mjs +7 -1
  48. package/src/hooks/query-optimizer.mjs +1 -5
  49. package/src/hooks/query.mjs +3 -3
  50. package/src/hooks/schemas.mjs +55 -5
  51. package/src/hooks/security/error-sanitizer.mjs +46 -24
  52. package/src/hooks/self-play-autonomics.mjs +423 -0
  53. package/src/hooks/telemetry.mjs +32 -9
  54. package/src/hooks/validate.mjs +100 -33
  55. package/src/index.mjs +2 -0
  56. package/src/lib/admit-hook.mjs +615 -0
  57. package/src/policy-compiler.mjs +23 -13
  58. package/dist/index.d.mts +0 -1738
  59. package/dist/index.d.ts +0 -1738
  60. package/dist/index.mjs +0 -1738
@@ -0,0 +1,261 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * @file Working example - Composable Hooks Marketplace
5
+ * @module examples/hooks-marketplace
6
+ * @description
7
+ * Demonstrates the Composable Hooks Marketplace with:
8
+ * 1. Hook normalization to RDF via SPARQL CONSTRUCT
9
+ * 2. Dependency resolution and circular cycle detection via N3
10
+ * 3. SHACL validation in soft-fail (annotate) mode with RDF audit trail
11
+ * 4. Marketplace queries over admitted hooks
12
+ *
13
+ * Run: node examples/hooks-marketplace.mjs
14
+ */
15
+
16
+ import { HooksMarketplace, HOOK_NS } from '../src/lib/admit-hook.mjs';
17
+
18
+ /**
19
+ * Helper: Pretty print JSON with 2-space indent
20
+ */
21
+ function pretty(obj) {
22
+ return JSON.stringify(obj, null, 2);
23
+ }
24
+
25
+ /**
26
+ * Helper: Create hook definition
27
+ */
28
+ function createHook(id, name, version, deps = []) {
29
+ return {
30
+ id,
31
+ name,
32
+ version,
33
+ description: `The ${name} hook performs important transformations`,
34
+ conditions: [
35
+ {
36
+ kind: 'sparql-ask',
37
+ query: `ASK { ?s a <${HOOK_NS.hook}${id}> }`,
38
+ },
39
+ ],
40
+ effects: [
41
+ {
42
+ kind: 'sparql-construct',
43
+ query: `CONSTRUCT { ?s ?p ?o } WHERE { ?s ?p ?o }`,
44
+ },
45
+ ],
46
+ dependsOn: deps,
47
+ priority: Math.floor(Math.random() * 100),
48
+ };
49
+ }
50
+
51
+ async function main() {
52
+ console.log('╔════════════════════════════════════════════════════════╗');
53
+ console.log('║ O* Innovation 5: Composable Hooks Marketplace ║');
54
+ console.log('║ RDF-based hook composition with SPARQL + N3 + SHACL ║');
55
+ console.log('╚════════════════════════════════════════════════════════╝\n');
56
+
57
+ // Initialize marketplace
58
+ const marketplace = new HooksMarketplace();
59
+ console.log('✓ Marketplace initialized\n');
60
+
61
+ // ═══════════════════════════════════════════════════════════════════
62
+ // DEMO 1: Single Hook Normalization
63
+ // ═══════════════════════════════════════════════════════════════════
64
+ console.log('┌─ DEMO 1: Hook Normalization to RDF ─────────────────┐');
65
+
66
+ const hookId1 = '550e8400-e29b-41d4-a716-446655440001';
67
+ const singleHook = createHook(
68
+ hookId1,
69
+ 'Data Enrichment Hook',
70
+ '1.0.0',
71
+ [], // No dependencies
72
+ );
73
+
74
+ console.log('Input hook definition:');
75
+ console.log(pretty(singleHook));
76
+ console.log('\nNormalizing to RDF...');
77
+
78
+ const normalized = marketplace.normalizeHookToRDF(singleHook);
79
+ console.log(`\nGenerated hook URI: ${normalized.hookUri}`);
80
+ console.log(`Total RDF triples: ${normalized.triples.length}`);
81
+ console.log(`Conditions: ${normalized.conditions.length}`);
82
+ console.log(`Effects: ${normalized.effects.length}`);
83
+
84
+ // Sample triples
85
+ console.log('\nSample RDF triples (first 5):');
86
+ normalized.triples.slice(0, 5).forEach((t, idx) => {
87
+ console.log(` ${idx + 1}. ${t.subject.value}`);
88
+ console.log(` --[${t.predicate.value.split('/').pop()}]-->`);
89
+ console.log(` ${t.object.value || t.object.datatype}`);
90
+ });
91
+
92
+ console.log('└───────────────────────────────────────────────────────┘\n');
93
+
94
+ // ═══════════════════════════════════════════════════════════════════
95
+ // DEMO 2: Hook Admission with SHACL Soft-Fail
96
+ // ═══════════════════════════════════════════════════════════════════
97
+ console.log('┌─ DEMO 2: Hook Admission with SHACL Soft-Fail ────────┐');
98
+
99
+ const admissionResult = marketplace.admitHook(singleHook);
100
+ console.log(`Hook admission result:`);
101
+ console.log(` Admitted: ${admissionResult.admitted}`);
102
+ console.log(` Hook URI: ${admissionResult.hookUri}`);
103
+ console.log(` Violations: ${admissionResult.violationCount}`);
104
+
105
+ if (admissionResult.violationCount > 0) {
106
+ console.log(` Violation details:`);
107
+ admissionResult.violations.forEach(v => {
108
+ console.log(` - ${v.message}`);
109
+ });
110
+ }
111
+
112
+ console.log('└───────────────────────────────────────────────────────┘\n');
113
+
114
+ // ═══════════════════════════════════════════════════════════════════
115
+ // DEMO 3: Valid Dependency Chain
116
+ // ═══════════════════════════════════════════════════════════════════
117
+ console.log('┌─ DEMO 3: Valid Dependency Chain A→B→C ────────────────┐');
118
+
119
+ const hookId2 = '550e8400-e29b-41d4-a716-446655440002';
120
+ const hookId3 = '550e8400-e29b-41d4-a716-446655440003';
121
+
122
+ const hookA = createHook(hookId1, 'Hook A (Base)', '1.0.0', []);
123
+ const hookB = createHook(hookId2, 'Hook B (depends on A)', '1.0.0', [hookId1]);
124
+ const hookC = createHook(hookId3, 'Hook C (depends on B)', '1.0.0', [hookId2]);
125
+
126
+ console.log('Admitting hooks A→B→C (valid chain)...\n');
127
+
128
+ const chainResult = marketplace.admitHooksWithDependencies([hookA, hookB, hookC]);
129
+
130
+ console.log(`Results:`);
131
+ console.log(` Admitted: ${chainResult.admittedCount}`);
132
+ console.log(` Rejected: ${chainResult.rejectedCount}`);
133
+ console.log(` Cycles detected: ${chainResult.hadCycles}`);
134
+
135
+ console.log(`\nDependency graph:`);
136
+ console.log(pretty(chainResult.dependencyGraph).split('\n').slice(0, 15).join('\n'));
137
+
138
+ console.log('└───────────────────────────────────────────────────────┘\n');
139
+
140
+ // ═══════════════════════════════════════════════════════════════════
141
+ // DEMO 4: Circular Dependency Detection
142
+ // ═══════════════════════════════════════════════════════════════════
143
+ console.log('┌─ DEMO 4: Circular Dependency Detection (A↔B) ────────┐');
144
+
145
+ const hookId4 = '550e8400-e29b-41d4-a716-446655440004';
146
+ const hookId5 = '550e8400-e29b-41d4-a716-446655440005';
147
+
148
+ const hookX = createHook(hookId4, 'Hook X', '1.0.0', [hookId5]);
149
+ const hookY = createHook(hookId5, 'Hook Y', '1.0.0', [hookId4]);
150
+
151
+ console.log('Admitting hooks X↔Y (circular dependency)...\n');
152
+
153
+ const cycleResult = marketplace.admitHooksWithDependencies([hookX, hookY]);
154
+
155
+ console.log(`Results:`);
156
+ console.log(` Admitted: ${cycleResult.admittedCount}`);
157
+ console.log(` Rejected: ${cycleResult.rejectedCount}`);
158
+ console.log(` Cycles detected: ${cycleResult.hadCycles}`);
159
+
160
+ if (cycleResult.cycles.length > 0) {
161
+ console.log(` Hooks involved in cycles:`);
162
+ cycleResult.cycles.slice(0, 3).forEach(cycle => {
163
+ console.log(` - ${cycle}`);
164
+ });
165
+ }
166
+
167
+ console.log('└───────────────────────────────────────────────────────┘\n');
168
+
169
+ // ═══════════════════════════════════════════════════════════════════
170
+ // DEMO 5: Marketplace Queries
171
+ // ═══════════════════════════════════════════════════════════════════
172
+ console.log('┌─ DEMO 5: RDF Marketplace Queries ─────────────────────┐');
173
+
174
+ // Re-create marketplace with valid hooks
175
+ const queryMarketplace = new HooksMarketplace();
176
+
177
+ const demoHooks = [
178
+ createHook('550e8400-e29b-41d4-a716-446655440010', 'Hook Alpha', '1.0.0', []),
179
+ createHook('550e8400-e29b-41d4-a716-446655440011', 'Hook Beta', '2.0.0', []),
180
+ createHook('550e8400-e29b-41d4-a716-446655440012', 'Hook Gamma', '1.5.0', []),
181
+ ];
182
+
183
+ demoHooks.forEach(h => queryMarketplace.admitHook(h));
184
+
185
+ console.log('Admitted hooks to marketplace:');
186
+ const admitted = queryMarketplace.getAdmittedHooks();
187
+ admitted.forEach((h, idx) => {
188
+ console.log(` ${idx + 1}. ${h.name} (v${h.version}) - priority: ${h.priority}`);
189
+ });
190
+
191
+ // Query: Count all hooks
192
+ const countQuery = `
193
+ PREFIX hook: <http://ostar.org/hook/>
194
+ SELECT (COUNT(?hook) AS ?count) WHERE {
195
+ ?hook a hook:Hook .
196
+ }
197
+ `;
198
+
199
+ try {
200
+ const countResults = queryMarketplace.query(countQuery);
201
+ console.log(`\nSPARQL query result (COUNT all hooks):`);
202
+ console.log(` Total hooks: ${countResults.length > 0 ? countResults[0].count : 0}`);
203
+ } catch (err) {
204
+ console.log(`Query note: ${err.message}`);
205
+ }
206
+
207
+ console.log('└───────────────────────────────────────────────────────┘\n');
208
+
209
+ // ═══════════════════════════════════════════════════════════════════
210
+ // DEMO 6: Soft-Fail Admission with SHACL Violations
211
+ // ═══════════════════════════════════════════════════════════════════
212
+ console.log('┌─ DEMO 6: Soft-Fail Admission (SHACL Annotate) ────────┐');
213
+
214
+ const softFailMarketplace = new HooksMarketplace();
215
+
216
+ // All hooks that pass Zod schema validation are admitted (soft-fail)
217
+ // This demonstrates the separation of concerns:
218
+ // - Zod: syntactic validation (hard-fail)
219
+ // - SHACL: semantic validation (soft-fail with audit trail RDF)
220
+ const validHook = createHook(
221
+ '550e8400-e29b-41d4-a716-446655440020',
222
+ 'Analytics Hook',
223
+ '1.0.0',
224
+ [],
225
+ );
226
+
227
+ const softFailResult = softFailMarketplace.admitHook(validHook);
228
+
229
+ console.log('Admitting valid hook (all constraints satisfied)...\n');
230
+ console.log(`Admission result:`);
231
+ console.log(` Admitted: ${softFailResult.admitted} (soft-fail mode)`);
232
+ console.log(` Violations recorded: ${softFailResult.violationCount}`);
233
+ console.log(` Hook URI: ${softFailResult.hookUri}`);
234
+
235
+ console.log(`\nDesign Notes:`);
236
+ console.log(` • Zod schema validation: Hard-fail (syntactic)`);
237
+ console.log(` • SHACL validation: Soft-fail (semantic, RDF audit trail)`);
238
+ console.log(` • Violated hooks recorded as RDF triples for compliance audits`);
239
+ console.log(` • Hooks always admitted if they pass syntax validation`);
240
+
241
+ console.log('└───────────────────────────────────────────────────────┘\n');
242
+
243
+ // ═══════════════════════════════════════════════════════════════════
244
+ // Summary
245
+ // ═══════════════════════════════════════════════════════════════════
246
+ console.log('╔════════════════════════════════════════════════════════╗');
247
+ console.log('║ Summary ║');
248
+ console.log('╠════════════════════════════════════════════════════════╣');
249
+ console.log('║ ✓ Hook normalization to RDF (SPARQL CONSTRUCT) ║');
250
+ console.log('║ ✓ Dependency composition (N3 forward-chaining) ║');
251
+ console.log('║ ✓ Circular cycle detection ║');
252
+ console.log('║ ✓ SHACL validation (annotate/soft-fail mode) ║');
253
+ console.log('║ ✓ RDF audit trail for violations ║');
254
+ console.log('║ ✓ Marketplace queries via SPARQL ║');
255
+ console.log('╚════════════════════════════════════════════════════════╝\n');
256
+ }
257
+
258
+ main().catch(err => {
259
+ console.error('Error:', err.message);
260
+ process.exit(1);
261
+ });
@@ -0,0 +1,279 @@
1
+ /**
2
+ * @unrdf/hooks - N3 Forward-Chaining Reasoning Example
3
+ *
4
+ * Demonstrates semantic inference using N3 rules and EYE reasoner.
5
+ * Derives new facts from existing data through logical rules.
6
+ *
7
+ * Use cases:
8
+ * - RDFS/OWL-like reasoning (class hierarchies, property inference)
9
+ * - Business rule execution (access control, workflow logic)
10
+ * - Data enrichment (derive properties from rules)
11
+ * - Compliance checking (derive compliance status)
12
+ */
13
+
14
+ import { createStore } from '@unrdf/oxigraph';
15
+ import { evaluateCondition } from '../src/hooks/condition-evaluator.mjs';
16
+ import { UnrdfDataFactory as DataFactory } from '@unrdf/core/rdf/n3-justified-only';
17
+
18
+ const { namedNode, literal, quad } = DataFactory;
19
+
20
+ console.log('=== N3 Forward-Chaining Reasoning Example ===\n');
21
+
22
+ // Example 1: Simple class inheritance
23
+ console.log('1. Simple Class Inheritance\n');
24
+
25
+ const classInheritanceCondition = {
26
+ kind: 'n3',
27
+ rules: `
28
+ @prefix : <http://example.org/> .
29
+ @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
30
+
31
+ # Rule: If X is subclass of Y and Z is instance of X, then Z is instance of Y
32
+ { ?x rdfs:subClassOf ?y . ?z a ?x } => { ?z a ?y } .
33
+ `,
34
+ askQuery: 'ASK { ?s a <http://example.org/Animal> }'
35
+ };
36
+
37
+ console.log('Rules:');
38
+ console.log(classInheritanceCondition.rules);
39
+ console.log('');
40
+ console.log('Scenario:');
41
+ console.log(' Data: Dog subClassOf Animal, Fido a Dog');
42
+ console.log(' Inference: Fido a Animal (derived)');
43
+ console.log(' Query: ASK { ?s a Animal } → true\n');
44
+
45
+ // Example 2: Access control reasoning
46
+ console.log('2. Access Control Reasoning\n');
47
+
48
+ const accessControlCondition = {
49
+ kind: 'n3',
50
+ rules: `
51
+ @prefix : <http://example.org/> .
52
+
53
+ # Rule 1: Admins can access everything
54
+ { ?user a :Admin } => { ?user :canAccess :SecureArea } .
55
+
56
+ # Rule 2: Group members inherit group permissions
57
+ { ?user :isMemberOf ?group . ?group :hasPermission ?perm }
58
+ => { ?user :hasPermission ?perm } .
59
+
60
+ # Rule 3: Users with edit permission need audit logging
61
+ { ?user :hasPermission :EditContent }
62
+ => { ?user :requiresAuditLog true } .
63
+
64
+ # Rule 4: Audit logging required if accessing secure area
65
+ { ?user :canAccess :SecureArea }
66
+ => { ?user :requiresAuditLog true } .
67
+ `,
68
+ askQuery: 'ASK { ?user :requiresAuditLog true }'
69
+ };
70
+
71
+ console.log('Rules demonstrate multi-level inference:');
72
+ console.log(' Rule 1: Admin role → access permission');
73
+ console.log(' Rule 2: Group membership → inherit permissions');
74
+ console.log(' Rule 3: Edit permission → audit requirement');
75
+ console.log(' Rule 4: Secure access → audit requirement');
76
+ console.log('');
77
+ console.log('Scenario:');
78
+ console.log(' Data: alice a Admin, bob :isMemberOf :editors');
79
+ console.log(' Step 1: alice a Admin → alice :canAccess :SecureArea');
80
+ console.log(' Step 2: alice :canAccess :SecureArea → alice :requiresAuditLog true');
81
+ console.log(' Step 3: bob :isMemberOf :editors → check group permissions');
82
+ console.log(' Result: Audit requirements derived from roles\n');
83
+
84
+ // Example 3: Business process workflow
85
+ console.log('3. Business Process Workflow Reasoning\n');
86
+
87
+ const workflowCondition = {
88
+ kind: 'n3',
89
+ rules: `
90
+ @prefix : <http://example.org/> .
91
+
92
+ # Rule 1: Large trades require compliance review
93
+ { ?trade a :Trade ; :amount ?amt . ?amt > 1000000 }
94
+ => { ?trade :requiresCompliance true } .
95
+
96
+ # Rule 2: Compliance required trades need risk assessment
97
+ { ?trade :requiresCompliance true }
98
+ => { ?trade :requiresRiskAssessment true } .
99
+
100
+ # Rule 3: Risk assessment must be approved by senior reviewer
101
+ { ?trade :requiresRiskAssessment true }
102
+ => { ?trade :requiresApprovalLevel :Senior } .
103
+
104
+ # Rule 4: High-risk trades need compliance officer sign-off
105
+ { ?trade :riskLevel :High ; :requiresApprovalLevel :Senior }
106
+ => { ?trade :requiresComplianceOfficer true } .
107
+
108
+ # Rule 5: Anything needing compliance officer needs audit trail
109
+ { ?trade :requiresComplianceOfficer true }
110
+ => { ?trade :auditTrailRequired true } .
111
+ `,
112
+ askQuery: 'ASK { ?trade :auditTrailRequired true }'
113
+ };
114
+
115
+ console.log('Multi-step workflow rules:');
116
+ console.log(' Trade amount > $1M → requires compliance');
117
+ console.log(' Requires compliance → requires risk assessment');
118
+ console.log(' Requires risk assessment → requires senior approval');
119
+ console.log(' High risk + senior approval → needs compliance officer');
120
+ console.log(' Needs compliance officer → needs audit trail');
121
+ console.log('');
122
+ console.log('Execution:');
123
+ console.log(' Input: Trade with amount $1.5M');
124
+ console.log(' Derives: auditTrailRequired = true');
125
+ console.log(' Effect: Create audit record in system\n');
126
+
127
+ // Example 4: Data enrichment
128
+ console.log('4. Data Enrichment Through Reasoning\n');
129
+
130
+ const enrichmentCondition = {
131
+ kind: 'n3',
132
+ rules: `
133
+ @prefix : <http://example.org/> .
134
+ @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
135
+
136
+ # Rule 1: Calculate age from birthDate
137
+ { ?person :birthDate ?birth }
138
+ => { ?person :age ?age } . # Would need SPARQL for real calculation
139
+
140
+ # Rule 2: Categorize by age
141
+ { ?person :age ?age . ?age > 65 }
142
+ => { ?person :category :Senior } .
143
+
144
+ { ?person :age ?age . ?age >= 18 . ?age <= 65 }
145
+ => { ?person :category :Adult } .
146
+
147
+ { ?person :age ?age . ?age < 18 }
148
+ => { ?person :category :Minor } .
149
+
150
+ # Rule 3: Seniors get special benefits
151
+ { ?person :category :Senior }
152
+ => { ?person :eligibleFor :SeniorDiscount } .
153
+
154
+ # Rule 4: Mark complete profiles
155
+ { ?person :name ?n ; :email ?e ; :category ?c }
156
+ => { ?person :profileComplete true } .
157
+ `,
158
+ askQuery: 'ASK { ?p :profileComplete true }'
159
+ };
160
+
161
+ console.log('Enrichment rules:');
162
+ console.log(' Birthdate → derive age');
163
+ console.log(' Age → categorize as Senior/Adult/Minor');
164
+ console.log(' Senior → eligible for discount');
165
+ console.log(' Complete profile (name + email + category) → mark as complete');
166
+ console.log('');
167
+ console.log('Input: Person with name, email, age');
168
+ console.log('Output: Category, discounts, completeness flag\n');
169
+
170
+ // Example 5: Compliance rule engine
171
+ console.log('5. Compliance Rule Engine\n');
172
+
173
+ const complianceCondition = {
174
+ kind: 'n3',
175
+ rules: `
176
+ @prefix : <http://example.org/> .
177
+
178
+ # GDPR Rules
179
+ { ?entity a :PersonalData ; :storedIn ?jurisdiction .
180
+ ?jurisdiction :region ?region . ?region != :EU }
181
+ => { ?entity :gdprViolation :DataResidency } .
182
+
183
+ # PCI-DSS Rules
184
+ { ?entity a :CardData ; :encryptionLevel ?level .
185
+ ?level < 256 }
186
+ => { ?entity :pciViolation :InsufficientEncryption } .
187
+
188
+ # SOX Rules (for public companies)
189
+ { ?company a :PublicCompany ;
190
+ :hasFinancialData ?data }
191
+ => { ?company :requiresSoxCompliance true } .
192
+
193
+ # Any violation → requires remediation
194
+ { ?entity :gdprViolation ?v } => { ?entity :requiresRemediation true } .
195
+ { ?entity :pciViolation ?v } => { ?entity :requiresRemediation true } .
196
+
197
+ # Mark non-compliant if has violations
198
+ { ?entity :requiresRemediation true }
199
+ => { ?entity :complianceStatus :NonCompliant } .
200
+ `,
201
+ askQuery: 'ASK { ?entity :complianceStatus :NonCompliant }'
202
+ };
203
+
204
+ console.log('Compliance engine checks:');
205
+ console.log(' GDPR: Personal data must be in EU jurisdiction');
206
+ console.log(' PCI-DSS: Card data must be 256-bit encrypted');
207
+ console.log(' SOX: Public companies must audit financial data');
208
+ console.log(' Any violation → mark non-compliant\n');
209
+
210
+ // Performance considerations
211
+ console.log('6. Performance Considerations\n');
212
+
213
+ console.log('Forward-chaining semantics:');
214
+ console.log(' - All applicable rules fire until fixpoint');
215
+ console.log(' - Derives all possible new facts');
216
+ console.log(' - Complete closure of logical consequences');
217
+ console.log('');
218
+ console.log('Performance factors:');
219
+ console.log(' 1. Rule count: More rules = more inference steps');
220
+ console.log(' 2. Data size: Large graphs = more match attempts');
221
+ console.log(' 3. Rule complexity: Join patterns in antecedents');
222
+ console.log(' 4. Iteration count: Fixpoint may require many passes');
223
+ console.log('');
224
+ console.log('Optimization tips:');
225
+ console.log(' ✓ Materialize frequently derived facts');
226
+ console.log(' ✓ Use specific patterns (avoid ?x ?p ?o)');
227
+ console.log(' ✓ Order rules: simple → complex');
228
+ console.log(' ✗ Avoid rules that derive rule premises');
229
+ console.log(' ✗ Don\'t use reasoning for high-frequency checks\n');
230
+
231
+ // Full hook example
232
+ console.log('7. Complete Hook with N3 Reasoning\n');
233
+
234
+ console.log(`
235
+ const dataEnrichmentHook = {
236
+ name: 'enriched-trade-data',
237
+
238
+ condition: {
239
+ kind: 'n3',
240
+ rules: \`
241
+ @prefix : <http://example.org/> .
242
+
243
+ { ?trade a :Trade ; :amount ?amt . ?amt > 500000 }
244
+ => { ?trade :largeTradeIndicator true } .
245
+
246
+ { ?trade :largeTradeIndicator true }
247
+ => { ?trade :requiresReview true } .
248
+
249
+ { ?trade :requiresReview true ; :counterparty ?cp }
250
+ => { ?cp :hadLargeTrade true } .
251
+ \`,
252
+ askQuery: 'ASK { ?t :requiresReview true }'
253
+ },
254
+
255
+ effects: [{
256
+ kind: 'sparql-construct',
257
+ query: \`
258
+ CONSTRUCT {
259
+ ?trade :reviewStatus ex:Pending ;
260
+ :derivedFrom ex:N3Rules ;
261
+ :timestamp ?now .
262
+ }
263
+ WHERE {
264
+ ?trade :requiresReview true .
265
+ BIND (NOW() as ?now)
266
+ }
267
+ \`
268
+ }]
269
+ };
270
+
271
+ Execution:
272
+ 1. Trade added with amount > $500K
273
+ 2. N3 reasoning: derives :requiresReview true
274
+ 3. Condition ASK: "is there a :requiresReview?" → true
275
+ 4. Effect executes: marks trade as pending review
276
+ 5. Counterparty flagged for trading pattern analysis
277
+ `);
278
+
279
+ console.log('\n=== Example Complete ===');
@@ -0,0 +1,21 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*|*MINGW*|*MSYS*)
6
+ if command -v cygpath > /dev/null 2>&1; then
7
+ basedir=`cygpath -w "$basedir"`
8
+ fi
9
+ ;;
10
+ esac
11
+
12
+ if [ -z "$NODE_PATH" ]; then
13
+ export NODE_PATH="/Users/sac/unrdf/node_modules/.pnpm/jiti@2.6.1/node_modules/jiti/lib/node_modules:/Users/sac/unrdf/node_modules/.pnpm/jiti@2.6.1/node_modules/jiti/node_modules:/Users/sac/unrdf/node_modules/.pnpm/jiti@2.6.1/node_modules:/Users/sac/unrdf/node_modules/.pnpm/node_modules"
14
+ else
15
+ export NODE_PATH="/Users/sac/unrdf/node_modules/.pnpm/jiti@2.6.1/node_modules/jiti/lib/node_modules:/Users/sac/unrdf/node_modules/.pnpm/jiti@2.6.1/node_modules/jiti/node_modules:/Users/sac/unrdf/node_modules/.pnpm/jiti@2.6.1/node_modules:/Users/sac/unrdf/node_modules/.pnpm/node_modules:$NODE_PATH"
16
+ fi
17
+ if [ -x "$basedir/node" ]; then
18
+ exec "$basedir/node" "$basedir/../../../../../../node_modules/.pnpm/jiti@2.6.1/node_modules/jiti/lib/jiti-cli.mjs" "$@"
19
+ else
20
+ exec node "$basedir/../../../../../../node_modules/.pnpm/jiti@2.6.1/node_modules/jiti/lib/jiti-cli.mjs" "$@"
21
+ fi
@@ -0,0 +1,21 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*|*MINGW*|*MSYS*)
6
+ if command -v cygpath > /dev/null 2>&1; then
7
+ basedir=`cygpath -w "$basedir"`
8
+ fi
9
+ ;;
10
+ esac
11
+
12
+ if [ -z "$NODE_PATH" ]; then
13
+ export NODE_PATH="/Users/sac/unrdf/node_modules/.pnpm/msw@2.12.14_@types+node@25.5.0_typescript@5.9.3/node_modules/msw/cli/node_modules:/Users/sac/unrdf/node_modules/.pnpm/msw@2.12.14_@types+node@25.5.0_typescript@5.9.3/node_modules/msw/node_modules:/Users/sac/unrdf/node_modules/.pnpm/msw@2.12.14_@types+node@25.5.0_typescript@5.9.3/node_modules:/Users/sac/unrdf/node_modules/.pnpm/node_modules"
14
+ else
15
+ export NODE_PATH="/Users/sac/unrdf/node_modules/.pnpm/msw@2.12.14_@types+node@25.5.0_typescript@5.9.3/node_modules/msw/cli/node_modules:/Users/sac/unrdf/node_modules/.pnpm/msw@2.12.14_@types+node@25.5.0_typescript@5.9.3/node_modules/msw/node_modules:/Users/sac/unrdf/node_modules/.pnpm/msw@2.12.14_@types+node@25.5.0_typescript@5.9.3/node_modules:/Users/sac/unrdf/node_modules/.pnpm/node_modules:$NODE_PATH"
16
+ fi
17
+ if [ -x "$basedir/node" ]; then
18
+ exec "$basedir/node" "$basedir/../../../../../../node_modules/.pnpm/msw@2.12.14_@types+node@25.5.0_typescript@5.9.3/node_modules/msw/cli/index.js" "$@"
19
+ else
20
+ exec node "$basedir/../../../../../../node_modules/.pnpm/msw@2.12.14_@types+node@25.5.0_typescript@5.9.3/node_modules/msw/cli/index.js" "$@"
21
+ fi
@@ -0,0 +1,21 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*|*MINGW*|*MSYS*)
6
+ if command -v cygpath > /dev/null 2>&1; then
7
+ basedir=`cygpath -w "$basedir"`
8
+ fi
9
+ ;;
10
+ esac
11
+
12
+ if [ -z "$NODE_PATH" ]; then
13
+ export NODE_PATH="/Users/sac/unrdf/node_modules/.pnpm/terser@5.46.1/node_modules/terser/bin/node_modules:/Users/sac/unrdf/node_modules/.pnpm/terser@5.46.1/node_modules/terser/node_modules:/Users/sac/unrdf/node_modules/.pnpm/terser@5.46.1/node_modules:/Users/sac/unrdf/node_modules/.pnpm/node_modules"
14
+ else
15
+ export NODE_PATH="/Users/sac/unrdf/node_modules/.pnpm/terser@5.46.1/node_modules/terser/bin/node_modules:/Users/sac/unrdf/node_modules/.pnpm/terser@5.46.1/node_modules/terser/node_modules:/Users/sac/unrdf/node_modules/.pnpm/terser@5.46.1/node_modules:/Users/sac/unrdf/node_modules/.pnpm/node_modules:$NODE_PATH"
16
+ fi
17
+ if [ -x "$basedir/node" ]; then
18
+ exec "$basedir/node" "$basedir/../../../../../../node_modules/.pnpm/terser@5.46.1/node_modules/terser/bin/terser" "$@"
19
+ else
20
+ exec node "$basedir/../../../../../../node_modules/.pnpm/terser@5.46.1/node_modules/terser/bin/terser" "$@"
21
+ fi
@@ -0,0 +1,21 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*|*MINGW*|*MSYS*)
6
+ if command -v cygpath > /dev/null 2>&1; then
7
+ basedir=`cygpath -w "$basedir"`
8
+ fi
9
+ ;;
10
+ esac
11
+
12
+ if [ -z "$NODE_PATH" ]; then
13
+ export NODE_PATH="/Users/sac/unrdf/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/node_modules:/Users/sac/unrdf/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/Users/sac/unrdf/node_modules/.pnpm/typescript@5.9.3/node_modules:/Users/sac/unrdf/node_modules/.pnpm/node_modules"
14
+ else
15
+ export NODE_PATH="/Users/sac/unrdf/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/node_modules:/Users/sac/unrdf/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/Users/sac/unrdf/node_modules/.pnpm/typescript@5.9.3/node_modules:/Users/sac/unrdf/node_modules/.pnpm/node_modules:$NODE_PATH"
16
+ fi
17
+ if [ -x "$basedir/node" ]; then
18
+ exec "$basedir/node" "$basedir/../../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/tsc" "$@"
19
+ else
20
+ exec node "$basedir/../../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/tsc" "$@"
21
+ fi
@@ -0,0 +1,21 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*|*MINGW*|*MSYS*)
6
+ if command -v cygpath > /dev/null 2>&1; then
7
+ basedir=`cygpath -w "$basedir"`
8
+ fi
9
+ ;;
10
+ esac
11
+
12
+ if [ -z "$NODE_PATH" ]; then
13
+ export NODE_PATH="/Users/sac/unrdf/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/node_modules:/Users/sac/unrdf/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/Users/sac/unrdf/node_modules/.pnpm/typescript@5.9.3/node_modules:/Users/sac/unrdf/node_modules/.pnpm/node_modules"
14
+ else
15
+ export NODE_PATH="/Users/sac/unrdf/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/node_modules:/Users/sac/unrdf/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/Users/sac/unrdf/node_modules/.pnpm/typescript@5.9.3/node_modules:/Users/sac/unrdf/node_modules/.pnpm/node_modules:$NODE_PATH"
16
+ fi
17
+ if [ -x "$basedir/node" ]; then
18
+ exec "$basedir/node" "$basedir/../../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/tsserver" "$@"
19
+ else
20
+ exec node "$basedir/../../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/tsserver" "$@"
21
+ fi