eyeling 1.22.4 → 1.22.6

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
@@ -2599,19 +2599,23 @@ In that sense, N3 is less a bid to make the web “smarter” than a bid to make
2599
2599
 
2600
2600
  <a id="app-c"></a>
2601
2601
 
2602
- ## Appendix C — N3 beyond Prolog: logic for RDF-style graphs
2602
+ ## Appendix C — N3 beyond Prolog: logic that survives the open web
2603
2603
 
2604
- Notation3 (N3) rule sets often look similar to Prolog at the surface: they use variables, unification, and implication-style rules (“if these patterns match, then these patterns follow”). N3 is typically used in a different setting: instead of a single program operating over a single local database, N3 rules and data are commonly written as documents that can be published, shared, merged, and referenced across systems.
2604
+ Notation3 and Prolog resemble each other at first glance. Both use variables, unification, and implication-shaped rules. Both can be used to derive consequences from a set of premises. But they were shaped for different native environments. Prolog was designed around executing logic programs. N3 was designed around expressing logic in the same world as RDF: a world of IRIs, triples, graphs, linked documents, and shared vocabularies. That difference in native setting gives N3 a wider built-in reach for web-scale knowledge work.
2605
2605
 
2606
- In practice, that setting is reflected in several common features of N3-style rule writing:
2606
+ The first difference is the data model. In Prolog, the basic units are terms and clauses. In N3, the basic units are RDF-style triples and graphs, extended with variables, lists, graph terms, and logical implication. N3 is explicitly defined as an extension of RDF, not as a separate programming language that merely happens to manipulate graphs. That means identifiers, data, and inferred results all live in one interoperable form. A rule consumes graph patterns and produces graph patterns, so the output of reasoning can be published, merged, quoted, exchanged, and reasoned over again without changing representation.
2607
2607
 
2608
- - **Identifiers are IRIs.** Terms are usually global identifiers rather than local symbols, which supports linking across datasets.
2609
- - **Input and output are graphs.** Rules consume graph patterns and produce additional triples, so the result of inference can be represented in the same form as the input data.
2610
- - **Quoted graphs allow statements-as-data.** N3 can treat a graph (a set of triples) as a term, which makes it possible to represent and reason about assertions (e.g., “this source says …” or “this formula implies …”) as data.
2611
- - **Rules can be distributed as text artifacts.** Rules can live alongside data, be versioned, and be reused without requiring an external host language to “carry” the meaning.
2612
- - **Built-ins cover common computations.** Many N3 workflows rely on built-ins for operations such as string handling, list processing, comparisons, and related utilities; some workflows also use IRIs as pointers to retrievable content.
2608
+ The second difference is more profound: N3 can treat graphs as first-class terms. A graph term is a quoted graph. It can appear in subject, predicate, or object position, and it does not automatically assert its contents as true. It is a resource in its own right. This makes it natural to represent claims, reports, beliefs, policies, source snapshots, and provenance. One can say not only “this is true,” but also “this document says this,” “this authority concludes that,” or “this rule applies to that quoted context.” In other words, N3 can reason about statements as statements, not only about the world those statements describe.
2613
2609
 
2614
- Engines can combine execution styles in different ways. One common pattern is to use a Prolog-like backward-chaining prover to satisfy rule bodies, while still using forward chaining to add the instantiated conclusions to the fact set until no new facts are produced.
2610
+ That leads directly to a third advantage: scope is part of the logic. In N3, implicit universal quantification is global, while implicit existential quantification is local to the graph in which it occurs. Once graphs can be nested and quoted, that distinction matters. It allows a reasoner to keep track of what is asserted here, what is asserted inside a quoted subgraph, and what variables belong to which level. This gives N3 a native way to express context-sensitive reasoning that would feel external or encoded-by-convention in classic Prolog.
2611
+
2612
+ A fourth difference is that N3 connects logic to the web inside the language itself. The N3 vocabulary includes `log:semantics` and `log:conclusion` for retrieving and reasoning over local or online sources. It also includes scoped operators such as `log:forAllIn` and `log:notIncludes`, which support scoped universal reasoning and scoped negation-as-failure over a chosen graph or document. So web retrieval, source-bounded reasoning, and reasoning over quoted content are not afterthoughts. They are part of the logic vocabulary. This is one of the clearest senses in which N3 has greater inherent potential: it is not only a language for deriving consequences from facts, but a language for locating, quoting, constraining, and comparing the sources of those facts.
2613
+
2614
+ By contrast, classic Prolog is centered on a proof procedure over definite clauses. In the usual operational reading, Prolog applies a restricted form of SLD-resolution, chooses the leftmost goal, tries clauses top-to-bottom, and searches depth-first. Traditional negation is negation-as-failure, described in the SWI-Prolog glossary as a weak negation. This makes Prolog extremely effective as an executable logic language, but it also means that much of its practical power comes from the operational behavior of the engine, not from a web-native knowledge model.
2615
+
2616
+ This does not make Prolog inferior. Modern Prolog systems add important capabilities beyond the classic core, including tabling, which improves termination behavior and can make Prolog behave more like a bottom-up theorem prover for some classes of problems. But that actually sharpens the comparison: when Prolog needs to work more comfortably in graph-heavy or knowledge-integration settings, it typically gains that power through extensions, libraries, or host-environment choices. N3 starts there. Graphs, quoted formulas, scoped reasoning, and web-connected semantics are part of its native conceptual center.
2617
+
2618
+ So the strongest claim is not that N3 replaces Prolog in every domain. The stronger and more precise claim is this: Prolog is a very strong language for executing logic programs, while N3 has greater inherent potential as a language for publishable, linkable, inspectable, and source-aware logic on the open web. It lets facts, rules, quoted claims, retrieved documents, and derived conclusions all live in one semantic space. For a system like Eyeling, that is not a cosmetic difference. It is the reason the language can scale from local inference to web-shaped reasoning without changing its basic form.
2615
2619
 
