eyeling 1.16.4 → 1.17.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 CHANGED
@@ -30,6 +30,7 @@
30
30
  - [Appendix C — N3 beyond Prolog: logic that survives the open web](#app-c)
31
31
  - [Appendix D — LLM + Eyeling: A Repeatable Logic Toolchain](#app-d)
32
32
  - [Appendix E — How Eyeling reaches 100% on `notation3tests`](#app-e)
33
+ - [Appendix F — The ARC approach: Answer • Reason Why • Check](#app-f)
33
34
 
34
35
  ---
35
36
 
@@ -1536,7 +1537,7 @@ Implementation: this is implemented by `lib/trace.js` and called from `lib/engin
1536
1537
 
1537
1538
  As a goal, this builtin simply checks that the terms are sufficiently bound/usable and then succeeds. The actual “printing” behavior is handled by the CLI:
1538
1539
 
1539
- - When you run Eyeling with `--strings` / `-r`, the CLI collects all `log:outputString` triples from the _saturated_ closure.
1540
+ - When the final closure contains any `log:outputString` triples, the CLI collects all of them from the _saturated_ closure and renders those strings instead of the default N3 output.
1540
1541
  - It sorts them deterministically by the subject “key” and concatenates the string values in that order.
1541
1542
 
1542
1543
  This is a pure test/side-effect marker (it shouldn’t drive search; it should merely validate that strings exist once other reasoning has produced them). In forward rules Eyeling may defer it if it is reached before the terms are usable.
@@ -1655,7 +1656,7 @@ Matches the regex once and returns the **first capturing group** (group 1). If t
1655
1656
 
1656
1657
  From a logic-programming point of view, printing is awkward: if you print _during_ proof search, you risk producing output along branches that later backtrack, or producing the same line multiple times in different derivations. Eyeling avoids that whole class of problems by treating “output” as **data**.
1657
1658
 
1658
- The predicate `log:outputString` is the only officially supported “side-effect channel”, and even it is handled in two phases:
1659
+ The predicate `log:outputString` is the only officially supported “side-effect channel”, and even it is handled in two phases. If any final `log:outputString` facts exist, Eyeling renders them automatically as the CLI output:
1659
1660
 
1660
1661
  1. **During reasoning (declarative phase):**
1661
1662
  `log:outputString` behaves like a pure test builtin (implemented in `lib/builtins.js`): it succeeds when its arguments are well-formed and sufficiently bound (notably, when the object is a string literal that can be emitted). Importantly, it does _not_ print anything at this time. If a rule derives a triple like:
@@ -1674,7 +1675,7 @@ This separation is not just an aesthetic choice; it preserves the meaning of log
1674
1675
  - Output becomes explainable. If you enable proof comments or inspect the closure, `log:outputString` facts can be traced back to the rules that produced them.
1675
1676
  - Output becomes compositional. You can reason about output strings (e.g., sort them, filter them, derive them conditionally) just like any other data.
1676
1677
 
1677
- In short: Eyeling makes `log:outputString` safe by refusing to treat it as an immediate effect. It is a _declarative output fact_ whose concrete rendering is a final, deterministic post-processing step.
1678
+ In short: Eyeling makes `log:outputString` safe by refusing to treat it as an immediate effect. It is a _declarative output fact_ whose concrete rendering is a final, deterministic post-processing step. If any such facts are present in the final closure, Eyeling renders those strings automatically instead of printing the default N3 result set.
1678
1679
 
1679
1680
  ---
1680
1681
 
@@ -1772,7 +1773,7 @@ The bundle contains the whole engine. The CLI path is the “canonical behavior
1772
1773
 
1773
1774
  - parse input file
1774
1775
  - reason to closure
1775
- - print derived triples or output strings
1776
+ - print derived triples, or render `log:outputString` strings when present
1776
1777
  - optional proof comments
1777
1778
  - optional streaming
1778
1779
 
@@ -1784,7 +1785,6 @@ The current CLI supports a small set of flags (see `lib/cli.js`):
1784
1785
  - `-d`, `--deterministic-skolem` — make `log:skolem` stable across runs.
1785
1786
  - `-e`, `--enforce-https` — rewrite `http://…` to `https://…` for dereferencing builtins.
1786
1787
  - `-p`, `--proof-comments` — include per-fact proof comment blocks in output.
1787
- - `-r`, `--strings` — after reasoning, render only `log:outputString` values (ordered by subject key).
1788
1788
  - `-s`, `--super-restricted` — disable all builtins except `log:implies` / `log:impliedBy`.
1789
1789
  - `-t`, `--stream` — stream derived triples as soon as they are derived.
1790
1790
  - `-v`, `--version` — print version and exit.
@@ -1987,13 +1987,12 @@ Options:
1987
1987
  -e, --enforce-https Rewrite http:// IRIs to https:// for log dereferencing builtins.
1988
1988
  -h, --help Show this help and exit.
1989
1989
  -p, --proof-comments Enable proof explanations.
1990
- -r, --strings Print log:outputString strings (ordered by key) instead of N3 output.
1991
1990
  -s, --super-restricted Disable all builtins except => and <=.
1992
1991
  -t, --stream Stream derived triples as soon as they are derived.
1993
1992
  -v, --version Print version and exit.
1994
1993
  ```
1995
1994
 
1996
- Note: when `log:query` directives are present, Eyeling cannot stream output (the selected results depend on the saturated closure), so `--stream` has no effect in that mode.
1995
+ Note: when `log:query` directives are present, or when the program may produce `log:outputString` facts, Eyeling cannot stream its final user-facing output from partial derivations, so `--stream` has no effect in those cases. In the latter case Eyeling saturates first and then renders the collected output strings.
1997
1996
 
1998
1997
  See also:
1999
1998
 
@@ -2576,3 +2575,155 @@ That is the method:
2576
2575
  - duplicate-safe fixpoint closure
2577
2576
 
2578
2577
  That is why the result is 100%.
2578
+
2579
+ ---
2580
+
2581
+ <a id="app-f"></a>
2582
+
2583
+ ## Appendix F — The ARC approach: Answer • Reason Why • Check
2584
+
2585
+ A useful way to structure an Eyeling program is the ARC approach:
2586
+
2587
+ > Answer • Reason Why • Check
2588
+
2589
+ The idea is simple: do not stop at producing a result. Produce the result, explain why it is the right result, and include a concrete verification that fails loudly when an important assumption does not hold.
2590
+
2591
+ ARC treats a program as a small, accountable artifact built from three ingredients:
2592
+
2593
+ 1. Data
2594
+ 2. Logic
2595
+ 3. A Question
2596
+
2597
+ From these, we build a compact program that answers the question, explains the answer, and checks itself.
2598
+
2599
+ ### F.1 The three parts
2600
+
2601
+ #### Answer
2602
+
2603
+ The **Answer** is the direct response to the question being asked.
2604
+
2605
+ It should be short, specific, and easy to read. In Eyeling, this is often emitted as one or more `log:outputString` lines such as:
2606
+
2607
+ - the final decision
2608
+ - the selected item
2609
+ - the computed value
2610
+ - the resulting classification
2611
+
2612
+ A good Answer reads like something you could show to a user, an auditor, or a calling program.
2613
+
2614
+ #### Reason Why
2615
+
2616
+ The **Reason Why** explains why the Answer is correct.
2617
+
2618
+ This is not a full proof calculus or a hidden chain of thought. It is a concise, inspectable explanation grounded in the facts, rules, thresholds, identities, or policies that matter for the case. In practice, it often includes:
2619
+
2620
+ - the relevant inputs
2621
+ - the governing rule or policy
2622
+ - the key intermediate facts
2623
+ - the condition that made the conclusion follow
2624
+
2625
+ In Eyeling, the Reason Why is usually rendered as additional `log:outputString` lines derived from the same closure as the Answer.
2626
+
2627
+ #### Check
2628
+
2629
+ The **Check** is an independent validation step.
2630
+
2631
+ Its purpose is not to restate the Answer, but to test that important invariants still hold. A Check should fail loudly if the program’s assumptions break, if a data dependency is malformed, or if an edge case invalidates the intended conclusion.
2632
+
2633
+ In Eyeling, Checks are a natural fit for either:
2634
+
2635
+ - derived facts such as `:ok :signatureVerified true .`, or
2636
+ - inference fuses such as `{ ... } => false .` when a violation must stop execution.
2637
+
2638
+ This makes verification part of the program itself rather than something left to external commentary.
2639
+
2640
+ ### F.2 Proof = Reason Why + Check
2641
+
2642
+ ARC summarizes its trust model as:
2643
+
2644
+ > Proof = Reason Why + Check
2645
+
2646
+ That is a practical notion of proof. The Reason Why explains the logic in human terms. The Check verifies that the critical conditions actually hold at runtime.
2647
+
2648
+ For many real workflows, that combination is more useful than a bare result: it is inspectable, repeatable, and suitable for automation.
2649
+
2650
+ ### F.3 Why ARC fits Eyeling well
2651
+
2652
+ Eyeling already encourages the separation that ARC needs.
2653
+
2654
+ Rules derive facts. Facts can include output facts. Output is not printed eagerly during proof search; instead, `log:outputString` facts are collected from the final closure and rendered deterministically whenever they are present. This makes it natural to derive a structured Answer and Reason Why as part of the logic itself.
2655
+
2656
+ Checks also map well to Eyeling. A rule with conclusion `false` acts as an inference fuse: if its body becomes provable, execution stops with a hard failure. This is exactly the behavior we want for “must-hold” conditions.
2657
+
2658
+ So ARC in Eyeling is not an add-on. It is mostly a disciplined way of organizing what Eyeling already does well: derive conclusions, expose supporting facts, and enforce invariants.
2659
+
2660
+ ### F.4 A practical pattern
2661
+
2662
+ A simple ARC-oriented Eyeling file often has four layers:
2663
+
2664
+ 1. **Facts**
2665
+ Input data, parameters, policies, and known relationships.
2666
+
2667
+ 2. **Logic**
2668
+ Rules that derive the program’s internal conclusions.
2669
+
2670
+ 3. **Presentation**
2671
+ Rules that turn derived conclusions into `log:outputString` lines for the Answer and Reason Why.
2672
+
2673
+ 4. **Verification**
2674
+ Rules that derive check facts or trigger inference fuses on violations.
2675
+
2676
+ A useful habit is to keep these layers visually separate in the file.
2677
+
2678
+ ### F.5 A tiny template
2679
+
2680
+ ```n3
2681
+ @prefix : <http://example.org/> .
2682
+ @prefix log: <http://www.w3.org/2000/10/swap/log#> .
2683
+
2684
+ # Facts
2685
+ :case :input 42 .
2686
+
2687
+ # Logic
2688
+ { :case :input ?n . ?n math:greaterThan 10 . }
2689
+ => { :case :decision "allowed" . } .
2690
+
2691
+ # Answer
2692
+ { :case :decision ?d . }
2693
+ => { :answer log:outputString "Answer\n" .
2694
+ :answer log:outputString ?d . } .
2695
+
2696
+ # Reason Why
2697
+ { :case :input ?n . :case :decision ?d . }
2698
+ => { :why log:outputString "\nReason Why\n" .
2699
+ :why log:outputString "Input satisfied the rule threshold.\n" . } .
2700
+
2701
+ # Check
2702
+ { :case :decision "allowed" .
2703
+ :case :input ?n .
2704
+ ?n math:notGreaterThan 10 . }
2705
+ => false .
2706
+ ```
2707
+
2708
+ The exact presentation style can vary, but the shape remains the same: derive the result, explain the result, and verify the result.
2709
+
2710
+ ### F.6 What ARC is not
2711
+
2712
+ ARC does **not** mean:
2713
+
2714
+ - printing a result and calling it explained
2715
+ - replacing checks with prose
2716
+ - hiding the important assumptions
2717
+ - relying on “trust me” comments outside the executable artifact
2718
+
2719
+ A file follows ARC only when the answer, explanation, and validation are all carried by the program itself.
2720
+
2721
+ ### F.7 A good default for examples
2722
+
2723
+ For worked examples in this handbook, ARC is a strong default presentation style:
2724
+
2725
+ - **Answer** for the main result
2726
+ - **Reason Why** for the key supporting explanation
2727
+ - **Check** for invariants and fail-loud validation
2728
+
2729
+ This keeps examples readable for newcomers while also making them more useful as reusable, auditable logic artifacts.
package/README.md CHANGED
@@ -44,7 +44,7 @@ Show all options:
44
44
  npx eyeling --help
45
45
  ```
46
46
 
47
- Useful flags include `--proof-comments`, `--stream`, `--strings`, and `--enforce-https`.
47
+ Useful flags include `--proof-comments`, `--stream`, and `--enforce-https`. If the final closure contains any `log:outputString` triples, Eyeling now renders those strings automatically instead of printing N3 output.
48
48
 
49
49
  ## What gets printed?
50
50