eyeling 1.26.6 → 1.26.7

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 CHANGED
@@ -236,7 +236,15 @@ The lexer turns the input into tokens like:
236
236
 
237
237
  Parsing becomes dramatically simpler because tokenization already decided where strings end, where numbers are, and so on.
238
238
 
239
- By default, Eyeling parses ordinary N3. Selected RDF/TriG surface syntax is accepted only when RDF compatibility is explicitly enabled with `eyeling -r file.trig`, `eyeling --rdf file.trig`, or API option `{ rdf: true }`. In that mode, the lexer normalizes RDF/TriG input syntax to ordinary N3 graph terms before normal parsing, and the printer emits RDF/TriG-compatible output where feasible. Eyeling remains an N3 reasoner; this is syntax compatibility, not a separate RDF dataset reasoning model.
239
+ By default, Eyeling parses ordinary N3. Selected RDF/TriG surface syntax is accepted only when RDF compatibility is explicitly enabled with `eyeling -r file.trig`, `eyeling --rdf file.trig`, or API option `{ rdf: true }`.
240
+
241
+ The `-r` flag does **not** switch Eyeling to a different RDF dataset reasoner. It adds a parser/printer compatibility layer around the same N3 engine:
242
+
243
+ 1. before normal parsing, RDF/TriG surface syntax is normalized into ordinary Eyeling N3 terms;
244
+ 2. the usual N3 parser, rule compiler, forward chainer, backward prover, builtins, and output rendering then run on that normalized program;
245
+ 3. when possible, final output is printed back in RDF/TriG-compatible syntax.
246
+
247
+ This matters because rules still reason over Eyeling's N3 term model. Named graphs become quoted formulas, RDF 1.2 triple terms become singleton quoted formulas, and RDF Message Logs become an explicit replay graph that ordinary N3 rules can consume.
240
248
 
241
249
  In RDF compatibility mode, RDF 1.2 triple terms written as `<<( s p o )>>`, plus the reified triple form `<<s p o ~ r>>`, are normalized to Eyeling's existing singleton quoted-formula term `{ s p o }`. A reifier `r` is preserved as `r rdf:reifies { s p o }`. A leading `VERSION "1.2"` or `@version "1.2"` directive is ignored for the same reason. On output, `--rdf` converts a singleton graph term back to `<<( ... )>>` only when its inner triple is valid as an RDF triple term; otherwise it stays in N3 graph-term form. It also prints `log:nameOf` graph-term triples back as TriG named graph blocks. For example:
242
250
 
@@ -266,7 +274,64 @@ is treated internally like:
266
274
  } .