2616
2620
  ---
2617
2621
 
@@ -3131,29 +3135,69 @@ Sometimes that means recomputing a quantity from another angle. Sometimes it mea
3131
3135
 
3132
3136
  The point is not to make checks large. The point is to make them real.
3133
3137
 
3134
- ### F.6 Examples in `examples/` that read well in ARC style
3138
+ ### F.6 ARC and the Insight Economy
3139
+
3140
+ One reason ARC matters beyond pedagogy is that it matches a broader way of thinking about data and computation that Ruben Verborgh has called the **Insight Economy**.
3141
+
3142
+ The basic claim is simple: raw data is usually the wrong thing to exchange directly. A better system refines source data into a **specific, purpose-limited, time-bound insight** that is useful in one context, loses much of its value when copied without that context, and can be governed more safely than an unrestricted dump of the original data.
3143
+
3144
+ That fits Eyeling remarkably well. Eyeling can derive narrow conclusions explicitly, show why they follow, and attach checks that make sure a decision still respects policy, scope, thresholds, or consistency constraints. In other words, an Eyeling program can act as a small governed insight refinery rather than as a black box that merely emits a verdict.
3145
+
3146
+ This is also why ARC is a good mental model here. The **Answer** is the bounded insight. The **Reason Why** makes the governing basis visible. The **Check** ensures the result can be trusted for the stated purpose instead of silently drifting beyond it.
3147
+
3148
+ ### F.7 ARC-style examples in `examples/`
3149
+
3150
+ The following examples are especially useful if you want to see Eyeling files that derive an answer, expose the key reason, and include meaningful checks. Each entry links to both the source example and the corresponding generated output file in `examples/output/`.
3151
+
3152
+ #### Insight Economy and governed-data cases
3153
+
3154
+ - [`examples/auroracare.n3`](examples/auroracare.n3) · [`examples/output/auroracare.txt`](examples/output/auroracare.txt) — purpose-based medical data exchange with explicit allow/deny reasoning and checks around role, purpose, and conditions.
3155
+ - [`examples/calidor.n3`](examples/calidor.n3) · [`examples/output/calidor.txt`](examples/output/calidor.txt) — heatwave-response case where private household signals become a narrow, expiring cooling-support insight.
3156
+ - [`examples/delfour.n3`](examples/delfour.n3) · [`examples/output/delfour.txt`](examples/output/delfour.txt) — shopping-assistance case where a private condition becomes a bounded “prefer lower-sugar products” insight.
3157
+ - [`examples/flandor.n3`](examples/flandor.n3) · [`examples/output/flandor.txt`](examples/output/flandor.txt) — macro-economic coordination case for Flanders that turns sensitive local signals into a regional retooling insight.
3158
+ - [`examples/medior.n3`](examples/medior.n3) · [`examples/output/medior.txt`](examples/output/medior.txt) — post-discharge care-coordination case that derives a minimal continuity-bundle insight without sharing the full record.
3159
+ - [`examples/parcellocker.n3`](examples/parcellocker.n3) · [`examples/output/parcellocker.txt`](examples/output/parcellocker.txt) — one-time parcel pickup authorization with a clear permit decision, justification, and misuse checks.
3160
+
3161
+ #### Core ARC-style walkthroughs
3162
+
3163
+ - [`examples/bmi.n3`](examples/bmi.n3) · [`examples/output/bmi.txt`](examples/output/bmi.txt) — Body Mass Index calculation with normalization, WHO category assignment, and boundary checks.
3164
+ - [`examples/control-system.n3`](examples/control-system.n3) · [`examples/output/control-system.txt`](examples/output/control-system.txt) — small control-system example that derives actuator commands and explains feedforward and feedback contributions.
3165
+ - [`examples/easter.n3`](examples/easter.n3) · [`examples/output/easter.txt`](examples/output/easter.txt) — Gregorian Easter computus with a readable explanation and date-window checks.
3166
+ - [`examples/french-cities.n3`](examples/french-cities.n3) · [`examples/output/french-cities.txt`](examples/output/french-cities.txt) — graph reachability over French cities with explicit path reasoning.
3167
+ - [`examples/gps.n3`](examples/gps.n3) · [`examples/output/gps.txt`](examples/output/gps.txt) — tiny route-planning example for western Belgium with route comparison and metric checks.
3168
+ - [`examples/resto.n3`](examples/resto.n3) · [`examples/output/resto.txt`](examples/output/resto.txt) — RESTdesc-style service composition from person and date to a concrete restaurant reservation.
3169
+ - [`examples/sudoku.n3`](examples/sudoku.n3) · [`examples/output/sudoku.txt`](examples/output/sudoku.txt) — Sudoku solver and report generator with consistency checks over the solved grid.
3170
+ - [`examples/wind-turbine.n3`](examples/wind-turbine.n3) · [`examples/output/wind-turbine.txt`](examples/output/wind-turbine.txt) — predictive-maintenance example that turns sensor readings into an auditable inspection decision.
3171
+
3172
+ #### Technical and scientific ARC demos
3173
+
3174
+ - [`examples/matrix-mechanics.n3`](examples/matrix-mechanics.n3) · [`examples/output/matrix-mechanics.txt`](examples/output/matrix-mechanics.txt) — small 2×2 matrix example deriving trace, determinant, products, and a non-zero commutator.
3175
+ - [`examples/pn-junction-tunneling.n3`](examples/pn-junction-tunneling.n3) · [`examples/output/pn-junction-tunneling.txt`](examples/output/pn-junction-tunneling.txt) — semiconductor toy model that explains current-proxy behavior across bias points.
3176
+ - [`examples/transistor-switch.n3`](examples/transistor-switch.n3) · [`examples/output/transistor-switch.txt`](examples/output/transistor-switch.txt) — NPN low-side switch model with exact arithmetic and cutoff-versus-saturation checks.
3177
+
3178
+ #### Deep-classification stress tests
3135
3179
 
