eyeling 1.26.6 → 1.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/HANDBOOK.md +100 -3
- package/dist/browser/eyeling.browser.js +396 -3
- package/examples/deck/act-barley-seed-lineage.md +1 -1
- package/examples/deck/faltings-genus2-finiteness.md +1 -1
- package/examples/deck/high-trust-rdf-bloom-envelope.md +1 -1
- package/examples/deck/odrl-dpv-risk-ranked.md +1 -1
- package/examples/deck/rdf-message-cold-chain-recall.md +71 -0
- package/examples/deck/rdf-message-flow.md +1 -1
- package/examples/deck/rdf-message-ldes-incremental.md +94 -0
- package/examples/deck/rdf-message-window-repair.md +175 -0
- package/examples/deck/schema-foaf-mapping.md +2 -0
- package/examples/input/rdf-message-cold-chain-recall.trig +668 -0
- package/examples/input/rdf-message-flow.trig +3 -0
- package/examples/input/rdf-message-ldes-incremental.trig +564 -0
- package/examples/input/rdf-message-microgrid.trig +3 -0
- package/examples/input/rdf-message-window-repair.trig +82 -0
- package/examples/input/rdf-messages.trig +3 -0
- package/examples/output/rdf-message-cold-chain-recall.md +13 -0
- package/examples/output/rdf-message-ldes-incremental.md +13 -0
- package/examples/output/rdf-message-window-repair.md +13 -0
- package/examples/rdf-message-cold-chain-recall.n3 +229 -0
- package/examples/rdf-message-flow.n3 +3 -0
- package/examples/rdf-message-ldes-incremental.n3 +231 -0
- package/examples/rdf-message-microgrid.n3 +3 -0
- package/examples/rdf-message-window-repair.n3 +166 -0
- package/examples/rdf-messages.n3 +3 -0
- package/eyeling.js +396 -3
- package/lib/cli.js +396 -3
- package/package.json +5 -3
- package/test/examples.test.js +25 -14
- package/test/fixtures/marc-rules-stream-messages.n3 +192 -0
- package/test/stream_messages.test.js +243 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# RDF Message Cold Chain Recall
|
|
2
|
+
|
|
3
|
+
This deck follows a cold-chain stream where the cost of a wrong conclusion is concrete: either release a shipment or quarantine it. The [rules](../rdf-message-cold-chain-recall.n3) replay the LDES [message log input](../input/rdf-message-cold-chain-recall.trig), the [golden output](../output/rdf-message-cold-chain-recall.md) records the repaired decision, and the [handbook section](https://eyereasoner.github.io/eyeling/HANDBOOK#rdf-message-log-replay-under--r) explains how `-r` exposes RDF Message boundaries to the rules.
|
|
4
|
+
|
|
5
|
+
## Why this example exists
|
|
6
|
+
|
|
7
|
+
A cold-chain monitor receives a long telemetry stream for a medicine batch.
|
|
8
|
+
|
|
9
|
+
Most readings are old and already materialized. The consumer has a checkpoint, so reloading and rechecking the whole stream would be wasteful. But the new tail is not clean: one message says the batch remained in range, while another says it crossed the temperature limit.
|
|
10
|
+
|
|
11
|
+
The example shows why streaming RDF reasoning needs three things together:
|
|
12
|
+
|
|
13
|
+
1. message boundaries, so the rules know which facts arrived together;
|
|
14
|
+
2. LDES sequence metadata, so the consumer resumes after a checkpoint;
|
|
15
|
+
3. a repair policy, so contradictory tail evidence is fixed before an operational decision is emitted.
|
|
16
|
+
|
|
17
|
+
## The story
|
|
18
|
+
|
|
19
|
+
`batchA` is moving through a cold-chain route.
|
|
20
|
+
|
|
21
|
+
The stream contains forty-eight telemetry observations. The first forty-two were already processed in an earlier synchronization run:
|
|
22
|
+
|
|
23
|
+
```turtle
|
|
24
|
+
:telemetryStream :lastCommittedSequence 42 .
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
That leaves only messages `43..48` for the current incremental repair window.
|
|
28
|
+
|
|
29
|
+
## The contradiction
|
|
30
|
+
|
|
31
|
+
The new tail contains both kinds of evidence:
|
|
32
|
+
|
|
33
|
+
```turtle
|
|
34
|
+
:obs-043 :temperatureTenthC 45 . # 4.5°C, within range
|
|
35
|
+
:obs-047 :temperatureTenthC 118 . # 11.8°C, over the 8.0°C limit
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Flattening the tail would make the batch look both safe and unsafe.
|
|
39
|
+
|
|
40
|
+
## The repair
|
|
41
|
+
|
|
42
|
+
The repair policy is intentionally simple and auditable: for recall decisions, a calibrated cold-chain logger wins over lower-priority telemetry.
|
|
43
|
+
|
|
44
|
+
```turtle
|
|
45
|
+
:obs-047 :source "calibrated-cold-chain-logger" ;
|
|
46
|
+
:priority 5 ;
|
|
47
|
+
:calibrationClass :calibratedLogger .
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Because that repaired reading is over the limit, the materialized decision is:
|
|
51
|
+
|
|
52
|
+
> quarantine batchA, notify QA, and hold shipment
|
|
53
|
+
|
|
54
|
+
## Why this is a good streaming case
|
|
55
|
+
|
|
56
|
+
The example is not about proving that one temperature number is bigger than another.
|
|
57
|
+
|
|
58
|
+
It is about the shape of the pipeline:
|
|
59
|
+
|
|
60
|
+
- the stream can keep growing;
|
|
61
|
+
- the consumer can resume from a bookmark;
|
|
62
|
+
- old messages do not need to be reprocessed;
|
|
63
|
+
- the inconsistent new tail is repaired locally;
|
|
64
|
+
- the final output is based on the repaired state, not on the raw noisy merge.
|
|
65
|
+
|
|
66
|
+
## Run it
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
eyeling -r examples/rdf-message-cold-chain-recall.n3 \
|
|
70
|
+
examples/input/rdf-message-cold-chain-recall.trig
|
|
71
|
+
```
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# RDF Message Logs in Eyeling — from stream to reasoning
|
|
2
2
|
|
|
3
|
-
This deck
|
|
3
|
+
This deck reads alongside the [rules](../rdf-message-flow.n3) and the replayed [message log input](../input/rdf-message-flow.trig): the [golden output](../output/rdf-message-flow.md) shows what Eyeling derives once `-r` has exposed the RDF Message envelopes and payload graphs. The [handbook section](https://eyereasoner.github.io/eyeling/HANDBOOK#rdf-message-log-replay-under--r) explains that replay step in more detail.
|
|
4
4
|
|
|
5
5
|
The goal is to show, in plain language, how Eyeling can now read an RDF Message Log directly instead of asking the example data to describe its own message envelopes by hand.
|
|
6
6
|
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# RDF Message LDES Incremental Repair
|
|
2
|
+
|
|
3
|
+
This deck walks through a stream that is large enough to make full recomputation unattractive. The [rules](../rdf-message-ldes-incremental.n3) consume the replayed LDES [message log input](../input/rdf-message-ldes-incremental.trig), the [golden output](../output/rdf-message-ldes-incremental.md) shows the incremental repair result, and the [handbook section](https://eyereasoner.github.io/eyeling/HANDBOOK#rdf-message-log-replay-under--r) explains how `-r` turns RDF Message boundaries into facts for the rules.
|
|
4
|
+
|
|
5
|
+
## Why this example exists
|
|
6
|
+
|
|
7
|
+
A long-running stream should not force a reasoner to reload and re-check all past data every time a new event arrives.
|
|
8
|
+
|
|
9
|
+
This example shows the intended shape:
|
|
10
|
+
|
|
11
|
+
1. publish events as an append-only **LDES**;
|
|
12
|
+
2. serialize each emitted member as an **RDF Message**;
|
|
13
|
+
3. remember a sequence bookmark from the previous synchronization run;
|
|
14
|
+
4. reason only over the new tail;
|
|
15
|
+
5. repair a noisy inconsistency before materializing the operational result.
|
|
16
|
+
|
|
17
|
+
## The story
|
|
18
|
+
|
|
19
|
+
A building monitors a fire door, `doorA`.
|
|
20
|
+
|
|
21
|
+
The stream contains forty door observations. Most are boring historical facts that were already processed. The consumer has stored this checkpoint:
|
|
22
|
+
|
|
23
|
+
```turtle
|
|
24
|
+
:doorStream :lastCommittedSequence 34 .
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
So when the log is replayed, the reasoner can classify:
|
|
28
|
+
|
|
29
|
+
- sequences `1..34` as committed history;
|
|
30
|
+
- sequences `35..40` as newly emitted LDES members;
|
|
31
|
+
- the new tail as the current repair window.
|
|
32
|
+
|
|
33
|
+
## Why RDF Messages help
|
|
34
|
+
|
|
35
|
+
The input file is a real RDF Message Log:
|
|
36
|
+
|
|
37
|
+
```turtle
|
|
38
|
+
VERSION "1.2-messages"
|
|
39
|
+
...
|
|
40
|
+
MESSAGE
|
|
41
|
+
...
|
|
42
|
+
MESSAGE
|
|
43
|
+
...
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Eyeling's `-r` mode preserves those message boundaries as `eymsg:` envelopes and payload graphs. The rules inspect payloads with `log:includes`, so each member remains scoped to the message that emitted it.
|
|
47
|
+
|
|
48
|
+
Handbook: <https://eyereasoner.github.io/eyeling/HANDBOOK#rdf-message-log-replay-under--r>
|
|
49
|
+
|
|
50
|
+
## Why LDES helps
|
|
51
|
+
|
|
52
|
+
LDES contributes the stream shape:
|
|
53
|
+
|
|
54
|
+
```turtle
|
|
55
|
+
:doorStream a ldes:EventStream ;
|
|
56
|
+
ldes:timestampPath :observedAt ;
|
|
57
|
+
ldes:sequencePath :sequence ;
|
|
58
|
+
tree:member :obs-040 .
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
The stream is append-only, and each member has a sequence number. That sequence number is the incremental bookmark: a consumer that already committed `34` does not need to re-run the repair over members `1..34`.
|
|
62
|
+
|
|
63
|
+
LDES spec: <https://semiceu.github.io/LinkedDataEventStreams/releases/1.0.0-alpha/index.html>
|
|
64
|
+
|
|
65
|
+
## The inconsistency
|
|
66
|
+
|
|
67
|
+
The new tail contains contradictory evidence:
|
|
68
|
+
|
|
69
|
+
- the camera says `doorA` is `:open`;
|
|
70
|
+
- the latch says `doorA` is `:closed`;
|
|
71
|
+
- the safety controller also says `doorA` is `:closed`, with higher priority.
|
|
72
|
+
|
|
73
|
+
Raw materialization would say the same door is both open and closed.
|
|
74
|
+
|
|
75
|
+
## The repair
|
|
76
|
+
|
|
77
|
+
The preferred repair keeps the highest-priority tail assertion:
|
|
78
|
+
|
|
79
|
+
```turtle
|
|
80
|
+
:obs-040 :doorState :closed ;
|
|
81
|
+
:priority 5 ;
|
|
82
|
+
:source "safety-controller" .
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
The materialized action is therefore:
|
|
86
|
+
|
|
87
|
+
> keep the compartment sealed and continue monitoring
|
|
88
|
+
|
|
89
|
+
## Run it
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
eyeling -r examples/rdf-message-ldes-incremental.n3 \
|
|
93
|
+
examples/input/rdf-message-ldes-incremental.trig
|
|
94
|
+
```
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# RDF Message window repair — fixing an open/closed door conflict
|
|
2
|
+
|
|
3
|
+
This deck follows a small RDF Message window where one door is reported both open and closed. The [rules](../rdf-message-window-repair.n3) inspect the replayed [message log input](../input/rdf-message-window-repair.trig), the [golden output](../output/rdf-message-window-repair.md) shows the repaired conclusion, and the [handbook section](https://eyereasoner.github.io/eyeling/HANDBOOK#rdf-message-log-replay-under--r) explains how `-r` exposes message payloads without silently merging them.
|
|
4
|
+
|
|
5
|
+
The goal is to show how Eyeling can reason over a replayed RDF Message Log, keep message boundaries visible, detect an inconsistency in a sliding window, and materialize a repaired conclusion instead of blindly merging contradictory facts.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## The story
|
|
10
|
+
|
|
11
|
+
A building automation system receives RDF messages about a fire door.
|
|
12
|
+
|
|
13
|
+
The messages arrive from different devices:
|
|
14
|
+
|
|
15
|
+
- a corridor camera,
|
|
16
|
+
- a hallway latch sensor,
|
|
17
|
+
- and a safety controller.
|
|
18
|
+
|
|
19
|
+
Most of the time they agree. But in the example, the current message window says both of these things:
|
|
20
|
+
|
|
21
|
+
```text
|
|
22
|
+
doorA is open
|
|
23
|
+
doorA is closed
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
That is the inconsistency the example is meant to fix.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Why ordinary merging is not enough
|
|
31
|
+
|
|
32
|
+
If all messages are merged into one graph, the system sees both facts at once.
|
|
33
|
+
|
|
34
|
+
For safety automation, that is not a useful final state. The system needs a current operational conclusion, such as:
|
|
35
|
+
|
|
36
|
+
```text
|
|
37
|
+
mark the fire compartment as sealed
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
or:
|
|
41
|
+
|
|
42
|
+
```text
|
|
43
|
+
send a technician to inspect and close the fire door
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
The example therefore separates two steps:
|
|
47
|
+
|
|
48
|
+
1. detect the raw conflict,
|
|
49
|
+
2. repair it before producing the final action.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## The message log
|
|
54
|
+
|
|
55
|
+
The input file is a real RDF Message Log:
|
|
56
|
+
|
|
57
|
+
```trig
|
|
58
|
+
VERSION "1.2-messages"
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Each `MESSAGE` delimiter separates one communication event from the next.
|
|
62
|
+
|
|
63
|
+
Eyeling parses those delimiters before ordinary reasoning starts and exposes a replay model with `eymsg:` terms:
|
|
64
|
+
|
|
65
|
+
- one stream,
|
|
66
|
+
- one envelope per message,
|
|
67
|
+
- ordered envelope links,
|
|
68
|
+
- offsets,
|
|
69
|
+
- and one payload graph per non-empty message.
|
|
70
|
+
|
|
71
|
+
The rules reason over that replay model rather than pretending the stream was one big static graph.
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## The five messages
|
|
76
|
+
|
|
77
|
+
The log has five messages.
|
|
78
|
+
|
|
79
|
+
Message 1 is policy and vocabulary:
|
|
80
|
+
|
|
81
|
+
- the sliding ABox window has size 3,
|
|
82
|
+
- the repair policy prefers higher-priority evidence,
|
|
83
|
+
- `:open` and `:closed` map to operational action text.
|
|
84
|
+
|
|
85
|
+
Messages 2 to 5 are door-state assertions.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## The sliding windows
|
|
90
|
+
|
|
91
|
+
The previous window contains messages 2, 3, and 4.
|
|
92
|
+
|
|
93
|
+
The current window contains messages 3, 4, and 5.
|
|
94
|
+
|
|
95
|
+
So when the window advances:
|
|
96
|
+
|
|
97
|
+
- message 2 expires,
|
|
98
|
+
- messages 3 and 4 are retained,
|
|
99
|
+
- message 5 enters.
|
|
100
|
+
|
|
101
|
+
This is the small stream-reasoning shape the example demonstrates.
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## The inconsistency
|
|
106
|
+
|
|
107
|
+
In the current window:
|
|
108
|
+
|
|
109
|
+
- message 3 says `doorA` is `:open`,
|
|
110
|
+
- message 4 says `doorA` is `:closed`,
|
|
111
|
+
- message 5 also says `doorA` is `:closed`.
|
|
112
|
+
|
|
113
|
+
The raw materialized window therefore contains an open/closed contradiction.
|
|
114
|
+
|
|
115
|
+
The example records this explicitly as:
|
|
116
|
+
|
|
117
|
+
```n3
|
|
118
|
+
:currentWindow :rawConflict :doorOpenAndClosed .
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## The repair policy
|
|
124
|
+
|
|
125
|
+
The repair policy is deliberately simple:
|
|
126
|
+
|
|
127
|
+
> If two current-window assertions conflict, keep the one with the higher priority.
|
|
128
|
+
|
|
129
|
+
The camera and latch readings have priority 1.
|
|
130
|
+
|
|
131
|
+
The safety-controller reading has priority 3.
|
|
132
|
+
|
|
133
|
+
So the repaired state is:
|
|
134
|
+
|
|
135
|
+
```text
|
|
136
|
+
doorA is closed
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
The lower-priority conflicting open assertion is still visible as rejected evidence; it is not silently erased.
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## The final materialization
|
|
144
|
+
|
|
145
|
+
After repair, the rules derive the final action from the repaired state, not from the inconsistent raw window.
|
|
146
|
+
|
|
147
|
+
For this data, the final action is:
|
|
148
|
+
|
|
149
|
+
```text
|
|
150
|
+
mark the fire compartment as sealed
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
That conclusion is only produced after the example has shown all of these things:
|
|
154
|
+
|
|
155
|
+
- the RDF Message Log was replayed,
|
|
156
|
+
- the sliding windows were constructed,
|
|
157
|
+
- the raw open/closed conflict was detected,
|
|
158
|
+
- the preferred repair selected the higher-priority assertion,
|
|
159
|
+
- and the repaired state was materialized.
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## What this example is useful for
|
|
164
|
+
|
|
165
|
+
This is a compact pattern for stream-style reasoning with noisy inputs.
|
|
166
|
+
|
|
167
|
+
It shows that RDF messages can be used as more than a transport format: their boundaries become part of the evidence.
|
|
168
|
+
|
|
169
|
+
That makes it possible to explain conclusions in terms of:
|
|
170
|
+
|
|
171
|
+
- which message arrived,
|
|
172
|
+
- which window it belonged to,
|
|
173
|
+
- whether it expired, was retained, or entered,
|
|
174
|
+
- whether it conflicted with another message,
|
|
175
|
+
- and why one assertion was preferred over another.
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Mapping two data models (beginner-friendly)
|
|
2
2
|
|
|
3
|
+
[Start with the source](../schema-foaf-mapping.n3) to see the vocabulary mapping rules; the [golden output](../output/schema-foaf-mapping.n3) shows the FOAF-shaped facts derived from the Schema.org-shaped input.
|
|
4
|
+
|
|
3
5
|
When people say “map two data models,” they mean:
|
|
4
6
|
|
|
5
7
|
> **Taking data described using one vocabulary (Model A) and expressing the same meaning using another vocabulary (Model B).**
|