eyeling 1.21.2 → 1.21.4
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 +65 -0
- package/README.md +0 -1
- package/dist/browser/eyeling.browser.js +12 -1
- package/examples/arc-bridge/README.md +208 -0
- package/examples/arc-bridge/delfour/delfour.data.json +68 -0
- package/examples/arc-bridge/delfour/delfour.expected.json +88 -0
- package/examples/arc-bridge/delfour/delfour.instance.schema.json +201 -0
- package/examples/arc-bridge/delfour/delfour.model.mjs +273 -0
- package/examples/arc-bridge/delfour/delfour.spec.md +118 -0
- package/examples/arc-bridge/flandor/flandor.data.json +107 -0
- package/examples/arc-bridge/flandor/flandor.expected.json +98 -0
- package/examples/arc-bridge/flandor/flandor.instance.schema.json +285 -0
- package/examples/arc-bridge/flandor/flandor.model.mjs +303 -0
- package/examples/arc-bridge/flandor/flandor.spec.md +156 -0
- package/examples/extra/flandor.js +349 -0
- package/examples/extra/output/flandor.txt +31 -0
- package/examples/flandor.n3 +425 -0
- package/examples/output/flandor.n3 +31 -0
- package/eyeling.js +12 -1
- package/lib/builtins.js +12 -1
- package/package.json +1 -2
- package/test/api.test.js +49 -0
- package/SEMANTICS.md +0 -41
package/HANDBOOK.md
CHANGED
|
@@ -31,6 +31,7 @@
|
|
|
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
33
|
- [Appendix F — The ARC approach: Answer • Reason Why • Check](#app-f)
|
|
34
|
+
- [Appendix G — Eyeling and the W3C CG Notation3 Semantics](#app-g)
|
|
34
35
|
|
|
35
36
|
---
|
|
36
37
|
|
|
@@ -1572,6 +1573,10 @@ A tiny `sprintf` subset:
|
|
|
1572
1573
|
- Supports only `%s` and `%%`.
|
|
1573
1574
|
- Any other specifier (`%d`, `%f`, …) causes the builtin to fail.
|
|
1574
1575
|
- Missing arguments are treated as empty strings.
|
|
1576
|
+
- The format string `fmt` itself must be string-castable.
|
|
1577
|
+
- Each `%s` argument may be any bound non-variable term:
|
|
1578
|
+
- string-castable terms (IRIs and literals) use their direct string value;
|
|
1579
|
+
- other bound terms (blank nodes, lists, quoted formulas, …) are rendered as N3.
|
|
1575
1580
|
|
|
1576
1581
|
### Length and character utilities (Eyeling extensions)
|
|
1577
1582
|
|
|
@@ -3104,3 +3109,63 @@ A file really follows ARC only when the answer, the explanation, and the validat
|
|
|
3104
3109
|
### F.9 Why this style is worth using
|
|
3105
3110
|
|
|
3106
3111
|
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.
|
|
3112
|
+
|
|
3113
|
+
<a id="app-g"></a>
|
|
3114
|
+
|
|
3115
|
+
## Appendix G — Eyeling and the W3C CG Notation3 Semantics
|
|
3116
|
+
|
|
3117
|
+
The purpose of this appendix is to say where Eyeling tracks the [W3C CG Notation3 semantics](https://w3c.github.io/N3/spec/semantics) closely, and where Eyeling makes deliberate operational choices of its own.
|
|
3118
|
+
|
|
3119
|
+
The comparison point here is the W3C CG Notation3 semantics document, not a claim that Eyeling is trying to be a line-by-line implementation of that document. Eyeling is a working reasoner, so some choices are shaped by execution, indexing, determinism, and the practical habits of N3 authors.
|
|
3120
|
+
|
|
3121
|
+
### G.1 Where Eyeling is strongly aligned
|
|
3122
|
+
|
|
3123
|
+
- **Core term model (IRIs, literals, variables, blank nodes, lists, quoted formulas):** The semantics document treats N3 terms as IRIs, literals, variables, lists, and graph terms. Eyeling’s internal model matches that shape directly through `Iri`, `Literal`, `Var`, `Blank`, `ListTerm`, and `GraphTerm`.
|
|
3124
|
+
|
|
3125
|
+
- **Quoted formulas need alpha-equivalence / isomorphism:** The semantics document defines isomorphism for graphs and graph terms using consistent renaming. Eyeling implements the same practical idea operationally as alpha-equivalence for `GraphTerm`, with consistent renaming as the criterion for a match.
|
|
3126
|
+
|
|
3127
|
+
- **Rules as implication (and `true` as empty formula):** The semantics document gives a special role to `log:implies` and treats `true` and `false` specially, with `true` corresponding to the empty formula. Eyeling follows that shape: it accepts both `{ P } => { C }` and `{ P } log:implies { C }`, and it treats `true` as `{}`.
|
|
3128
|
+
|
|
3129
|
+
- **Lists as first-class citizens (not just RDF collections):** The semantics document treats lists as genuine N3 terms. Eyeling does the same through `ListTerm`, and also materializes RDF `rdf:first` / `rdf:rest` chains into list terms so one list model can be used throughout the engine.
|
|
3130
|
+
|
|
3131
|
+
### G.2 Where Eyeling diverges or goes beyond the semantics document
|
|
3132
|
+
|
|
3133
|
+
#### G.2.1 Blank nodes in rule bodies: Eyeling chooses common N3 rule-writing practice
|
|
3134
|
+
|
|
3135
|
+
The semantics document describes blank nodes as existentially quantified with local scope. Eyeling intentionally rewrites blank nodes in **rule premises** into variables during normalization. In practice this makes body blanks behave like the placeholders many N3 authors expect when they write rules.
|
|
3136
|
+
|
|
3137
|
+
That is a real semantic choice. It is useful and intentional, but it is not the same as reading blank nodes as existentials everywhere.
|
|
3138
|
+
|
|
3139
|
+
#### G.2.2 Groundness of quoted formulas containing variables
|
|
3140
|
+
|
|
3141
|
+
In the semantics document, whether a graph term is ground depends on whether the underlying graph is closed, and nested formulas can still contain free variables when viewed in isolation. Eyeling makes a pragmatic engine choice: variables inside a `GraphTerm` do not make the surrounding triple non-ground. In the handbook this is summarized as “variables inside formulas do not leak.”
|
|
3142
|
+
|
|
3143
|
+
That supports indexing, matching, and duplicate checks, but it is not a one-to-one restatement of model-theoretic groundness for graph terms.
|
|
3144
|
+
|
|
3145
|
+
#### G.2.3 Eyeling defines operational behavior beyond what the semantics document currently fixes
|
|
3146
|
+
|
|
3147
|
+
The semantics document mainly fixes meaning around implication and the core N3 term/formula model. Eyeling goes further and gives operational meaning to a large standard library of builtins and control features. Examples include `math:*`, `string:*`, `list:*`, `time:*`, `log:includes`, `log:notIncludes`, `log:query`, and scoped closure via `log:conclusion`.
|
|
3148
|
+
|
|
3149
|
+
So Eyeling is not only implementing the semantics document; it is also defining engine behavior for features that the current document does not fully specify.
|
|
3150
|
+
|
|
3151
|
+
#### G.2.4 Inference fuses (`=> false`) are an engine-level procedural feature
|
|
3152
|
+
|
|
3153
|
+
The semantics document discusses `false` in relation to implication and constraints. Eyeling turns `{ ... } => false` into an engine-level hard failure with a visible message and failing exit status. That is a practical tooling feature: it lets a rule act like a checked invariant.
|
|
3154
|
+
|
|
3155
|
+
This is very useful in real programs, but it is an operational behavior of the reasoner, not something a model-theoretic semantics “executes.”
|
|
3156
|
+
|
|
3157
|
+
#### G.2.5 Surface-language coverage is not the same thing as semantic alignment
|
|
3158
|
+
|
|
3159
|
+
The semantics document discusses explicit quantification in its abstract syntax. Eyeling mostly exposes implicit quantification through `?x` variables and blank nodes, together with the rule-normalization choices described earlier. The handbook documents the supported surface forms Eyeling actually parses, which may be narrower than the full abstract surface discussed in the semantics document.
|
|
3160
|
+
|
|
3161
|
+
So even where the underlying ideas line up, the accepted concrete syntax may still be a proper subset.
|
|
3162
|
+
|
|
3163
|
+
### G.3 The practical takeaway
|
|
3164
|
+
|
|
3165
|
+
A good short summary is this:
|
|
3166
|
+
|
|
3167
|
+
- Eyeling is strongly aligned with the N3 semantics on the **core ontology of terms, quoted formulas, implication, and lists**.
|
|
3168
|
+
- Eyeling makes deliberate, implementation-shaped choices around **rule-body blanks, groundness of quoted formulas, and constraint execution**.
|
|
3169
|
+
- Eyeling also defines a wider operational language than the current semantics document, especially through builtins and scoped proof/query features.
|
|
3170
|
+
|
|
3171
|
+
So the handbook and the semantics document are best read as complementary. The semantics document explains the abstract shape of Notation3. The handbook explains how a compact working reasoner realizes that shape, and where it chooses a practical execution model over a purely model-theoretic presentation.
|
package/README.md
CHANGED
|
@@ -16,5 +16,4 @@ echo '@prefix : <http://example.org/> .
|
|
|
16
16
|
|
|
17
17
|
- **Handbook:** [eyereasoner.github.io/eyeling/HANDBOOK](https://eyereasoner.github.io/eyeling/HANDBOOK)
|
|
18
18
|
- **Playground:** [eyereasoner.github.io/eyeling/demo](https://eyereasoner.github.io/eyeling/demo)
|
|
19
|
-
- **Semantics:** [eyereasoner.github.io/eyeling/SEMANTICS](https://eyereasoner.github.io/eyeling/SEMANTICS)
|
|
20
19
|
- **Conformance report:** [codeberg.org/phochste/notation3tests/.../report.md](https://codeberg.org/phochste/notation3tests/src/branch/main/reports/report.md)
|
|
@@ -1012,6 +1012,13 @@ function simpleStringFormat(fmt, args) {
|
|
|
1012
1012
|
return out;
|
|
1013
1013
|
}
|
|
1014
1014
|
|
|
1015
|
+
function termToFormatArgString(t) {
|
|
1016
|
+
const s = termToJsString(t);
|
|
1017
|
+
if (s !== null) return s;
|
|
1018
|
+
if (t instanceof Var) return null;
|
|
1019
|
+
return termToN3(t, PrefixEnv.newDefault());
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1015
1022
|
// -----------------------------------------------------------------------------
|
|
1016
1023
|
// SWAP/N3 regex compatibility helper
|
|
1017
1024
|
// -----------------------------------------------------------------------------
|
|
@@ -4182,6 +4189,10 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
4182
4189
|
|
|
4183
4190
|
// string:format
|
|
4184
4191
|
// (limited: only %s and %% are supported, anything else ⇒ builtin fails)
|
|
4192
|
+
// The format string itself must be string-castable, but placeholder arguments
|
|
4193
|
+
// are allowed to be any bound non-variable term. Plain strings/IRIs keep their
|
|
4194
|
+
// direct string value; other terms fall back to N3 rendering so formatting a
|
|
4195
|
+
// bound blank node, list, or quoted formula does not make the whole builtin fail.
|
|
4185
4196
|
if (pv === STRING_NS + 'format') {
|
|
4186
4197
|
if (!(g.s instanceof ListTerm) || g.s.elems.length < 1) return [];
|
|
4187
4198
|
const fmtStr = termToJsString(g.s.elems[0]);
|
|
@@ -4189,7 +4200,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
4189
4200
|
|
|
4190
4201
|
const args = [];
|
|
4191
4202
|
for (let i = 1; i < g.s.elems.length; i++) {
|
|
4192
|
-
const aStr =
|
|
4203
|
+
const aStr = termToFormatArgString(g.s.elems[i]);
|
|
4193
4204
|
if (aStr === null) return [];
|
|
4194
4205
|
args.push(aStr);
|
|
4195
4206
|
}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# ARC Bridge
|
|
2
|
+
|
|
3
|
+
This directory holds **ARC Bridge** cases.
|
|
4
|
+
|
|
5
|
+
An ARC Bridge case sits between two existing forms in Eyeling:
|
|
6
|
+
|
|
7
|
+
- the **declarative N3** case in `examples/`, and
|
|
8
|
+
- the **specialized executable** case in `examples/extra/`.
|
|
9
|
+
|
|
10
|
+
Its purpose is to keep the ARC promise visible while making the case easy to read, easy to rerun, and easy to port.
|
|
11
|
+
|
|
12
|
+
In one line:
|
|
13
|
+
|
|
14
|
+
> `examples/arc-bridge/` presents controlled-English ARC specifications with reference ECMAScript realizations and JSON test vectors.
|
|
15
|
+
|
|
16
|
+
## Why this directory exists
|
|
17
|
+
|
|
18
|
+
Eyeling already has two valuable ways to present a case.
|
|
19
|
+
|
|
20
|
+
The files in `examples/` are ideal for seeing the logic in open declarative form. The files in `examples/extra/` are ideal when a case has already been shaped and we want a compact executable artifact that runs quickly.
|
|
21
|
+
|
|
22
|
+
ARC Bridge exists for the middle layer. It gives each case:
|
|
23
|
+
|
|
24
|
+
- a **normative statement** in controlled mathematical English,
|
|
25
|
+
- a **reference realization** in ECMAScript,
|
|
26
|
+
- a **concrete instance** in JSON, and
|
|
27
|
+
- an **expected result** for comparison and regression testing.
|
|
28
|
+
|
|
29
|
+
So ARC Bridge is not a replacement for either of the existing collections. It is a bridge between them.
|
|
30
|
+
|
|
31
|
+
## The ARC part
|
|
32
|
+
|
|
33
|
+
ARC means:
|
|
34
|
+
|
|
35
|
+
- **Answer**
|
|
36
|
+
- **Reason Why**
|
|
37
|
+
- **Check**
|
|
38
|
+
|
|
39
|
+
A good ARC Bridge case should preserve that trust pattern even though it is not written directly in N3.
|
|
40
|
+
|
|
41
|
+
That means:
|
|
42
|
+
|
|
43
|
+
- the **answer** is clearly identifiable,
|
|
44
|
+
- the **reason why** is visible as named clauses or derived predicates,
|
|
45
|
+
- and the **check** is real, meaning it could fail for a meaningful reason.
|
|
46
|
+
|
|
47
|
+
## What belongs here
|
|
48
|
+
|
|
49
|
+
A case belongs in `examples/arc-bridge/` when:
|
|
50
|
+
|
|
51
|
+
- there is a useful ARC-style case in `examples/`,
|
|
52
|
+
- there is value in giving the case a more direct operational form,
|
|
53
|
+
- but we still want the logic to stay explicit and auditable,
|
|
54
|
+
- with a specification that can be read independently of the code.
|
|
55
|
+
|
|
56
|
+
Typical uses:
|
|
57
|
+
|
|
58
|
+
- policy and governance examples,
|
|
59
|
+
- privacy-preserving decision examples,
|
|
60
|
+
- cases with a stable logical core and a small executable shell,
|
|
61
|
+
- cases that benefit from conformance-style testing.
|
|
62
|
+
|
|
63
|
+
## Directory shape
|
|
64
|
+
|
|
65
|
+
Each case should live in its own subdirectory.
|
|
66
|
+
|
|
67
|
+
For example:
|
|
68
|
+
|
|
69
|
+
```text
|
|
70
|
+
examples/arc-bridge/
|
|
71
|
+
delfour/
|
|
72
|
+
delfour.spec.md
|
|
73
|
+
delfour.data.json
|
|
74
|
+
delfour.model.mjs
|
|
75
|
+
delfour.expected.json
|
|
76
|
+
delfour.instance.schema.json
|
|
77
|
+
flandor/
|
|
78
|
+
flandor.spec.md
|
|
79
|
+
flandor.data.json
|
|
80
|
+
flandor.model.mjs
|
|
81
|
+
flandor.expected.json
|
|
82
|
+
flandor.instance.schema.json
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## The five files
|
|
86
|
+
|
|
87
|
+
Each ARC Bridge case should contain these files.
|
|
88
|
+
|
|
89
|
+
### 1. `name.spec.md`
|
|
90
|
+
|
|
91
|
+
The normative case description.
|
|
92
|
+
|
|
93
|
+
This file should use **controlled mathematical English**. It should define the vocabulary, the inputs, the derived predicates, the decision rule, the governance rule, the checks, and the output contract.
|
|
94
|
+
|
|
95
|
+
The spec should be written so that a careful reader can understand the case without reading the ECMAScript source first.
|
|
96
|
+
|
|
97
|
+
### 2. `name.data.json`
|
|
98
|
+
|
|
99
|
+
The concrete instance data.
|
|
100
|
+
|
|
101
|
+
This file contains the facts for the case: entities, thresholds, observed values, policies, timestamps, candidate actions, and any other case inputs.
|
|
102
|
+
|
|
103
|
+
### 3. `name.model.mjs`
|
|
104
|
+
|
|
105
|
+
The reference ECMAScript realization.
|
|
106
|
+
|
|
107
|
+
This file should implement the case directly and clearly. A good pattern is to map named clauses in the spec to named functions in the model.
|
|
108
|
+
|
|
109
|
+
For example:
|
|
110
|
+
|
|
111
|
+
- `clauseR1_exportWeakness`
|
|
112
|
+
- `clauseS2_recommendedPackage`
|
|
113
|
+
- `clauseG1_authorizedUse`
|
|
114
|
+
- `clauseM2_payloadHash`
|
|
115
|
+
|
|
116
|
+
The model is not the normative source. It is the **reference realization** of the normative source.
|
|
117
|
+
|
|
118
|
+
### 4. `name.expected.json`
|
|
119
|
+
|
|
120
|
+
The expected derived result.
|
|
121
|
+
|
|
122
|
+
This file is the conformance vector for the case. It should capture the main derived predicates, the selected answer, the visible checks, and any stable integrity values needed for regression testing.
|
|
123
|
+
|
|
124
|
+
### 5. `name.instance.schema.json`
|
|
125
|
+
|
|
126
|
+
The instance schema.
|
|
127
|
+
|
|
128
|
+
This file defines the required structure of the input JSON. It should be strict enough to catch malformed case instances before evaluation.
|
|
129
|
+
|
|
130
|
+
## How to read an ARC Bridge case
|
|
131
|
+
|
|
132
|
+
A good reading order is:
|
|
133
|
+
|
|
134
|
+
1. start with `name.spec.md`,
|
|
135
|
+
2. inspect `name.data.json`,
|
|
136
|
+
3. run `name.model.mjs`,
|
|
137
|
+
4. compare the result with `name.expected.json`,
|
|
138
|
+
5. then relate the case back to its N3 and specialized counterparts.
|
|
139
|
+
|
|
140
|
+
That order keeps the meaning visible before the operational details.
|
|
141
|
+
|
|
142
|
+
## Relationship to the rest of `examples/`
|
|
143
|
+
|
|
144
|
+
A useful mental model is:
|
|
145
|
+
|
|
146
|
+
- `examples/` shows ARC cases in **declarative Eyeling form**,
|
|
147
|
+
- `examples/arc-bridge/` shows the same kind of cases in **specification-plus-reference form**,
|
|
148
|
+
- `examples/extra/` shows selected cases in **specialized executable form**.
|
|
149
|
+
|
|
150
|
+
So the three collections are complementary:
|
|
151
|
+
|
|
152
|
+
- **N3** is best for seeing the logic in the open,
|
|
153
|
+
- **ARC Bridge** is best for stating the case normatively and running a portable reference model,
|
|
154
|
+
- **extra** is best for fast specialized execution.
|
|
155
|
+
|
|
156
|
+
## Design rules
|
|
157
|
+
|
|
158
|
+
When adding a case here, prefer the following.
|
|
159
|
+
|
|
160
|
+
### 1. Keep the spec normative
|
|
161
|
+
|
|
162
|
+
The spec should say what the case means. It should not merely paraphrase the code.
|
|
163
|
+
|
|
164
|
+
### 2. Keep the code direct
|
|
165
|
+
|
|
166
|
+
The ECMAScript model should say what it does and do what it says. Avoid unnecessary framework machinery.
|
|
167
|
+
|
|
168
|
+
### 3. Keep the data separate
|
|
169
|
+
|
|
170
|
+
Case facts belong in JSON, not hard-coded into the prose.
|
|
171
|
+
|
|
172
|
+
### 4. Keep checks substantive
|
|
173
|
+
|
|
174
|
+
A check should add confidence. It should not only restate the answer.
|
|
175
|
+
|
|
176
|
+
### 5. Keep names aligned
|
|
177
|
+
|
|
178
|
+
If a case is called `delfour` in `examples/` and `examples/extra/`, the ARC Bridge case should use the same base name.
|
|
179
|
+
|
|
180
|
+
## Suggested workflow for a new case
|
|
181
|
+
|
|
182
|
+
1. Start from a strong ARC-style N3 example.
|
|
183
|
+
2. Write a controlled-English specification of the case.
|
|
184
|
+
3. Move the concrete instance into JSON.
|
|
185
|
+
4. Implement a small ECMAScript reference model.
|
|
186
|
+
5. Capture the expected result in JSON.
|
|
187
|
+
6. Keep the visible output in Answer / Reason Why / Check shape.
|
|
188
|
+
7. Link the bridge case to its N3 and specialized counterparts.
|
|
189
|
+
|
|
190
|
+
## What ARC Bridge is not
|
|
191
|
+
|
|
192
|
+
ARC Bridge is not:
|
|
193
|
+
|
|
194
|
+
- a replacement for declarative Eyeling,
|
|
195
|
+
- a performance collection,
|
|
196
|
+
- a general application framework,
|
|
197
|
+
- or a place for prose that cannot be tested.
|
|
198
|
+
|
|
199
|
+
It exists to make a case simultaneously:
|
|
200
|
+
|
|
201
|
+
- readable,
|
|
202
|
+
- executable,
|
|
203
|
+
- checkable,
|
|
204
|
+
- and portable.
|
|
205
|
+
|
|
206
|
+
## In one line
|
|
207
|
+
|
|
208
|
+
`examples/arc-bridge/` presents controlled-English ARC case specifications with reference ECMAScript realizations, JSON instances, and expected results, as a bridge between declarative Eyeling examples and specialized executable companions.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "./delfour.instance.schema.json",
|
|
3
|
+
"caseName": "Delfour",
|
|
4
|
+
"retailer": "Delfour",
|
|
5
|
+
"question": "Is the Delfour self-scanner allowed to use a neutral shopping insight for shopping assistance, and if so what lower-sugar alternative should it suggest?",
|
|
6
|
+
"timestamps": {
|
|
7
|
+
"createdAt": "2025-10-05T20:33:48.907163+00:00",
|
|
8
|
+
"expiresAt": "2025-10-05T22:33:48.907185+00:00",
|
|
9
|
+
"authorizedAt": "2025-10-05T20:35:48.907163+00:00",
|
|
10
|
+
"dutyPerformedAt": "2025-10-05T20:37:48.907163+00:00"
|
|
11
|
+
},
|
|
12
|
+
"evaluationContext": {
|
|
13
|
+
"scopeDevice": "self-scanner",
|
|
14
|
+
"scopeEvent": "pick_up_scanner",
|
|
15
|
+
"purpose": "shopping_assist",
|
|
16
|
+
"prohibitedReusePurpose": "marketing",
|
|
17
|
+
"requestAction": "odrl:use"
|
|
18
|
+
},
|
|
19
|
+
"thresholds": {
|
|
20
|
+
"sugarPerServingGAtLeast": 10.0
|
|
21
|
+
},
|
|
22
|
+
"householdProfile": {
|
|
23
|
+
"condition": "Diabetes"
|
|
24
|
+
},
|
|
25
|
+
"catalog": [
|
|
26
|
+
{
|
|
27
|
+
"id": "prod:BIS_001",
|
|
28
|
+
"name": "Classic Tea Biscuits",
|
|
29
|
+
"sugarTenths": 120,
|
|
30
|
+
"sugarPerServing": 12.0
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"id": "prod:BIS_101",
|
|
34
|
+
"name": "Low-Sugar Tea Biscuits",
|
|
35
|
+
"sugarTenths": 30,
|
|
36
|
+
"sugarPerServing": 3.0
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"id": "prod:CHOC_050",
|
|
40
|
+
"name": "Milk Chocolate Bar",
|
|
41
|
+
"sugarTenths": 150,
|
|
42
|
+
"sugarPerServing": 15.0
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"id": "prod:CHOC_150",
|
|
46
|
+
"name": "85% Dark Chocolate",
|
|
47
|
+
"sugarTenths": 60,
|
|
48
|
+
"sugarPerServing": 6.0
|
|
49
|
+
}
|
|
50
|
+
],
|
|
51
|
+
"scan": {
|
|
52
|
+
"scannedProductId": "prod:BIS_001"
|
|
53
|
+
},
|
|
54
|
+
"insightPolicy": {
|
|
55
|
+
"id": "https://example.org/insight/delfour",
|
|
56
|
+
"metric": "sugar_g_per_serving",
|
|
57
|
+
"type": "ins:Insight",
|
|
58
|
+
"suggestionPolicy": "lower_metric_first_higher_price_ok",
|
|
59
|
+
"policyType": "odrl:Policy",
|
|
60
|
+
"policyProfile": "Delfour-Insight-Policy"
|
|
61
|
+
},
|
|
62
|
+
"integrity": {
|
|
63
|
+
"hashAlgorithm": "SHA-256",
|
|
64
|
+
"macAlgorithm": "HMAC-SHA-256",
|
|
65
|
+
"secret": "neutral-insight-demo-shared-secret",
|
|
66
|
+
"verificationMode": "trustedPrecomputedInput"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
{
|
|
2
|
+
"caseName": "Delfour",
|
|
3
|
+
"derived": {
|
|
4
|
+
"needsLowSugar": true,
|
|
5
|
+
"highSugarScanned": true,
|
|
6
|
+
"lowerSugarCandidateIds": ["prod:BIS_101", "prod:CHOC_150"],
|
|
7
|
+
"recommendedAlternativeId": "prod:BIS_101",
|
|
8
|
+
"recommendedAlternativeName": "Low-Sugar Tea Biscuits",
|
|
9
|
+
"alternativeLowersSugar": true
|
|
10
|
+
},
|
|
11
|
+
"envelope": {
|
|
12
|
+
"insight": {
|
|
13
|
+
"createdAt": "2025-10-05T20:33:48.907163+00:00",
|
|
14
|
+
"expiresAt": "2025-10-05T22:33:48.907185+00:00",
|
|
15
|
+
"id": "https://example.org/insight/delfour",
|
|
16
|
+
"metric": "sugar_g_per_serving",
|
|
17
|
+
"retailer": "Delfour",
|
|
18
|
+
"scopeDevice": "self-scanner",
|
|
19
|
+
"scopeEvent": "pick_up_scanner",
|
|
20
|
+
"suggestionPolicy": "lower_metric_first_higher_price_ok",
|
|
21
|
+
"threshold": 10,
|
|
22
|
+
"type": "ins:Insight"
|
|
23
|
+
},
|
|
24
|
+
"policy": {
|
|
25
|
+
"duty": {
|
|
26
|
+
"action": "odrl:delete",
|
|
27
|
+
"constraint": {
|
|
28
|
+
"leftOperand": "odrl:dateTime",
|
|
29
|
+
"operator": "odrl:eq",
|
|
30
|
+
"rightOperand": "2025-10-05T22:33:48.907185+00:00"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"permission": {
|
|
34
|
+
"action": "odrl:use",
|
|
35
|
+
"constraint": {
|
|
36
|
+
"leftOperand": "odrl:purpose",
|
|
37
|
+
"operator": "odrl:eq",
|
|
38
|
+
"rightOperand": "shopping_assist"
|
|
39
|
+
},
|
|
40
|
+
"target": "https://example.org/insight/delfour"
|
|
41
|
+
},
|
|
42
|
+
"profile": "Delfour-Insight-Policy",
|
|
43
|
+
"prohibition": {
|
|
44
|
+
"action": "odrl:distribute",
|
|
45
|
+
"constraint": {
|
|
46
|
+
"leftOperand": "odrl:purpose",
|
|
47
|
+
"operator": "odrl:eq",
|
|
48
|
+
"rightOperand": "marketing"
|
|
49
|
+
},
|
|
50
|
+
"target": "https://example.org/insight/delfour"
|
|
51
|
+
},
|
|
52
|
+
"type": "odrl:Policy"
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
"integrity": {
|
|
56
|
+
"canonicalEnvelope": "{\"insight\":{\"createdAt\":\"2025-10-05T20:33:48.907163+00:00\",\"expiresAt\":\"2025-10-05T22:33:48.907185+00:00\",\"id\":\"https://example.org/insight/delfour\",\"metric\":\"sugar_g_per_serving\",\"retailer\":\"Delfour\",\"scopeDevice\":\"self-scanner\",\"scopeEvent\":\"pick_up_scanner\",\"suggestionPolicy\":\"lower_metric_first_higher_price_ok\",\"threshold\":10.0,\"type\":\"ins:Insight\"},\"policy\":{\"duty\":{\"action\":\"odrl:delete\",\"constraint\":{\"leftOperand\":\"odrl:dateTime\",\"operator\":\"odrl:eq\",\"rightOperand\":\"2025-10-05T22:33:48.907185+00:00\"}},\"permission\":{\"action\":\"odrl:use\",\"constraint\":{\"leftOperand\":\"odrl:purpose\",\"operator\":\"odrl:eq\",\"rightOperand\":\"shopping_assist\"},\"target\":\"https://example.org/insight/delfour\"},\"profile\":\"Delfour-Insight-Policy\",\"prohibition\":{\"action\":\"odrl:distribute\",\"constraint\":{\"leftOperand\":\"odrl:purpose\",\"operator\":\"odrl:eq\",\"rightOperand\":\"marketing\"},\"target\":\"https://example.org/insight/delfour\"},\"type\":\"odrl:Policy\"}}",
|
|
57
|
+
"payloadHashSHA256": "e1ad69852c98ca7697a164dbc6f0ca28f873508a6676865dba37b81faa66ebcb",
|
|
58
|
+
"envelopeHmacSHA256": "518a84185e2975928c6c935dae6e251a071766078c6e9e70d6f583a1147728db",
|
|
59
|
+
"verificationMode": "trustedPrecomputedInput"
|
|
60
|
+
},
|
|
61
|
+
"answer": {
|
|
62
|
+
"sentence": "The scanner is allowed to use a neutral shopping insight and recommends Low-Sugar Tea Biscuits instead of Classic Tea Biscuits.",
|
|
63
|
+
"scannedProduct": "Classic Tea Biscuits",
|
|
64
|
+
"suggestedAlternative": "Low-Sugar Tea Biscuits",
|
|
65
|
+
"payloadHashSHA256": "e1ad69852c98ca7697a164dbc6f0ca28f873508a6676865dba37b81faa66ebcb",
|
|
66
|
+
"envelopeHmacSHA256": "518a84185e2975928c6c935dae6e251a071766078c6e9e70d6f583a1147728db"
|
|
67
|
+
},
|
|
68
|
+
"reasonWhy": [
|
|
69
|
+
"The phone desensitizes a diabetes-related household condition into a scoped low-sugar need, wraps it in an expiring Insight+Policy envelope, and signs it.",
|
|
70
|
+
"scanned product : Classic Tea Biscuits",
|
|
71
|
+
"suggested alternative: Low-Sugar Tea Biscuits",
|
|
72
|
+
"payload SHA-256 : e1ad69852c98ca7697a164dbc6f0ca28f873508a6676865dba37b81faa66ebcb",
|
|
73
|
+
"HMAC-SHA256 : 518a84185e2975928c6c935dae6e251a071766078c6e9e70d6f583a1147728db"
|
|
74
|
+
],
|
|
75
|
+
"checks": {
|
|
76
|
+
"signatureVerifies": true,
|
|
77
|
+
"payloadHashMatches": true,
|
|
78
|
+
"minimizationRespected": true,
|
|
79
|
+
"scopeComplete": true,
|
|
80
|
+
"authorizationAllowed": true,
|
|
81
|
+
"highSugarBanner": true,
|
|
82
|
+
"alternativeLowersSugar": true,
|
|
83
|
+
"dutyTimingConsistent": true,
|
|
84
|
+
"marketingProhibited": true
|
|
85
|
+
},
|
|
86
|
+
"allChecksPass": true,
|
|
87
|
+
"arcText": "=== Answer ===\nThe scanner is allowed to use a neutral shopping insight and recommends Low-Sugar Tea Biscuits instead of Classic Tea Biscuits.\n\n=== Reason Why ===\nThe phone desensitizes a diabetes-related household condition into a scoped low-sugar need, wraps it in an expiring Insight+Policy envelope, and signs it.\nscanned product : Classic Tea Biscuits\nsuggested alternative: Low-Sugar Tea Biscuits\npayload SHA-256 : e1ad69852c98ca7697a164dbc6f0ca28f873508a6676865dba37b81faa66ebcb\nHMAC-SHA256 : 518a84185e2975928c6c935dae6e251a071766078c6e9e70d6f583a1147728db\n\n=== Check ===\nsignature verifies : yes\npayload hash matches : yes\nminimization strips sensitive terms: yes\nscope complete : yes\nauthorization allowed : yes\nhigh-sugar banner : yes\nalternative lowers sugar : yes\nduty timing consistent : yes\nmarketing prohibited : yes"
|
|
88
|
+
}
|