3136
- The following examples are especially good places to see this style in practice.
3180
+ - [`examples/deep-taxonomy-10.n3`](examples/deep-taxonomy-10.n3) · [`examples/output/deep-taxonomy-10.txt`](examples/output/deep-taxonomy-10.txt) ARC-style deep-taxonomy benchmark at depth 10.
3181
+ - [`examples/deep-taxonomy-100.n3`](examples/deep-taxonomy-100.n3) · [`examples/output/deep-taxonomy-100.txt`](examples/output/deep-taxonomy-100.txt) — ARC-style deep-taxonomy benchmark at depth 100.
3182
+ - [`examples/deep-taxonomy-1000.n3`](examples/deep-taxonomy-1000.n3) · [`examples/output/deep-taxonomy-1000.txt`](examples/output/deep-taxonomy-1000.txt) — ARC-style deep-taxonomy benchmark at depth 1000.
3183
+ - [`examples/deep-taxonomy-10000.n3`](examples/deep-taxonomy-10000.n3) · [`examples/output/deep-taxonomy-10000.txt`](examples/output/deep-taxonomy-10000.txt) — ARC-style deep-taxonomy benchmark at depth 10000.
3184
+ - [`examples/deep-taxonomy-100000.n3`](examples/deep-taxonomy-100000.n3) · [`examples/output/deep-taxonomy-100000.txt`](examples/output/deep-taxonomy-100000.txt) — ARC-style deep-taxonomy benchmark at depth 100000.
3137
3185
 
3138
- - [`examples/delfour.n3`](examples/delfour.n3) privacy-preserving shopping assistance with a concrete recommendation, an explanation, and policy checks. Expected output: [`examples/output/delfour.n3`](examples/output/delfour.n3)
3139
- - [`examples/control-system.n3`](examples/control-system.n3) — derives actuator decisions, explains the control basis, and checks the result. Expected output: [`examples/output/control-system.n3`](examples/output/control-system.n3)
3140
- - [`examples/deep-taxonomy-100000.n3`](examples/deep-taxonomy-100000.n3) — a deep classification stress test whose answer is whether the final goal class is reached. Expected output: [`examples/output/deep-taxonomy-100000.n3`](examples/output/deep-taxonomy-100000.n3)
3141
- - [`examples/gps.n3`](examples/gps.n3) — route planning with readable route output. Expected output: [`examples/output/gps.n3`](examples/output/gps.n3)
3142
- - [`examples/sudoku.n3`](examples/sudoku.n3) — solver output plus legality and consistency checks. Expected output: [`examples/output/sudoku.n3`](examples/output/sudoku.n3)
3186
+ These files fit together because they all present reasoning in a recognizably ARC-like way: they derive an answer, make the reason visible in a compact report, and include checks that are meant to catch real mistakes. Some are classical logic or numeric examples; others show how Eyeling can express policy-aware, insight-oriented decision flows without collapsing everything into opaque application code.
3143
3187
 
