@unrdf/knowledge-engine 5.0.1 → 26.4.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.
- package/package.json +23 -17
- package/src/ai-enhanced-search.mjs +371 -0
- package/src/anomaly-detector.mjs +226 -0
- package/src/artifact-generator.mjs +252 -0
- package/src/browser.mjs +1 -1
- package/src/chatman/disruption-arithmetic.mjs +140 -0
- package/src/chatman/market-dynamics.mjs +140 -0
- package/src/chatman/organizational-dynamics.mjs +140 -0
- package/src/chatman/strategic-dynamics.mjs +140 -0
- package/src/chatman-config-loader.mjs +282 -0
- package/src/chatman-engine.mjs +435 -0
- package/src/chatman-operator.mjs +343 -0
- package/src/dark-field-detector.mjs +332 -0
- package/src/formation-theorems.mjs +345 -0
- package/src/index.mjs +20 -2
- package/src/knowledge-hook-manager.mjs +1 -1
- package/src/lockchain-writer-browser.mjs +2 -2
- package/src/observability.mjs +40 -4
- package/src/query-optimizer.mjs +1 -1
- package/src/resolution-layer.mjs +1 -1
- package/src/transaction.mjs +11 -9
- package/README.md +0 -84
- package/src/browser-shims.mjs +0 -343
- package/src/canonicalize.mjs +0 -414
- package/src/condition-cache.mjs +0 -109
- package/src/condition-evaluator.mjs +0 -722
- package/src/dark-matter-core.mjs +0 -742
- package/src/define-hook.mjs +0 -213
- package/src/effect-sandbox-browser.mjs +0 -283
- package/src/effect-sandbox-worker.mjs +0 -170
- package/src/effect-sandbox.mjs +0 -517
- package/src/engines/index.mjs +0 -11
- package/src/engines/rdf-engine.mjs +0 -299
- package/src/file-resolver.mjs +0 -387
- package/src/hook-executor-batching.mjs +0 -277
- package/src/hook-executor.mjs +0 -870
- package/src/hook-management.mjs +0 -150
- package/src/ken-parliment.mjs +0 -119
- package/src/ken.mjs +0 -149
- package/src/knowledge-engine/builtin-rules.mjs +0 -190
- package/src/knowledge-engine/inference-engine.mjs +0 -418
- package/src/knowledge-engine/knowledge-engine.mjs +0 -317
- package/src/knowledge-engine/pattern-dsl.mjs +0 -142
- package/src/knowledge-engine/pattern-matcher.mjs +0 -215
- package/src/knowledge-engine/rules.mjs +0 -184
- package/src/knowledge-engine.mjs +0 -319
- package/src/knowledge-hook-engine.mjs +0 -360
- package/src/knowledge-substrate-core.mjs +0 -927
- package/src/lite.mjs +0 -222
- package/src/lockchain-writer.mjs +0 -602
- package/src/monitoring/andon-signals.mjs +0 -775
- package/src/parse.mjs +0 -290
- package/src/performance-optimizer.mjs +0 -678
- package/src/policy-pack.mjs +0 -572
- package/src/query-cache.mjs +0 -116
- package/src/query.mjs +0 -306
- package/src/reason.mjs +0 -350
- package/src/schemas.mjs +0 -1063
- package/src/security/error-sanitizer.mjs +0 -257
- package/src/security/path-validator.mjs +0 -194
- package/src/security/sandbox-restrictions.mjs +0 -331
- package/src/security-validator.mjs +0 -389
- package/src/store-cache.mjs +0 -137
- package/src/telemetry.mjs +0 -167
- package/src/utils/adaptive-monitor.mjs +0 -746
- package/src/utils/circuit-breaker.mjs +0 -513
- package/src/utils/edge-case-handler.mjs +0 -503
- package/src/utils/memory-manager.mjs +0 -498
- package/src/utils/ring-buffer.mjs +0 -282
- package/src/validate.mjs +0 -319
- package/src/validators/index.mjs +0 -338
package/src/hook-management.mjs
DELETED
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file Standalone Hook Management Functions
|
|
3
|
-
* @module hook-management
|
|
4
|
-
*
|
|
5
|
-
* @description
|
|
6
|
-
* Provides standalone functions for hook management as expected by the README API.
|
|
7
|
-
* These functions wrap the class methods for easier usage.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { defineHook } from './define-hook.mjs';
|
|
11
|
-
import { KnowledgeHookManager } from './knowledge-hook-manager.mjs';
|
|
12
|
-
|
|
13
|
-
// Global hook manager instance for standalone functions
|
|
14
|
-
let globalHookManager = null;
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Initialize the global hook manager if not already initialized
|
|
18
|
-
* @param {Object} options - Options for the hook manager
|
|
19
|
-
* @returns {KnowledgeHookManager} The global hook manager
|
|
20
|
-
*/
|
|
21
|
-
function getGlobalHookManager(options = {}) {
|
|
22
|
-
if (!globalHookManager) {
|
|
23
|
-
globalHookManager = new KnowledgeHookManager(options);
|
|
24
|
-
}
|
|
25
|
-
return globalHookManager;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Register a knowledge hook globally
|
|
30
|
-
* @param {Object} hook - The knowledge hook to register
|
|
31
|
-
* @param {Object} options - Manager options (if manager needs initialization)
|
|
32
|
-
* @throws {Error} If hook is invalid or already exists
|
|
33
|
-
*
|
|
34
|
-
* @example
|
|
35
|
-
* const hook = defineHook({
|
|
36
|
-
* meta: { name: 'test-hook', description: 'Test hook' },
|
|
37
|
-
* when: { kind: 'sparql-ask', query: 'ASK { ?s ?p ?o }' },
|
|
38
|
-
* run: async (event) => console.log('Hook triggered')
|
|
39
|
-
* });
|
|
40
|
-
*
|
|
41
|
-
* await registerHook(hook);
|
|
42
|
-
*/
|
|
43
|
-
export async function registerHook(hook, options = {}) {
|
|
44
|
-
const manager = getGlobalHookManager(options);
|
|
45
|
-
|
|
46
|
-
// Validate hook if it's not already validated
|
|
47
|
-
const validatedHook = typeof hook === 'object' && !hook._validated ? defineHook(hook) : hook;
|
|
48
|
-
|
|
49
|
-
return manager.addKnowledgeHook(validatedHook);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Deregister (remove) a knowledge hook globally
|
|
54
|
-
* @param {string} hookName - The name of the hook to remove
|
|
55
|
-
* @returns {boolean} True if hook was removed, false if not found
|
|
56
|
-
*
|
|
57
|
-
* @example
|
|
58
|
-
* const removed = await deregisterHook('test-hook');
|
|
59
|
-
* console.log('Hook removed:', removed);
|
|
60
|
-
*/
|
|
61
|
-
export async function deregisterHook(hookName) {
|
|
62
|
-
if (!globalHookManager) {
|
|
63
|
-
return false;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return globalHookManager.removeKnowledgeHook(hookName);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Manually evaluate a hook against given data
|
|
71
|
-
* @param {Object} hook - The hook to evaluate
|
|
72
|
-
* @param {Store} store - The RDF store to evaluate against
|
|
73
|
-
* @param {Object} context - Additional context for evaluation
|
|
74
|
-
* @returns {Object} Evaluation result
|
|
75
|
-
*
|
|
76
|
-
* @example
|
|
77
|
-
* const result = await evaluateHook(hook, store, { timestamp: Date.now() });
|
|
78
|
-
* console.log('Hook evaluation result:', result);
|
|
79
|
-
*/
|
|
80
|
-
export async function evaluateHook(hook, store, context = {}) {
|
|
81
|
-
// Validate hook if needed
|
|
82
|
-
const validatedHook = typeof hook === 'object' && !hook._validated ? defineHook(hook) : hook;
|
|
83
|
-
|
|
84
|
-
// Create a temporary manager for evaluation
|
|
85
|
-
const tempManager = new KnowledgeHookManager({ enableKnowledgeHooks: true });
|
|
86
|
-
|
|
87
|
-
try {
|
|
88
|
-
// Add hook temporarily
|
|
89
|
-
tempManager.addKnowledgeHook(validatedHook);
|
|
90
|
-
|
|
91
|
-
// Evaluate the hook
|
|
92
|
-
const event = {
|
|
93
|
-
store,
|
|
94
|
-
context,
|
|
95
|
-
timestamp: Date.now(),
|
|
96
|
-
hookName: validatedHook.meta.name,
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
// Run the hook evaluation logic
|
|
100
|
-
const conditionResult = await tempManager.conditionEvaluator.isSatisfied(
|
|
101
|
-
validatedHook.when,
|
|
102
|
-
store,
|
|
103
|
-
context
|
|
104
|
-
);
|
|
105
|
-
|
|
106
|
-
event.result = conditionResult;
|
|
107
|
-
event.satisfied = conditionResult === true;
|
|
108
|
-
|
|
109
|
-
// Execute hook if condition is satisfied
|
|
110
|
-
if (event.satisfied && validatedHook.run) {
|
|
111
|
-
event.output = await validatedHook.run(event);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
return event;
|
|
115
|
-
} catch (error) {
|
|
116
|
-
return {
|
|
117
|
-
error: error.message,
|
|
118
|
-
hookName: validatedHook.meta.name,
|
|
119
|
-
timestamp: Date.now(),
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Get all registered hooks
|
|
126
|
-
* @returns {Array} Array of registered hook names
|
|
127
|
-
*/
|
|
128
|
-
export function getRegisteredHooks() {
|
|
129
|
-
if (!globalHookManager) {
|
|
130
|
-
return [];
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
return Array.from(globalHookManager.knowledgeHooks.keys());
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Reset the global hook manager
|
|
138
|
-
* Useful for testing or cleanup
|
|
139
|
-
*/
|
|
140
|
-
export function resetGlobalHookManager() {
|
|
141
|
-
globalHookManager = null;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
export default {
|
|
145
|
-
registerHook,
|
|
146
|
-
deregisterHook,
|
|
147
|
-
evaluateHook,
|
|
148
|
-
getRegisteredHooks,
|
|
149
|
-
resetGlobalHookManager,
|
|
150
|
-
};
|
package/src/ken-parliment.mjs
DELETED
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file ken-parliament-debug.mjs
|
|
3
|
-
* @description Debugging version of Parliamentary Swarm Demo with Robert's Rules
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { UnrdfDataFactory as DataFactory } from '@unrdf/core/rdf/n3-justified-only';
|
|
7
|
-
import { createStore } from '@unrdf/oxigraph'; // TODO: Replace with Oxigraph Store
|
|
8
|
-
import { TransactionManager, printReceipt } from './knowledge-engine.mjs';
|
|
9
|
-
|
|
10
|
-
const { namedNode, literal, quad } = DataFactory;
|
|
11
|
-
|
|
12
|
-
async function main() {
|
|
13
|
-
console.log('🏛️ Starting Parliamentary Swarm Demo (Debug Mode)...\n');
|
|
14
|
-
|
|
15
|
-
const store = createStore();
|
|
16
|
-
const tx = new TransactionManager();
|
|
17
|
-
const ex = 'http://example.org/';
|
|
18
|
-
|
|
19
|
-
// === Hooks ===
|
|
20
|
-
tx.addHook({
|
|
21
|
-
id: 'motion-must-be-seconded',
|
|
22
|
-
mode: 'pre',
|
|
23
|
-
condition: async (store, delta) => {
|
|
24
|
-
const adoptions = delta.additions.filter(q => q.predicate.value === `${ex}adoptMotion`);
|
|
25
|
-
for (const adoption of adoptions) {
|
|
26
|
-
const motion = adoption.subject;
|
|
27
|
-
const seconds = store.getQuads(motion, namedNode(`${ex}secondedBy`), null, null);
|
|
28
|
-
console.log(`🔎 Hook check: ${motion.value} has ${seconds.length} seconds in store.`);
|
|
29
|
-
if (seconds.length === 0) return false;
|
|
30
|
-
}
|
|
31
|
-
return true;
|
|
32
|
-
},
|
|
33
|
-
effect: 'veto',
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
tx.addHook({
|
|
37
|
-
id: 'vote-before-adoption',
|
|
38
|
-
mode: 'pre',
|
|
39
|
-
condition: async (store, delta) => {
|
|
40
|
-
const adoptions = delta.additions.filter(q => q.predicate.value === `${ex}adoptMotion`);
|
|
41
|
-
for (const adoption of adoptions) {
|
|
42
|
-
const motion = adoption.subject;
|
|
43
|
-
const votes = store.getQuads(motion, namedNode(`${ex}votedBy`), null, null);
|
|
44
|
-
console.log(`🔎 Hook check: ${motion.value} has ${votes.length} votes in store.`);
|
|
45
|
-
if (votes.length === 0) return false;
|
|
46
|
-
}
|
|
47
|
-
return true;
|
|
48
|
-
},
|
|
49
|
-
effect: 'veto',
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
tx.addHook({
|
|
53
|
-
id: 'audit-log',
|
|
54
|
-
mode: 'post',
|
|
55
|
-
condition: async () => true,
|
|
56
|
-
effect: async (_store, delta) => {
|
|
57
|
-
delta.additions.forEach(q => {
|
|
58
|
-
console.log(`🪵 Audit: ${q.subject.value} ${q.predicate.value} ${q.object.value}`);
|
|
59
|
-
});
|
|
60
|
-
},
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
// === Helper to apply commits ===
|
|
64
|
-
async function commit(description, additions, actor) {
|
|
65
|
-
console.log(`\n🤖 ${description}`);
|
|
66
|
-
const delta = { additions, removals: [] };
|
|
67
|
-
const { receipt, store: updatedStore } = await tx.apply(store, delta, {
|
|
68
|
-
actor,
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
// Dump motion state after each commit
|
|
72
|
-
const motion1Quads = updatedStore.getQuads(namedNode(`${ex}motion1`), null, null, null);
|
|
73
|
-
console.log('📊 Current motion1 state:');
|
|
74
|
-
motion1Quads.forEach(q =>
|
|
75
|
-
console.log(` • ${q.subject.value} ${q.predicate.value} ${q.object.value}`)
|
|
76
|
-
);
|
|
77
|
-
|
|
78
|
-
// Use the new printReceipt helper
|
|
79
|
-
printReceipt(receipt, { verbose: true });
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// === Scenario ===
|
|
83
|
-
await commit(
|
|
84
|
-
'PlannerAgent proposes: Introduce motion1: fund AI project',
|
|
85
|
-
[quad(namedNode(`${ex}motion1`), namedNode(`${ex}introducedBy`), literal('PlannerAgent'))],
|
|
86
|
-
'PlannerAgent'
|
|
87
|
-
);
|
|
88
|
-
|
|
89
|
-
await commit(
|
|
90
|
-
'ResearchAgent proposes: Second motion1',
|
|
91
|
-
[quad(namedNode(`${ex}motion1`), namedNode(`${ex}secondedBy`), literal('ResearchAgent'))],
|
|
92
|
-
'ResearchAgent'
|
|
93
|
-
);
|
|
94
|
-
|
|
95
|
-
await commit(
|
|
96
|
-
'CoderAgent proposes: Vote YES on motion1',
|
|
97
|
-
[quad(namedNode(`${ex}motion1`), namedNode(`${ex}votedBy`), literal('CoderAgent'))],
|
|
98
|
-
'CoderAgent'
|
|
99
|
-
);
|
|
100
|
-
|
|
101
|
-
await commit(
|
|
102
|
-
'PlannerAgent proposes: Adopt motion1',
|
|
103
|
-
[quad(namedNode(`${ex}motion1`), namedNode(`${ex}adoptMotion`), literal('PlannerAgent'))],
|
|
104
|
-
'PlannerAgent'
|
|
105
|
-
);
|
|
106
|
-
|
|
107
|
-
await commit(
|
|
108
|
-
'AdversarialAgent proposes: Adopt motion2 (no process)',
|
|
109
|
-
[quad(namedNode(`${ex}motion2`), namedNode(`${ex}adoptMotion`), literal('AdversarialAgent'))],
|
|
110
|
-
'AdversarialAgent'
|
|
111
|
-
);
|
|
112
|
-
|
|
113
|
-
console.log('\n✅ Debug demo complete.');
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
main().catch(err => {
|
|
117
|
-
console.error('❌ Demo failed:', err);
|
|
118
|
-
process.exit(1);
|
|
119
|
-
});
|
package/src/ken.mjs
DELETED
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file Knowledge Engine Bulk Example with Assertions
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
_parseTurtle,
|
|
7
|
-
_toTurtle,
|
|
8
|
-
query,
|
|
9
|
-
validateShacl,
|
|
10
|
-
reason,
|
|
11
|
-
canonicalize,
|
|
12
|
-
isIsomorphic,
|
|
13
|
-
TransactionManager,
|
|
14
|
-
} from './knowledge-engine.mjs';
|
|
15
|
-
|
|
16
|
-
import { UnrdfDataFactory as DataFactory } from '@unrdf/core/rdf/n3-justified-only';
|
|
17
|
-
import { createStore } from '@unrdf/oxigraph'; // TODO: Replace with Oxigraph Store
|
|
18
|
-
import { faker } from '@faker-js/faker';
|
|
19
|
-
import assert from 'assert';
|
|
20
|
-
|
|
21
|
-
const { namedNode, literal, quad } = DataFactory;
|
|
22
|
-
|
|
23
|
-
async function generatePeople(count) {
|
|
24
|
-
const store = createStore();
|
|
25
|
-
const ex = 'http://example.org/';
|
|
26
|
-
|
|
27
|
-
for (let i = 0; i < count; i++) {
|
|
28
|
-
const id = faker.string.uuid();
|
|
29
|
-
const iri = namedNode(`${ex}person-${id}`);
|
|
30
|
-
const name = literal(faker.person.firstName());
|
|
31
|
-
const age = literal(
|
|
32
|
-
faker.number.int({ min: 18, max: 90 }).toString(),
|
|
33
|
-
namedNode('http://www.w3.org/2001/XMLSchema#integer')
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
store.addQuad(iri, namedNode(`${ex}type`), namedNode(`${ex}Person`));
|
|
37
|
-
store.addQuad(iri, namedNode(`${ex}name`), name);
|
|
38
|
-
store.addQuad(iri, namedNode(`${ex}age`), age);
|
|
39
|
-
|
|
40
|
-
if (i > 0 && Math.random() > 0.5) {
|
|
41
|
-
const otherIndex = Math.floor(Math.random() * i);
|
|
42
|
-
const otherIri = namedNode(`${ex}person-${otherIndex}`);
|
|
43
|
-
store.addQuad(iri, namedNode(`${ex}knows`), otherIri);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return store;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
async function main() {
|
|
51
|
-
const bulkStore = await generatePeople(50);
|
|
52
|
-
console.log('Generated bulk store size:', bulkStore.size);
|
|
53
|
-
|
|
54
|
-
// === Assertion 1: Store has expected number of quads ===
|
|
55
|
-
assert(bulkStore.size >= 150, 'Store should have at least 3 triples per person');
|
|
56
|
-
|
|
57
|
-
// === SPARQL Query ===
|
|
58
|
-
const rows = await query(
|
|
59
|
-
bulkStore,
|
|
60
|
-
`
|
|
61
|
-
PREFIX ex: <http://example.org/>
|
|
62
|
-
SELECT ?person ?name ?age WHERE {
|
|
63
|
-
?person ex:name ?name ;
|
|
64
|
-
ex:age ?age .
|
|
65
|
-
} LIMIT 5
|
|
66
|
-
`
|
|
67
|
-
);
|
|
68
|
-
console.log('SPARQL query results:', rows);
|
|
69
|
-
assert(rows.length > 0, 'SPARQL query should return at least 1 result');
|
|
70
|
-
rows.forEach(r => {
|
|
71
|
-
console.log('Row:', r);
|
|
72
|
-
assert(r.name && r.name !== '[object Object]', 'Each row should have a name');
|
|
73
|
-
assert(r.age && r.age !== '[object Object]', 'Each row should have an age');
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
// === SHACL Validation ===
|
|
77
|
-
const shapesTtl = `
|
|
78
|
-
@prefix sh: <http://www.w3.org/ns/shacl#> .
|
|
79
|
-
@prefix ex: <http://example.org/> .
|
|
80
|
-
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
|
|
81
|
-
|
|
82
|
-
ex:PersonShape a sh:NodeShape ;
|
|
83
|
-
sh:targetClass ex:Person ;
|
|
84
|
-
sh:property [
|
|
85
|
-
sh:path ex:name ;
|
|
86
|
-
sh:datatype xsd:string ;
|
|
87
|
-
sh:minCount 1
|
|
88
|
-
] ;
|
|
89
|
-
sh:property [
|
|
90
|
-
sh:path ex:age ;
|
|
91
|
-
sh:datatype xsd:integer ;
|
|
92
|
-
sh:minInclusive 0
|
|
93
|
-
] .
|
|
94
|
-
`;
|
|
95
|
-
const report = validateShacl(bulkStore, shapesTtl);
|
|
96
|
-
console.log('SHACL validation report:', report);
|
|
97
|
-
// SHACL validation may return undefined for conforms, so we check that there are no results
|
|
98
|
-
assert(report.conforms !== false, 'SHACL validation should not have violations');
|
|
99
|
-
assert(report.results.length === 0, 'SHACL validation should have no validation results');
|
|
100
|
-
|
|
101
|
-
// === Reasoning ===
|
|
102
|
-
const rulesTtl = `
|
|
103
|
-
@prefix ex: <http://example.org/> .
|
|
104
|
-
{ ?x ex:knows ?y } => { ?y ex:knows ?x } .
|
|
105
|
-
`;
|
|
106
|
-
const reasonedStore = await reason(bulkStore, rulesTtl);
|
|
107
|
-
assert(reasonedStore.size >= bulkStore.size, 'Reasoned store should be same size or larger');
|
|
108
|
-
|
|
109
|
-
// === Canonicalization & Isomorphism ===
|
|
110
|
-
const canonical = await canonicalize(bulkStore);
|
|
111
|
-
assert(canonical.length > 0, 'Canonicalization should produce non-empty output');
|
|
112
|
-
|
|
113
|
-
const copy = createStore(bulkStore.getQuads());
|
|
114
|
-
const iso = await isIsomorphic(bulkStore, copy);
|
|
115
|
-
assert.strictEqual(iso, true, 'Copy of store should be isomorphic');
|
|
116
|
-
|
|
117
|
-
// === Transactions ===
|
|
118
|
-
const tx = new TransactionManager();
|
|
119
|
-
tx.addHook({
|
|
120
|
-
id: 'no-teenagers',
|
|
121
|
-
mode: 'pre',
|
|
122
|
-
condition: async (_store, delta) => {
|
|
123
|
-
return !delta.additions.some(
|
|
124
|
-
q => q.predicate.value.endsWith('age') && parseInt(q.object.value) < 18
|
|
125
|
-
);
|
|
126
|
-
},
|
|
127
|
-
effect: 'veto',
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
const delta = {
|
|
131
|
-
additions: [
|
|
132
|
-
quad(
|
|
133
|
-
namedNode('http://example.org/person-extra'),
|
|
134
|
-
namedNode('http://example.org/age'),
|
|
135
|
-
literal('15')
|
|
136
|
-
),
|
|
137
|
-
],
|
|
138
|
-
removals: [],
|
|
139
|
-
};
|
|
140
|
-
const { receipt } = await tx.apply(bulkStore, delta);
|
|
141
|
-
assert.strictEqual(receipt.committed, false, 'Transaction with underage person should be vetoed');
|
|
142
|
-
|
|
143
|
-
console.log('✅ All assertions passed successfully.');
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
main().catch(err => {
|
|
147
|
-
console.error('❌ Assertion failed:', err.message);
|
|
148
|
-
process.exit(1);
|
|
149
|
-
});
|
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file Built-in RDFS Inference Rules
|
|
3
|
-
* @module @unrdf/knowledge-engine/builtin-rules
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { defineRule } from './rules.mjs';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* RDFS SubClass inference rule
|
|
10
|
-
* If A rdfs:subClassOf B and X rdf:type A, then infer X rdf:type B
|
|
11
|
-
*/
|
|
12
|
-
export const rdfsSubClassRule = defineRule({
|
|
13
|
-
name: 'rdfs:subClassOf',
|
|
14
|
-
description: 'Infer type from subclass hierarchy',
|
|
15
|
-
pattern: [
|
|
16
|
-
{ subject: '?subClass', predicate: 'rdfs:subClassOf', object: '?superClass' },
|
|
17
|
-
{ subject: '?instance', predicate: 'rdf:type', object: '?subClass' },
|
|
18
|
-
],
|
|
19
|
-
consequent: {
|
|
20
|
-
subject: '?instance',
|
|
21
|
-
predicate: 'rdf:type',
|
|
22
|
-
object: '?superClass',
|
|
23
|
-
},
|
|
24
|
-
salience: 80,
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* RDFS SubProperty inference rule
|
|
29
|
-
* If P rdfs:subPropertyOf Q and X P Y, then infer X Q Y
|
|
30
|
-
*/
|
|
31
|
-
export const rdfsSubPropertyRule = defineRule({
|
|
32
|
-
name: 'rdfs:subPropertyOf',
|
|
33
|
-
description: 'Infer property from subproperty hierarchy',
|
|
34
|
-
pattern: [
|
|
35
|
-
{ subject: '?subProp', predicate: 'rdfs:subPropertyOf', object: '?superProp' },
|
|
36
|
-
{ subject: '?x', predicate: '?subProp', object: '?y' },
|
|
37
|
-
],
|
|
38
|
-
consequent: {
|
|
39
|
-
subject: '?x',
|
|
40
|
-
predicate: '?superProp',
|
|
41
|
-
object: '?y',
|
|
42
|
-
},
|
|
43
|
-
salience: 75,
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* RDFS Domain inference rule
|
|
48
|
-
* If P rdfs:domain C and X P Y, then infer X rdf:type C
|
|
49
|
-
*/
|
|
50
|
-
export const rdfsDomainRule = defineRule({
|
|
51
|
-
name: 'rdfs:domain',
|
|
52
|
-
description: 'Infer type from property domain',
|
|
53
|
-
pattern: [
|
|
54
|
-
{ subject: '?property', predicate: 'rdfs:domain', object: '?class' },
|
|
55
|
-
{ subject: '?x', predicate: '?property', object: '?y' },
|
|
56
|
-
],
|
|
57
|
-
consequent: {
|
|
58
|
-
subject: '?x',
|
|
59
|
-
predicate: 'rdf:type',
|
|
60
|
-
object: '?class',
|
|
61
|
-
},
|
|
62
|
-
salience: 70,
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* RDFS Range inference rule
|
|
67
|
-
* If P rdfs:range C and X P Y, then infer Y rdf:type C
|
|
68
|
-
*/
|
|
69
|
-
export const rdfsRangeRule = defineRule({
|
|
70
|
-
name: 'rdfs:range',
|
|
71
|
-
description: 'Infer type from property range',
|
|
72
|
-
pattern: [
|
|
73
|
-
{ subject: '?property', predicate: 'rdfs:range', object: '?class' },
|
|
74
|
-
{ subject: '?x', predicate: '?property', object: '?y' },
|
|
75
|
-
],
|
|
76
|
-
consequent: {
|
|
77
|
-
subject: '?y',
|
|
78
|
-
predicate: 'rdf:type',
|
|
79
|
-
object: '?class',
|
|
80
|
-
},
|
|
81
|
-
salience: 70,
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* OWL Transitive Property rule
|
|
86
|
-
* If P rdf:type owl:TransitiveProperty and X P Y and Y P Z, then infer X P Z
|
|
87
|
-
*/
|
|
88
|
-
export const owlTransitiveRule = defineRule({
|
|
89
|
-
name: 'owl:TransitiveProperty',
|
|
90
|
-
description: 'Apply transitive property closure',
|
|
91
|
-
pattern: [
|
|
92
|
-
{ subject: '?property', predicate: 'rdf:type', object: 'owl:TransitiveProperty' },
|
|
93
|
-
{ subject: '?x', predicate: '?property', object: '?y' },
|
|
94
|
-
{ subject: '?y', predicate: '?property', object: '?z' },
|
|
95
|
-
],
|
|
96
|
-
consequent: {
|
|
97
|
-
subject: '?x',
|
|
98
|
-
predicate: '?property',
|
|
99
|
-
object: '?z',
|
|
100
|
-
},
|
|
101
|
-
salience: 60,
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* OWL Symmetric Property rule
|
|
106
|
-
* If P rdf:type owl:SymmetricProperty and X P Y, then infer Y P X
|
|
107
|
-
*/
|
|
108
|
-
export const owlSymmetricRule = defineRule({
|
|
109
|
-
name: 'owl:SymmetricProperty',
|
|
110
|
-
description: 'Apply symmetric property',
|
|
111
|
-
pattern: [
|
|
112
|
-
{ subject: '?property', predicate: 'rdf:type', object: 'owl:SymmetricProperty' },
|
|
113
|
-
{ subject: '?x', predicate: '?property', object: '?y' },
|
|
114
|
-
],
|
|
115
|
-
consequent: {
|
|
116
|
-
subject: '?y',
|
|
117
|
-
predicate: '?property',
|
|
118
|
-
object: '?x',
|
|
119
|
-
},
|
|
120
|
-
salience: 65,
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* OWL Inverse Property rule
|
|
125
|
-
* If P owl:inverseOf Q and X P Y, then infer Y Q X
|
|
126
|
-
*/
|
|
127
|
-
export const owlInverseRule = defineRule({
|
|
128
|
-
name: 'owl:inverseOf',
|
|
129
|
-
description: 'Apply inverse property',
|
|
130
|
-
pattern: [
|
|
131
|
-
{ subject: '?p', predicate: 'owl:inverseOf', object: '?q' },
|
|
132
|
-
{ subject: '?x', predicate: '?p', object: '?y' },
|
|
133
|
-
],
|
|
134
|
-
consequent: {
|
|
135
|
-
subject: '?y',
|
|
136
|
-
predicate: '?q',
|
|
137
|
-
object: '?x',
|
|
138
|
-
},
|
|
139
|
-
salience: 65,
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Collection of all built-in RDFS/OWL rules
|
|
144
|
-
*/
|
|
145
|
-
export const builtinRules = [
|
|
146
|
-
rdfsSubClassRule,
|
|
147
|
-
rdfsSubPropertyRule,
|
|
148
|
-
rdfsDomainRule,
|
|
149
|
-
rdfsRangeRule,
|
|
150
|
-
owlTransitiveRule,
|
|
151
|
-
owlSymmetricRule,
|
|
152
|
-
owlInverseRule,
|
|
153
|
-
];
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* Get all built-in rules
|
|
157
|
-
*
|
|
158
|
-
* @returns {Object[]} Array of built-in rules
|
|
159
|
-
*
|
|
160
|
-
* @example
|
|
161
|
-
* const rules = getBuiltinRules();
|
|
162
|
-
* addRules(engine, rules);
|
|
163
|
-
*/
|
|
164
|
-
export function getBuiltinRules() {
|
|
165
|
-
return builtinRules;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* Get RDFS rules only (no OWL)
|
|
170
|
-
*
|
|
171
|
-
* @returns {Object[]} Array of RDFS rules
|
|
172
|
-
*
|
|
173
|
-
* @example
|
|
174
|
-
* const rdfsRules = getRDFSRules();
|
|
175
|
-
*/
|
|
176
|
-
export function getRDFSRules() {
|
|
177
|
-
return [rdfsSubClassRule, rdfsSubPropertyRule, rdfsDomainRule, rdfsRangeRule];
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Get OWL rules only
|
|
182
|
-
*
|
|
183
|
-
* @returns {Object[]} Array of OWL rules
|
|
184
|
-
*
|
|
185
|
-
* @example
|
|
186
|
-
* const owlRules = getOWLRules();
|
|
187
|
-
*/
|
|
188
|
-
export function getOWLRules() {
|
|
189
|
-
return [owlTransitiveRule, owlSymmetricRule, owlInverseRule];
|
|
190
|
-
}
|