267
275
  ```
268
276
 
269
- This keeps Eyeling's N3 model stable while allowing small RDF 1.1/RDF 1.2 dataset-shaped inputs to run through the existing `GraphTerm` machinery when the caller opts in. More exotic future RDF forms should be added only if they can be mapped cleanly onto Eyeling's quoted-formula term model.
277
+ A top-level default graph block is unwrapped into ordinary top-level triples. A named graph block is not merged into the default graph; it remains a quoted formula reachable through `log:nameOf`.
278
+
279
+ #### RDF Message Log replay under `-r`
280
+
281
+ If RDF compatibility mode sees a top-level message version directive such as:
282
+
283
+ ```trig
284
+ VERSION "1.2-messages"
285
+ ```
286
+
287
+ or the corresponding `@version` spelling, Eyeling treats the input as an RDF Message Log before ordinary N3 parsing starts. The accepted message-version strings are `"1.1-messages"`, `"1.2-messages"`, and `"1.2-basic-messages"`.
288
+
289
+ At top-level statement boundaries, `MESSAGE` and `@message` delimiters split the document into message chunks. The text before the first delimiter is the first message. An empty chunk is still a message: it is replayed as an empty heartbeat rather than being dropped. Directives and comments alone do not make a message non-empty.
290
+
291
+ Each chunk is then normalized separately using the same RDF/TriG compatibility rules. Eyeling also scopes blank-node labels per message, so reusing `_:x` in two different messages does not accidentally identify the same blank node across message boundaries.
292
+
293
+ The result of replay is not a hidden side channel. Eyeling materializes ordinary facts using the `eymsg:` vocabulary:
294
+
295
+ ```n3
296
+ @prefix eymsg: <https://eyereasoner.github.io/eyeling/vocab/message#>.
297
+
298
+ ?stream a eymsg:RDFMessageStream;
299
+ eymsg:messageCount ?count;
300
+ eymsg:orderedEnvelopes ?envelopes;
301
+ eymsg:firstEnvelope ?first;
302
+ eymsg:lastEnvelope ?last;
303
+ eymsg:envelope ?envelope.
304
+
305
+ ?envelope a eymsg:MessageEnvelope;
306
+ eymsg:offset ?n;
307
+ eymsg:payloadKind eymsg:nonEmpty;
308
+ eymsg:payloadGraph ?payload;
309
+ eymsg:nextEnvelope ?next.
310
+ ```
311
+
312
+ For an empty message, the envelope has `eymsg:payloadKind eymsg:empty` and no `eymsg:payloadGraph`. For a non-empty message, the payload is exposed as a named graph:
313
+
314
+ ```n3
315
+ ?payload log:nameOf {
316
+ ...the normalized message body...
317
+ } .
318
+ ```
319
+
320
+ That design is deliberate: message payload triples are **not silently merged** into the global fact store. Rules inspect a payload explicitly, usually with `log:nameOf` plus `log:includes`:
321
+
322
+ ```n3
323
+ {
324
+ ?envelope eymsg:payloadGraph ?payload.
325
+ ?payload log:nameOf ?payloadGraph.
326
+ ?payloadGraph log:includes { :doorA :state :closed }.
327
+ } => {
328
+ ?envelope :reportsClosed :doorA.
329
+ }.
330
+ ```
331
+
332
+ This is the important mental model for `-r` with RDF Messages: the parser preserves message order and message boundaries as data. Reasoning can then implement stream-like behavior—flow stages, sliding windows, heartbeats, conflict repair, replay audits—without the TriG sidecar having to invent envelope facts by hand.
333
+
334
+ This keeps Eyeling's N3 model stable while allowing small RDF 1.1/RDF 1.2 dataset-shaped and message-log-shaped inputs to run through the existing `GraphTerm` machinery when the caller opts in. More exotic future RDF forms should be added only if they can be mapped cleanly onto Eyeling's quoted-formula term model.
270
335
 
271
336
  ### 4.2 Parsing triples, with Turtle-style convenience
272
337
 
@@ -2557,6 +2622,7 @@ Options:
2557
2622
  -e, --enforce-https Rewrite http:// IRIs to https:// for log dereferencing builtins.
2558
2623
  -h, --help Show this help and exit.
2559
2624
  -p, --proof Enable proof explanations.
2625
+ -r, --rdf Enable RDF/TriG input/output compatibility.
2560
2626
  -s, --super-restricted Disable all builtins except => and <=.
2561
2627
  -t, --stream Stream derived triples as soon as they are derived.
2562
2628
  -v, --version Print version and exit.
@@ -2597,7 +2663,7 @@ Quoted graphs/formulas use `{ ... }`. Inside a quoted formula, directive scope m
2597
2663
 
2598
2664
  - `@prefix/@base` and `PREFIX/BASE` directives may appear at top level **or inside `{ ... }`**, and apply to the formula they occur in (formula-local scoping).
2599
2665
 
2600
- With `-r, --rdf` / `{ rdf: true }`, Eyeling also accepts RDF 1.2 triple-term surface forms such as `<<( s p o )>>` and `<<s p o ~ r>>` as compatibility spellings for a singleton quoted formula `{ s p o }`. In the same mode, feasible singleton graph terms are printed back as RDF 1.2 triple terms, while invalid cases such as a literal subject remain ordinary N3 graph terms. This is useful for inputs that use `rdf:reifies` or other predicates whose objects are RDF 1.2 triple terms, while keeping the default language and the rest of Eyeling on its N3 formula-term model.
2666
+ With `-r, --rdf` / `{ rdf: true }`, Eyeling accepts selected RDF/TriG surface syntax before normal N3 parsing. RDF 1.2 triple-term forms such as `<<( s p o )>>` and `<<s p o ~ r>>` are compatibility spellings for singleton quoted formulas such as `{ s p o }`; feasible singleton graph terms are printed back as RDF 1.2 triple terms. TriG named graph blocks become `log:nameOf` quoted formulas. If a `VERSION "1.2-messages"`-style directive is present, top-level `MESSAGE` delimiters are replayed as `eymsg:` stream/envelope facts and per-message payload graphs. See [Chapter 4.1](#41-lexing-tokens-not-magic) for the full `-r` model and RDF Message handling.
2601
2667
 
2602
2668
  For the formal grammar, see the N3 spec grammar:
2603
2669
 
@@ -0,0 +1,175 @@
1
+ # RDF Message window repair — fixing an open/closed door conflict
2
+
3
+ This deck explains the example `rdf-message-window-repair.n3` and its input file `input/rdf-message-window-repair.trig`.
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.
@@ -0,0 +1,79 @@
1
+ # =====================================
2
+ # RDF Message Window Repair message log
3
+ # =====================================
4
+ #
5
+ # This file is the data half of the runnable example:
6
+ #
7
+ # eyeling -r examples/rdf-message-window-repair.n3 examples/input/rdf-message-window-repair.trig
8
+ #
9
+ # The log models a fire-door monitoring ABox stream. Message 1 is stable
10
+ # configuration/TBox-like policy. Messages 2-5 are ordered ABox assertions. The
11
+ # rules use a sliding window over the last three ABox messages and repair a noisy
12
+ # contradiction by preferring the highest-priority assertion.
13
+
14
+ VERSION "1.2-messages"
15
+ PREFIX : <https://eyereasoner.github.io/eyeling/examples/rdf-message-window-repair#>
16
+ PREFIX see: <https://example.org/see#>
17
+ PREFIX in: <https://example.org/see/input#>
18
+ PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
19
+
20
+ # Message 1: fixed stream policy and action vocabulary.
21
+ :doorA a :FireDoor ;
22
+ :windowSize 3 ;
23
+ :repairPolicy :preferHigherPriority .
24
+
25
+ :open :actionText "send a technician to inspect and close the fire door";
26
+ :stateText "open" .
27
+ :closed :actionText "mark the fire compartment as sealed";
28
+ :stateText "closed" .
29
+
30
+ in:run a see:InputDataset ;
31
+ see:name "rdf_message_window_repair" ;
32
+ see:title "RDF Message Window Repair" ;
33
+ see:sourceFile "examples/rdf-message-window-repair.n3" ;
34
+ see:description "A true RDF 1.2 Message Log for sliding-window repair of an open/closed fire-door inconsistency." ;
35
+ see:compiler "Eyeling RDF Message Log input" .
36
+
37
+ MESSAGE
38
+
39
+ # Message 2: the previous window starts with a normal closed reading. It expires
40
+ # when the current window slides forward.
41
+ :reading-001 a :DoorAssertion ;
42
+ :about :doorA ;
43
+ :doorState :closed ;
44
+ :priority 1 ;
45
+ :source "hallway-latch" ;
46
+ :observedAt "2026-05-12T18:20:00Z"^^xsd:dateTime .
47
+
48
+ MESSAGE
49
+
50
+ # Message 3: overlapping evidence retained in the next window. The camera says
51
+ # the door is open.
52
+ :reading-002 a :DoorAssertion ;
53
+ :about :doorA ;
54
+ :doorState :open ;
55
+ :priority 1 ;
56
+ :source "corridor-camera" ;
57
+ :observedAt "2026-05-12T18:20:30Z"^^xsd:dateTime .
58
+
59
+ MESSAGE
60
+
61
+ # Message 4: another overlapping reading conflicts with message 3: the latch
62
+ # says the same door is closed.
63
+ :reading-003 a :DoorAssertion ;
64
+ :about :doorA ;
65
+ :doorState :closed ;
66
+ :priority 1 ;
67
+ :source "hallway-latch" ;
68
+ :observedAt "2026-05-12T18:21:00Z"^^xsd:dateTime .
69
+
70
+ MESSAGE
71
+
72
+ # Message 5: entering high-priority safety-controller assertion. The preferred
73
+ # repair keeps this assertion rather than the lower-priority conflicting fact.
74
+ :reading-004 a :DoorAssertion ;
75
+ :about :doorA ;
76
+ :doorState :closed ;
77
+ :priority 3 ;
78
+ :source "safety-controller" ;
79
+ :observedAt "2026-05-12T18:21:30Z"^^xsd:dateTime .
@@ -0,0 +1,13 @@
1
+ # rdf-message-window-repair
2
+
3
+ ## Source files
4
+
5
+ - [N3 rules](../rdf-message-window-repair.n3)
6
+ - [Input RDF Message Log](../input/rdf-message-window-repair.trig)
7
+ - [Story deck](../deck/rdf-message-window-repair.md)
8
+
9
+ ## Answer
10
+ Sliding-window RDF Message repair accepted: 5 parser-replayed messages produced two overlapping 3-message ABox windows. The current window retained two envelopes from the previous window, expired one old door reading, and added one new safety-controller reading. Its raw graph-level materialization was inconsistent because doorA was both open and closed. The preferred repair kept the priority-3 assertion from safety-controller, resolved the door state to closed, and materialized the action: mark the fire compartment as sealed.
11
+
12
+ ## Explanation
13
+ The RDF Message Log uses VERSION \"1.2-messages\" and MESSAGE delimiters. Eyeling parses those boundaries into eymsg: envelopes and payload graphs; the rules inspect each payload with log:includes rather than merging message bodies by hand. The example mirrors a sliding-window stream-reasoning pattern: when the window advances, overlapping message evidence is retained, an expired assertion leaves the window, an entering assertion can change the materialization, and a preferred repair fixes a noisy open/closed contradiction before the final action is produced.
@@ -0,0 +1,163 @@
1
+ # =========================
2
+ # RDF Message Window Repair
3
+ # =========================
4
+ #
5
+ # Run as:
6
+ #
7
+ # eyeling -r examples/rdf-message-window-repair.n3 examples/input/rdf-message-window-repair.trig
8
+ #
9
+ # This example is inspired by incremental, inconsistency-resilient reasoning over
10
+ # sliding ABox streams. The input is a true RDF Message Log: each MESSAGE
11
+ # boundary is parsed by Eyeling into an eymsg: envelope with one payload graph per
12
+ # non-empty message.
13
+ #
14
+ # The rules below keep the message boundaries visible, select two overlapping
15
+ # three-message windows, detect that the current window says the same fire door
16
+ # is both open and closed, and repair the inconsistency by keeping the
17
+ # higher-priority safety-controller assertion for the final materialization.
18
+
19
+ @prefix : <https://eyereasoner.github.io/eyeling/examples/rdf-message-window-repair#>.
20
+ @prefix eymsg: <https://eyereasoner.github.io/eyeling/vocab/message#>.
21
+ @prefix math: <http://www.w3.org/2000/10/swap/math#>.
22
+ @prefix list: <http://www.w3.org/2000/10/swap/list#>.
23
+ @prefix log: <http://www.w3.org/2000/10/swap/log#>.
24
+ @prefix string: <http://www.w3.org/2000/10/swap/string#>.
25
+
26
+ # Eyeling's parser-level replay gives a static view of the message log: an
27
+ # ordered list, explicit offsets, and next-envelope links.
28
+ {
29
+ ?Stream a eymsg:RDFMessageStream;
30
+ eymsg:envelope ?Message.
31
+ ?Message a eymsg:MessageEnvelope;
32
+ eymsg:offset ?Offset.
33
+ } => {
34
+ ?Message :boundaryExplicit true.
35
+ ?Message :offset ?Offset.
36
+ }.
37
+
38
+ # The first payload carries stream policy, like a fixed TBox/configuration that
39
+ # is not itself part of the changing ABox window.
40
+ {
41
+ ?Message eymsg:payloadGraph ?Payload.
42
+ ?Payload log:nameOf ?PayloadContext.
43
+ ?PayloadContext log:includes {
44
+ :doorA :windowSize ?WindowSize;
45
+ :repairPolicy :preferHigherPriority.
46
+ :open :actionText ?OpenAction;
47
+ :stateText ?OpenStateText.
48
+ :closed :actionText ?ClosedAction;
49
+ :stateText ?ClosedStateText.
50
+ }.
51
+ } => {
52
+ :doorA :windowSize ?WindowSize;
53
+ :repairPolicy :preferHigherPriority.
54
+ :open :actionText ?OpenAction;
55
+ :stateText ?OpenStateText.
56
+ :closed :actionText ?ClosedAction;
57
+ :stateText ?ClosedStateText.
58
+ }.
59
+
60
+ # With five messages, message 1 is configuration and messages 2-5 are ABox
61
+ # assertions. The previous and current sliding windows overlap on messages 3
62
+ # and 4; message 2 expires and message 5 enters.
63
+ {
64
+ ?Stream a eymsg:RDFMessageStream;
65
+ eymsg:firstEnvelope ?M1.
66
+ ?M1 eymsg:nextEnvelope ?M2.
67
+ ?M2 eymsg:nextEnvelope ?M3.
68
+ ?M3 eymsg:nextEnvelope ?M4.
69
+ ?M4 eymsg:nextEnvelope ?M5.
70
+ } => {
71
+ :previousWindow :contains ?M2, ?M3, ?M4.
72
+ :currentWindow :contains ?M3, ?M4, ?M5.
73
+ :windowSlide :expired ?M2;
74
+ :retained ?M3, ?M4;
75
+ :entered ?M5.
76
+ }.
77
+
78
+ # Inspect each message payload inside its own replayed RDF Message graph, then
79
+ # lift only the ABox assertion metadata needed for window reasoning.
80
+ {
81
+ ?Window :contains ?Message.
82
+ ?Message eymsg:payloadGraph ?Payload.
83
+ ?Payload log:nameOf ?PayloadContext.
84
+ ?PayloadContext log:includes {
85
+ ?Reading :about :doorA;
86
+ :doorState ?State;
87
+ :priority ?Priority;
88
+ :source ?Source.
89
+ }.
90
+ } => {
91
+ ?Message :windowAssertion ?Reading;
92
+ :doorState ?State;
93
+ :priority ?Priority;
94
+ :source ?Source.
95
+ ?Window :hasDoorState ?State.
96
+ }.
97
+
98
+ # The current graph-level window is inconsistent: after raw materialization it
99
+ # says the same door is both open and closed.
100
+ {
101
+ :currentWindow :contains ?OpenMessage, ?ClosedMessage.
102
+ ?OpenMessage :doorState :open.
103
+ ?ClosedMessage :doorState :closed.
104
+ } => {
105
+ :currentWindow :rawConflict :doorOpenAndClosed;
106
+ :inconsistentDoor :doorA.
107
+ }.
108
+
109
+ # Preferred repair: if a current-window assertion has higher priority than a
110
+ # conflicting current-window assertion, keep the higher-priority assertion as the
111
+ # one used by materialization.
112
+ {
113
+ :currentWindow :contains ?PreferredMessage, ?RejectedMessage;
114
+ :rawConflict :doorOpenAndClosed.
115
+ ?PreferredMessage :doorState ?PreferredState;
116
+ :priority ?PreferredPriority;
117
+ :source ?PreferredSource.
118
+ ?RejectedMessage :doorState ?RejectedState;
119
+ :priority ?RejectedPriority.
120
+ ?PreferredState log:notEqualTo ?RejectedState.
121
+ ?PreferredPriority math:greaterThan ?RejectedPriority.
122
+ } => {
123
+ :currentWindow :preferredRepairState ?PreferredState;
124
+ :preferredEvidence ?PreferredMessage;
125
+ :preferredSource ?PreferredSource;
126
+ :rejectsLowerPriority ?RejectedMessage;
127
+ :repairsInconsistency :doorOpenAndClosed;
128
+ :resolvedDoorState ?PreferredState.
129
+ }.
130
+
131
+ # Materialize the final operational conclusion from the repaired state rather
132
+ # than from the inconsistent raw window.
133
+ {
134
+ :currentWindow :preferredRepairState ?State.
135
+ ?State :actionText ?ActionText.
136
+ } => {
137
+ :currentWindow :materializedActionText ?ActionText.
138
+ }.
139
+
140
+ # Emit a report only when the parser replay, sliding-window bookkeeping, raw
141
+ # conflict, preferred repair, and final materialization were all derived.
142
+ {
143
+ ?Stream a eymsg:RDFMessageStream;
144
+ eymsg:orderedEnvelopes ?Messages.
145
+ ?Messages list:length ?Count.
146
+ :doorA :windowSize ?WindowSize.
147
+ :previousWindow :contains ?PreviousOnly.
148
+ :windowSlide :expired ?PreviousOnly;
149
+ :retained ?Overlap1, ?Overlap2;
150
+ :entered ?Entered.
151
+ :currentWindow :rawConflict :doorOpenAndClosed;
152
+ :inconsistentDoor :doorA;
153
+ :preferredEvidence ?PreferredMessage;
154
+ :preferredSource ?PreferredSource;
155
+ :resolvedDoorState ?State;
156
+ :materializedActionText ?ActionText.
157
+ ?State :stateText ?StateText.
158
+ ?PreferredMessage :priority ?PreferredPriority.
159
+ ("# rdf-message-window-repair\n\n## Source files\n\n- [N3 rules](../rdf-message-window-repair.n3)\n- [Input RDF Message Log](../input/rdf-message-window-repair.trig)\n- [Story deck](../deck/rdf-message-window-repair.md)\n\n## Answer\nSliding-window RDF Message repair accepted: %d parser-replayed messages produced two overlapping %d-message ABox windows. The current window retained two envelopes from the previous window, expired one old door reading, and added one new safety-controller reading. Its raw graph-level materialization was inconsistent because doorA was both open and closed. The preferred repair kept the priority-%d assertion from %s, resolved the door state to %s, and materialized the action: %s.\n\n## Explanation\nThe RDF Message Log uses VERSION \\\"1.2-messages\\\" and MESSAGE delimiters. Eyeling parses those boundaries into eymsg: envelopes and payload graphs; the rules inspect each payload with log:includes rather than merging message bodies by hand. The example mirrors a sliding-window stream-reasoning pattern: when the window advances, overlapping message evidence is retained, an expired assertion leaves the window, an entering assertion can change the materialization, and a preferred repair fixes a noisy open/closed contradiction before the final action is produced." ?Count ?WindowSize ?PreferredPriority ?PreferredSource ?StateText ?ActionText) string:format ?Block.
160
+ } => {
161
+ :rdfMessageWindowRepairExample log:outputString ?Block.
162
+ :rdfMessageWindowRepairExample :demonstrates :RDFMessageLogReplay, :SlidingWindow, :OverlappingWindows, :ABoxStream, :RawDoorInconsistency, :PreferredRepair, :IncrementalMaterialization.
163
+ }.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eyeling",
3
- "version": "1.26.6",
3
+ "version": "1.26.7",
4
4
  "description": "A minimal Notation3 (N3) reasoner in JavaScript.",
5
5
  "main": "./index.js",
6
6
  "keywords": [