3144
- ### F.7 How to read an ARC-style example
3188
+ ### F.8 How to read an ARC-style example
3145
3189
 
3146
3190
  A good way to read one of these files is to start with the question in the comments or input facts. Then find the part that gives the answer. Then trace the few rules that explain why that answer follows. Finally, look for the checks: the validation facts, the recomputation, or the `=> false` fuse that would stop the run if something important were wrong.
3147
3191
 
3148
3192
  That reading order keeps the example grounded in observable behavior rather than in source code alone.
3149
3193
 
3150
- ### F.8 What ARC is not
3194
+ ### F.9 What ARC is not
3151
3195
 
3152
3196
  ARC does not mean wrapping every file in ceremony. It does not mean long prose explanations. It does not mean hiding important assumptions in comments while the executable part stays thin. And it does not mean replacing checks with a confident tone.
3153
3197
 
3154
3198
  A file really follows ARC only when the answer, the explanation, and the validation all live in the program itself.
3155
3199
 
3156
- ### F.9 Why this style is worth using
3200
+ ### F.10 Why this style is worth using
3157
3201
 
3158
3202
  This style is worth using because it makes an Eyeling file easier to run, easier to inspect, and easier to trust. The result is visible. The key reason is visible. The check is visible. That makes examples better teaching material, makes policy or computation examples easier to audit, and makes the whole file more reusable as a small reasoning artifact instead of an opaque session transcript.
3159
3203
 
@@ -1343,6 +1343,15 @@
1343
1343
  return null;
1344
1344
  }
1345
1345
 
1346
+ function inferDatatypeForShorthandLexical(lex) {
1347
+ if (typeof lex !== 'string' || isQuotedLexical(lex)) return null;
1348
+ if (lex === 'true' || lex === 'false') return XSD_NS + 'boolean';
1349
+ if (/^[+-]?\d+$/.test(lex)) return XSD_NS + 'integer';
1350
+ if (/^[+-]?(?:\d+\.\d*|\.\d+)$/.test(lex)) return XSD_NS + 'decimal';
1351
+ if (/^[+-]?(?:\d+\.\d*|\.\d+|\d+)(?:[eE][+-]?\d+)$/.test(lex)) return XSD_NS + 'double';
1352
+ return null;
1353
+ }
1354
+
1346
1355
  // ===========================================================================
1347
1356
  // Math builtin helpers
1348
1357
  // ===========================================================================
@@ -3864,6 +3873,7 @@
3864
3873
  if (oDt === null) {
3865
3874
  if (literalHasLangTag(g.o.value)) oDt = RDF_NS + 'langString';
3866
3875
  else if (isPlainStringLiteralValue(g.o.value)) oDt = XSD_NS + 'string';
3876
+ else oDt = inferDatatypeForShorthandLexical(oLex);
3867
3877
  }
3868
3878
 
3869
3879
  if (oDt !== null) {
@@ -3978,6 +3988,23 @@
3978
3988
  results.push(s2);
3979
3989
  }
3980
3990
 
3991
+ // Also match quoted log:implies triples present as data in the current scope.
3992
+ if (facts && typeof facts.length === 'number') {
3993
+ ensureFactIndexes(facts);
3994
+ const pb = facts.__byPred.get(goal.p.__tid) || [];
3995
+ for (const idx of pb) {
3996
+ const tr = facts[idx];
3997
+
3998
+ let s2 = unifyTerm(goal.s, tr.s, subst);
3999
+ if (s2 === null) continue;
4000
+
4001
+ s2 = unifyTerm(goal.o, tr.o, s2);
4002
+ if (s2 === null) continue;
4003
+
4004
+ results.push(s2);
4005
+ }
4006
+ }
4007
+
3981
4008
  return results;
3982
4009
  }
3983
4010
 
@@ -4007,6 +4034,23 @@
4007
4034
  results.push(s2);
4008
4035
  }
4009
4036
 
4037
+ // Also match quoted log:impliedBy triples present as data in the current scope.
4038
+ if (facts && typeof facts.length === 'number') {
4039
+ ensureFactIndexes(facts);
4040
+ const pb = facts.__byPred.get(goal.p.__tid) || [];
4041
+ for (const idx of pb) {
4042
+ const tr = facts[idx];
4043
+
4044
+ let s2 = unifyTerm(goal.s, tr.s, subst);
4045
+ if (s2 === null) continue;
4046
+
4047
+ s2 = unifyTerm(goal.o, tr.o, s2);
4048
+ if (s2 === null) continue;
4049
+
4050
+ results.push(s2);
4051
+ }
4052
+ }
4053
+
4010
4054
  return results;
4011
4055
  }
4012
4056
 
@@ -1,57 +1,11 @@
1
1
  # ARC-style examples in Eyeling
2
2
 
3
- This page points to the ARC-style examples that currently live in [`examples/`](../). The files themselves are one level up; this folder exists as a convenient index for readers who want to browse Eyeling examples that follow the same presentation pattern.
3
+ This content is now integrated into the handbook:
4
4
 
5
- ## What ARC is
5
+ - [Appendix F — The ARC approach: Answer • Reason Why • Check](../../HANDBOOK.md#app-f)
6
6
 
7
- [ARC](https://josd.github.io/arc/) stands for **Answer • Reason Why • Check**. The idea is to make a program do three things at once: give the result, explain the small reason that matters, and include a check that can fail loudly when an assumption is wrong. In practice, ARC turns a runnable example into a small, auditable artifact rather than a black box.
7
+ That appendix now includes:
8
8
 
9
- In Eyeling, ARC fits naturally: facts hold the data, rules derive the result, `log:outputString` can render a human-readable report, and `=> false` rules can act as hard validation fuses.
10
-
11
- ## What the Insight Economy is
12
-
13
- Ruben Verborgh’s [Insight Economy](https://ruben.verborgh.org/blog/2025/08/12/inside-the-insight-economy/) argues that raw data is a bad thing to trade directly. Instead of handing over the source data, a system should refine it into a **specific, purpose-limited, time-bound insight** that is useful in one context, loses value when copied, and can be governed more safely.
14
-
15
- That makes the examples below especially relevant: Eyeling can derive those narrow insights explicitly, explain why they hold, and check that the resulting decision respects policy, purpose, and consistency constraints.
16
-
17
- ## ARC-style examples in `examples/`
18
-
19
- Each entry links to both the source example and the corresponding generated output in [`examples/output/`](../output/).
20
-
21
- ### Insight Economy and governed-data cases
22
-
23
- - [`../auroracare.n3`](../auroracare.n3) · [`../output/auroracare.txt`](../output/auroracare.txt) — Purpose-based medical data exchange with explicit allow/deny reasoning and checks around role, purpose, and conditions.
24
- - [`../calidor.n3`](../calidor.n3) · [`../output/calidor.txt`](../output/calidor.txt) — Heatwave-response case where private household signals become a narrow, expiring cooling-support insight.
25
- - [`../delfour.n3`](../delfour.n3) · [`../output/delfour.txt`](../output/delfour.txt) — Shopping-assistance case where a private condition becomes a bounded “prefer lower-sugar products” insight.
26
- - [`../flandor.n3`](../flandor.n3) · [`../output/flandor.txt`](../output/flandor.txt) — Macro-economic coordination case for Flanders that turns sensitive local signals into a regional retooling insight.
27
- - [`../medior.n3`](../medior.n3) · [`../output/medior.txt`](../output/medior.txt) — Post-discharge care-coordination case that derives a minimal continuity-bundle insight without sharing the full record.
28
- - [`../parcellocker.n3`](../parcellocker.n3) · [`../output/parcellocker.txt`](../output/parcellocker.txt) — One-time parcel pickup authorization with a clear permit decision, justification, and misuse checks.
29
-
30
- ### Core ARC-style walkthroughs
31
-
32
- - [`../bmi.n3`](../bmi.n3) · [`../output/bmi.txt`](../output/bmi.txt) — Body Mass Index calculation with normalization, WHO category assignment, and boundary checks.
33
- - [`../control-system.n3`](../control-system.n3) · [`../output/control-system.txt`](../output/control-system.txt) — Small control-system example that derives actuator commands and explains feedforward and feedback contributions.
34
- - [`../easter.n3`](../easter.n3) · [`../output/easter.txt`](../output/easter.txt) — Gregorian Easter computus with a readable explanation and date-window checks.
35
- - [`../french-cities.n3`](../french-cities.n3) · [`../output/french-cities.txt`](../output/french-cities.txt) — Graph reachability over French cities with explicit path reasoning.
36
- - [`../gps.n3`](../gps.n3) · [`../output/gps.txt`](../output/gps.txt) — Tiny route-planning example for western Belgium with route comparison and metric checks.
37
- - [`../resto.n3`](../resto.n3) · [`../output/resto.txt`](../output/resto.txt) — RESTdesc-style service composition from person and date to a concrete restaurant reservation.
38
- - [`../sudoku.n3`](../sudoku.n3) · [`../output/sudoku.txt`](../output/sudoku.txt) — Sudoku solver and report generator with consistency checks over the solved grid.
39
- - [`../wind-turbine.n3`](../wind-turbine.n3) · [`../output/wind-turbine.txt`](../output/wind-turbine.txt) — Predictive-maintenance example that turns sensor readings into an auditable inspection decision.
40
-
41
- ### Technical and scientific ARC demos
42
-
43
- - [`../matrix-mechanics.n3`](../matrix-mechanics.n3) · [`../output/matrix-mechanics.txt`](../output/matrix-mechanics.txt) — Small 2×2 matrix example deriving trace, determinant, products, and a non-zero commutator.
44
- - [`../pn-junction-tunneling.n3`](../pn-junction-tunneling.n3) · [`../output/pn-junction-tunneling.txt`](../output/pn-junction-tunneling.txt) — Semiconductor toy model that explains current-proxy behavior across bias points.
45
- - [`../transistor-switch.n3`](../transistor-switch.n3) · [`../output/transistor-switch.txt`](../output/transistor-switch.txt) — NPN low-side switch model with exact arithmetic and cutoff-versus-saturation checks.
46
-
47
- ### Deep-classification stress tests
48
-
49
- - [`../deep-taxonomy-10.n3`](../deep-taxonomy-10.n3) · [`../output/deep-taxonomy-10.txt`](../output/deep-taxonomy-10.txt) — ARC-style deep-taxonomy benchmark at depth 10.
50
- - [`../deep-taxonomy-100.n3`](../deep-taxonomy-100.n3) · [`../output/deep-taxonomy-100.txt`](../output/deep-taxonomy-100.txt) — ARC-style deep-taxonomy benchmark at depth 100.
51
- - [`../deep-taxonomy-1000.n3`](../deep-taxonomy-1000.n3) · [`../output/deep-taxonomy-1000.txt`](../output/deep-taxonomy-1000.txt) — ARC-style deep-taxonomy benchmark at depth 1000.
52
- - [`../deep-taxonomy-10000.n3`](../deep-taxonomy-10000.n3) · [`../output/deep-taxonomy-10000.txt`](../output/deep-taxonomy-10000.txt) — ARC-style deep-taxonomy benchmark at depth 10000.
53
- - [`../deep-taxonomy-100000.n3`](../deep-taxonomy-100000.n3) · [`../output/deep-taxonomy-100000.txt`](../output/deep-taxonomy-100000.txt) — ARC-style deep-taxonomy benchmark at depth 100000.
54
-
55
- ## Why these examples fit together
56
-
57
- These files all present reasoning in a recognizably ARC-like way: they derive an answer, make the reason visible in a compact report, and include checks that are meant to catch real mistakes. Some are classical logic or numeric examples; others show how Eyeling can express policy-aware, insight-oriented decision flows without collapsing everything into opaque application code.
9
+ - a brief explanation of ARC,
10
+ - a brief explanation of the Insight Economy,
11
+ - and links to the ARC-style examples in `examples/` together with their outputs in `examples/output/`.
@@ -28,6 +28,7 @@ Completed grid
28
28
  3 5 6 | 4 7 8 | 2 1 9
29
29
  2 4 1 | 9 3 5 | 8 6 7
30
30
  8 9 7 | 2 6 1 | 3 5 4
31
+
31
32
  === Reason Why ===
32
33
  The solver starts from 23 clues and fills the remaining 58 cells by combining constraint propagation with depth-first search. At each step it chooses the empty cell with the fewest legal digits, places forced singles immediately, and only guesses when more than one candidate remains. Across the search it made 213 forced placements and tried 22 guesses, visited 23 search nodes overall, and backtracked 12 times before reaching the completed grid. The solver also confirmed that the solution is unique. Early steps: r2c3=4: guess, r5c3=3: forced, r2c1=5: guess, r2c4=1: guess, r2c6=9: forced, r2c7=6: guess, r2c8=7: forced, r1c7=4: guess, … and 50 more placements
33
34
 
@@ -114,8 +114,8 @@
114
114
  log:outputString ?puzzleText ;
115
115
  log:outputString "\n" ;
116
116
  log:outputString "Completed grid\n" ;
117
- log:outputString ?solutionText ;
118
- log:outputString "\n\n" .
117
+ log:outputString ?solutionText .
118
+ :01b-answer log:outputString "\n" .
119
119
  :02-reason log:outputString "=== Reason Why ===\n" ;
120
120
  log:outputString ?reasonText ;
121
121
  log:outputString "\n\n" .
package/eyeling.js CHANGED
@@ -1338,6 +1338,15 @@ function parseXsdFloatSpecialLex(s) {
1338
1338
  return null;
1339
1339
  }
1340
1340
 
1341
+ function inferDatatypeForShorthandLexical(lex) {
1342
+ if (typeof lex !== 'string' || isQuotedLexical(lex)) return null;
1343
+ if (lex === 'true' || lex === 'false') return XSD_NS + 'boolean';
1344
+ if (/^[+-]?\d+$/.test(lex)) return XSD_NS + 'integer';
1345
+ if (/^[+-]?(?:\d+\.\d*|\.\d+)$/.test(lex)) return XSD_NS + 'decimal';
1346
+ if (/^[+-]?(?:\d+\.\d*|\.\d+|\d+)(?:[eE][+-]?\d+)$/.test(lex)) return XSD_NS + 'double';
1347
+ return null;
1348
+ }
1349
+
1341
1350
  // ===========================================================================
1342
1351
  // Math builtin helpers
1343
1352
  // ===========================================================================
@@ -3850,6 +3859,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
3850
3859
  if (oDt === null) {
3851
3860
  if (literalHasLangTag(g.o.value)) oDt = RDF_NS + 'langString';
3852
3861
  else if (isPlainStringLiteralValue(g.o.value)) oDt = XSD_NS + 'string';
3862
+ else oDt = inferDatatypeForShorthandLexical(oLex);
3853
3863
  }
3854
3864
 
3855
3865
  if (oDt !== null) {
@@ -3964,6 +3974,23 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
3964
3974
  results.push(s2);
3965
3975
  }
3966
3976
 
3977
+ // Also match quoted log:implies triples present as data in the current scope.
3978
+ if (facts && typeof facts.length === 'number') {
3979
+ ensureFactIndexes(facts);
3980
+ const pb = facts.__byPred.get(goal.p.__tid) || [];
3981
+ for (const idx of pb) {
3982
+ const tr = facts[idx];
3983
+
3984
+ let s2 = unifyTerm(goal.s, tr.s, subst);
3985
+ if (s2 === null) continue;
3986
+
3987
+ s2 = unifyTerm(goal.o, tr.o, s2);
3988
+ if (s2 === null) continue;
3989
+
3990
+ results.push(s2);
3991
+ }
3992
+ }
3993
+
3967
3994
  return results;
3968
3995
  }
3969
3996
 
@@ -3993,6 +4020,23 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
3993
4020
  results.push(s2);
3994
4021
  }
3995
4022
 
4023
+ // Also match quoted log:impliedBy triples present as data in the current scope.
4024
+ if (facts && typeof facts.length === 'number') {
4025
+ ensureFactIndexes(facts);
4026
+ const pb = facts.__byPred.get(goal.p.__tid) || [];
4027
+ for (const idx of pb) {
4028
+ const tr = facts[idx];
4029
+
4030
+ let s2 = unifyTerm(goal.s, tr.s, subst);
4031
+ if (s2 === null) continue;
4032
+
4033
+ s2 = unifyTerm(goal.o, tr.o, s2);
4034
+ if (s2 === null) continue;
4035
+
4036
+ results.push(s2);
4037
+ }
4038
+ }
4039
+
3996
4040
  return results;
3997
4041
  }
3998
4042
 
package/lib/builtins.js CHANGED
@@ -859,6 +859,15 @@ function parseXsdFloatSpecialLex(s) {
859
859
  return null;
860
860
  }
861
861
 
862
+ function inferDatatypeForShorthandLexical(lex) {
863
+ if (typeof lex !== 'string' || isQuotedLexical(lex)) return null;
864
+ if (lex === 'true' || lex === 'false') return XSD_NS + 'boolean';
865
+ if (/^[+-]?\d+$/.test(lex)) return XSD_NS + 'integer';
866
+ if (/^[+-]?(?:\d+\.\d*|\.\d+)$/.test(lex)) return XSD_NS + 'decimal';
867
+ if (/^[+-]?(?:\d+\.\d*|\.\d+|\d+)(?:[eE][+-]?\d+)$/.test(lex)) return XSD_NS + 'double';
868
+ return null;
869
+ }
870
+
862
871
  // ===========================================================================
863
872
  // Math builtin helpers
864
873
  // ===========================================================================
@@ -3371,6 +3380,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
3371
3380
  if (oDt === null) {
3372
3381
  if (literalHasLangTag(g.o.value)) oDt = RDF_NS + 'langString';
3373
3382
  else if (isPlainStringLiteralValue(g.o.value)) oDt = XSD_NS + 'string';
3383
+ else oDt = inferDatatypeForShorthandLexical(oLex);
3374
3384
  }
3375
3385
 
3376
3386
  if (oDt !== null) {
@@ -3485,6 +3495,23 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
3485
3495
  results.push(s2);
3486
3496
  }
3487
3497
 
3498
+ // Also match quoted log:implies triples present as data in the current scope.
3499
+ if (facts && typeof facts.length === 'number') {
3500
+ ensureFactIndexes(facts);
3501
+ const pb = facts.__byPred.get(goal.p.__tid) || [];
3502
+ for (const idx of pb) {
3503
+ const tr = facts[idx];
3504
+
3505
+ let s2 = unifyTerm(goal.s, tr.s, subst);
3506
+ if (s2 === null) continue;
3507
+
3508
+ s2 = unifyTerm(goal.o, tr.o, s2);
3509
+ if (s2 === null) continue;
3510
+
3511
+ results.push(s2);
3512
+ }
3513
+ }
3514
+
3488
3515
  return results;
3489
3516
  }
3490
3517
 
@@ -3514,6 +3541,23 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
3514
3541
  results.push(s2);
3515
3542
  }
3516
3543
 
3544
+ // Also match quoted log:impliedBy triples present as data in the current scope.
3545
+ if (facts && typeof facts.length === 'number') {
3546
+ ensureFactIndexes(facts);
3547
+ const pb = facts.__byPred.get(goal.p.__tid) || [];
3548
+ for (const idx of pb) {
3549
+ const tr = facts[idx];
3550
+
3551
+ let s2 = unifyTerm(goal.s, tr.s, subst);
3552
+ if (s2 === null) continue;
3553
+
3554
+ s2 = unifyTerm(goal.o, tr.o, s2);
3555
+ if (s2 === null) continue;
3556
+
3557
+ results.push(s2);
3558
+ }
3559
+ }
3560
+
3517
3561
  return results;
3518
3562
  }
3519
3563
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eyeling",
3
- "version": "1.22.4",
3
+ "version": "1.22.6",
4
4
  "description": "A minimal Notation3 (N3) reasoner in JavaScript.",
5
5
  "main": "./index.js",
6
6
  "keywords": [
package/test/api.test.js CHANGED
@@ -2152,6 +2152,90 @@ _:x :hates { _:foo :making :mess }.
2152
2152
  ],
2153
2153
  notExpect: [/:result\s+:sumX\s+"329"\^\^xsd:decimal\s*\./, /:result\s+:meanX\s+"47"\^\^xsd:decimal\s*\./],
2154
2154
  },
2155
+ {
2156
+ name: '244 regression: log:dtlit recognizes shorthand numeric and boolean literals',
2157
+ opt: { proofComments: false },
2158
+ input: `@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
2159
+ @prefix log: <http://www.w3.org/2000/10/swap/log#> .
2160
+ @prefix : <http://example.org#> .
2161
+
2162
+ :let :term 4, 2.5, 3e1, true, "3"^^xsd:integer .
2163
+
2164
+ {
2165
+ :let :term ?term .
2166
+ (?text ?datatype) log:dtlit ?term .
2167
+ }
2168
+ =>
2169
+ {
2170
+ ?term :is (?text ?datatype) .
2171
+ }.
2172
+ `,
2173
+ expect: [
2174
+ /^4\s+:is\s+\("4"\s+xsd:integer\)\s*\./m,
2175
+ /^2\.5\s+:is\s+\("2\.5"\s+xsd:decimal\)\s*\./m,
2176
+ /^3e1\s+:is\s+\("3e1"\s+xsd:double\)\s*\./m,
2177
+ /^true\s+:is\s+\("true"\s+xsd:boolean\)\s*\./m,
2178
+ /^"3"\^\^xsd:integer\s+:is\s+\("3"\s+xsd:integer\)\s*\./m,
2179
+ ],
2180
+ },
2181
+ {
2182
+ name: '245 regression: log:includes sees quoted log:implies triples as data',
2183
+ opt: { proofComments: false },
2184
+ input: `@prefix : <http://example.org/> .
2185
+ @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
2186
+ @prefix log: <http://www.w3.org/2000/10/swap/log#> .
2187
+
2188
+ <> :data {
2189
+ {
2190
+ ?A a ?B .
2191
+ ?B rdfs:subClassOf ?C.
2192
+ }
2193
+ =>
2194
+ {
2195
+ ?A a ?C .
2196
+ }.
2197
+ }.
2198
+
2199
+ {
2200
+ ?W :data ?F.
2201
+ ?F log:includes { ?X log:implies ?Y }.
2202
+ }
2203
+ =>
2204
+ {
2205
+ :result :is ?X .
2206
+ }.
2207
+ `,
2208
+ expect: [/^:result\s+:is\s+\{[\s\S]*\?A\s+a\s+\?B\s*\.[\s\S]*\?B\s+rdfs:subClassOf\s+\?C\s*\.[\s\S]*\}\s*\./m],
2209
+ },
2210
+ {
2211
+ name: '246 regression: log:includes sees quoted log:impliedBy triples as data',
2212
+ opt: { proofComments: false },
2213
+ input: `@prefix : <http://example.org/> .
2214
+ @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
2215
+ @prefix log: <http://www.w3.org/2000/10/swap/log#> .
2216
+
2217
+ <> :data {
2218
+ {
2219
+ ?A a ?C .
2220
+ }
2221
+ <=
2222
+ {
2223
+ ?A a ?B .
2224
+ ?B rdfs:subClassOf ?C.
2225
+ }.
2226
+ }.
2227
+
2228
+ {
2229
+ ?W :data ?F.
2230
+ ?F log:includes { ?Y <= ?X }.
2231
+ }
2232
+ =>
2233
+ {
2234
+ :result :is ?X .
2235
+ }.
2236
+ `,
2237
+ expect: [/^:result\s+:is\s+\{[\s\S]*\?A\s+a\s+\?B\s*\.[\s\S]*\?B\s+rdfs:subClassOf\s+\?C\s*\.[\s\S]*\}\s*\./m],
2238
+ },
2155
2239
  ];
2156
2240
 
2157
2241
  let passed = 0;