skynet-graph 1.2.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.
Files changed (213) hide show
  1. package/CONTRIBUTING.md +22 -0
  2. package/LICENSE +661 -0
  3. package/README.md +245 -0
  4. package/bin/sg +20 -0
  5. package/concepts/README.md +23 -0
  6. package/concepts/_substrate/Claim/Confidence/Trusted.json +6 -0
  7. package/concepts/_substrate/Claim/Confidence.json +10 -0
  8. package/concepts/_substrate/Claim/Freshness/Stale.json +7 -0
  9. package/concepts/_substrate/Claim/Freshness.json +5 -0
  10. package/concepts/_substrate/Claim/Verification/Refuted.json +6 -0
  11. package/concepts/_substrate/Claim/Verification.json +6 -0
  12. package/concepts/_substrate/Claim.json +4 -0
  13. package/concepts/_substrate/Frontier/InBeam.json +6 -0
  14. package/concepts/_substrate/Frontier/Stuck.json +6 -0
  15. package/concepts/_substrate/Frontier.json +5 -0
  16. package/concepts/_substrate/Intake/ToTask.json +22 -0
  17. package/concepts/_substrate/Intake/Typed.json +10 -0
  18. package/concepts/_substrate/Intake.json +27 -0
  19. package/concepts/_substrate/Task/Answer.json +12 -0
  20. package/concepts/_substrate/Task/Complexity/Atomic.json +5 -0
  21. package/concepts/_substrate/Task/Complexity/Compound/Expansion.json +7 -0
  22. package/concepts/_substrate/Task/Complexity/Compound.json +6 -0
  23. package/concepts/_substrate/Task/Complexity.json +6 -0
  24. package/concepts/_substrate/Task/EvalComplexity.json +13 -0
  25. package/concepts/_substrate/Task/ReportUp.json +6 -0
  26. package/concepts/_substrate/Task/Rollup.json +10 -0
  27. package/concepts/_substrate/Task.json +5 -0
  28. package/concepts/clinical/Diagnosis/Medication.json +6 -0
  29. package/concepts/clinical/Diagnosis.json +15 -0
  30. package/concepts/clinical/Observation/LabValue/OutOfRange.json +6 -0
  31. package/concepts/clinical/Observation/LabValue.json +5 -0
  32. package/concepts/clinical/Observation.json +6 -0
  33. package/concepts/common/Document/pathBasket.json +6 -0
  34. package/concepts/common/Document.json +3 -0
  35. package/concepts/common/Edge/Distance.json +13 -0
  36. package/concepts/common/Edge/Stay/LongStay.json +8 -0
  37. package/concepts/common/Edge/Stay.json +8 -0
  38. package/concepts/common/Edge/Travel/LongTravel.json +16 -0
  39. package/concepts/common/Edge/Travel/ShortTravel.json +11 -0
  40. package/concepts/common/Edge/Travel/targetNode.json +7 -0
  41. package/concepts/common/Edge/Travel.json +7 -0
  42. package/concepts/common/Edge.json +3 -0
  43. package/concepts/common/Vertice.json +3 -0
  44. package/concepts/supply/Fulfillment.json +10 -0
  45. package/concepts/supply/Inventory/Reorder.json +7 -0
  46. package/concepts/supply/Inventory.json +5 -0
  47. package/concepts/supply/Procurement/SupplierConfirm.json +6 -0
  48. package/concepts/supply/Procurement.json +8 -0
  49. package/concepts/supply/Transport.json +5 -0
  50. package/doc/API.md +556 -0
  51. package/doc/CAPABILITIES.md +373 -0
  52. package/doc/MODELISATION.md +511 -0
  53. package/doc/architecture.md +267 -0
  54. package/doc/concept-as-graph.md +379 -0
  55. package/doc/concept-learning.md +168 -0
  56. package/doc/creative-loop-map.md +202 -0
  57. package/doc/original-2016-doc.md +148 -0
  58. package/doc/usage.md +501 -0
  59. package/lib/authoring/abstract.js +401 -0
  60. package/lib/authoring/abstraction.js +190 -0
  61. package/lib/authoring/adapt.js +393 -0
  62. package/lib/authoring/ancestry.js +216 -0
  63. package/lib/authoring/author.js +147 -0
  64. package/lib/authoring/bounded-merge.js +57 -0
  65. package/lib/authoring/canon.js +158 -0
  66. package/lib/authoring/clock.js +123 -0
  67. package/lib/authoring/combinator.js +92 -0
  68. package/lib/authoring/compete.js +76 -0
  69. package/lib/authoring/compose-hotspot.js +314 -0
  70. package/lib/authoring/compress.js +279 -0
  71. package/lib/authoring/concept-net.js +254 -0
  72. package/lib/authoring/concepts.js +66 -0
  73. package/lib/authoring/context-project.js +277 -0
  74. package/lib/authoring/contract.js +476 -0
  75. package/lib/authoring/corpus-pack.js +125 -0
  76. package/lib/authoring/cost-probe.js +86 -0
  77. package/lib/authoring/crystallize.js +555 -0
  78. package/lib/authoring/dag-decompose.js +256 -0
  79. package/lib/authoring/dataset-adapter.js +253 -0
  80. package/lib/authoring/debug-provider.js +92 -0
  81. package/lib/authoring/decompose.js +343 -0
  82. package/lib/authoring/emittability.js +236 -0
  83. package/lib/authoring/equilibrium.js +160 -0
  84. package/lib/authoring/extract.js +153 -0
  85. package/lib/authoring/forest.js +55 -0
  86. package/lib/authoring/forge-fallback.js +116 -0
  87. package/lib/authoring/givens.js +121 -0
  88. package/lib/authoring/glossary.js +177 -0
  89. package/lib/authoring/grammar-graph.js +191 -0
  90. package/lib/authoring/granularity.js +80 -0
  91. package/lib/authoring/graph-net.js +108 -0
  92. package/lib/authoring/ground.js +148 -0
  93. package/lib/authoring/higher-order.js +85 -0
  94. package/lib/authoring/hotspot.js +132 -0
  95. package/lib/authoring/hysteresis.js +85 -0
  96. package/lib/authoring/index.js +106 -0
  97. package/lib/authoring/lattice-morphism.js +61 -0
  98. package/lib/authoring/lattice-pack.js +148 -0
  99. package/lib/authoring/leaf-io.js +77 -0
  100. package/lib/authoring/library.js +156 -0
  101. package/lib/authoring/lifecycle.js +92 -0
  102. package/lib/authoring/loop.js +193 -0
  103. package/lib/authoring/master-loop.js +132 -0
  104. package/lib/authoring/mdl.js +209 -0
  105. package/lib/authoring/memo-stability.js +122 -0
  106. package/lib/authoring/method-explorer.js +138 -0
  107. package/lib/authoring/method-pack.js +181 -0
  108. package/lib/authoring/method.js +202 -0
  109. package/lib/authoring/mine.js +510 -0
  110. package/lib/authoring/mount.js +119 -0
  111. package/lib/authoring/negotiate.js +100 -0
  112. package/lib/authoring/parametric.js +139 -0
  113. package/lib/authoring/reaggregate.js +75 -0
  114. package/lib/authoring/rebalance.js +157 -0
  115. package/lib/authoring/recall.js +135 -0
  116. package/lib/authoring/registry.js +350 -0
  117. package/lib/authoring/relearn.js +147 -0
  118. package/lib/authoring/retention.js +89 -0
  119. package/lib/authoring/segment-proxy.js +114 -0
  120. package/lib/authoring/serve-leaf.js +64 -0
  121. package/lib/authoring/slot-aware-serve.js +77 -0
  122. package/lib/authoring/sound-invoke.js +59 -0
  123. package/lib/authoring/split-serve.js +74 -0
  124. package/lib/authoring/ste.js +239 -0
  125. package/lib/authoring/stock.js +101 -0
  126. package/lib/authoring/store.js +94 -0
  127. package/lib/authoring/supervise.js +138 -0
  128. package/lib/authoring/support.js +131 -0
  129. package/lib/authoring/task-mirror.js +51 -0
  130. package/lib/authoring/typed-loop.js +160 -0
  131. package/lib/authoring/validate.js +569 -0
  132. package/lib/authoring/widen.js +88 -0
  133. package/lib/combos/appliance.js +189 -0
  134. package/lib/combos/critique.js +377 -0
  135. package/lib/combos/defaults.js +86 -0
  136. package/lib/combos/durable-runner.js +115 -0
  137. package/lib/combos/forge.js +209 -0
  138. package/lib/combos/index.js +86 -0
  139. package/lib/combos/learning-library.js +253 -0
  140. package/lib/combos/mixture-serve.js +193 -0
  141. package/lib/combos/plan-loop.js +192 -0
  142. package/lib/combos/proxy-cache.js +272 -0
  143. package/lib/combos/self-mod.js +94 -0
  144. package/lib/durable/audit.js +102 -0
  145. package/lib/durable/checkpoint-store.js +550 -0
  146. package/lib/durable/fold.js +62 -0
  147. package/lib/durable/interpreter.js +242 -0
  148. package/lib/durable/xlate.js +185 -0
  149. package/lib/graph/Graph.js +2486 -0
  150. package/lib/graph/expr.js +307 -0
  151. package/lib/graph/index.js +26 -0
  152. package/lib/graph/log.js +134 -0
  153. package/lib/graph/objects/Concept.js +382 -0
  154. package/lib/graph/objects/Entity.js +503 -0
  155. package/lib/graph/objects/Node.js +57 -0
  156. package/lib/graph/objects/PathMap.js +557 -0
  157. package/lib/graph/objects/Segment.js +100 -0
  158. package/lib/graph/tasks/stabilize.js +59 -0
  159. package/lib/graph/tasks/taskflow.js +247 -0
  160. package/lib/index.js +122 -0
  161. package/lib/load.js +132 -0
  162. package/lib/providers/backends.js +117 -0
  163. package/lib/providers/borderline.js +129 -0
  164. package/lib/providers/cache.js +226 -0
  165. package/lib/providers/canonicalize.js +198 -0
  166. package/lib/providers/constat.js +107 -0
  167. package/lib/providers/geo.js +53 -0
  168. package/lib/providers/index.js +116 -0
  169. package/lib/providers/intake.js +263 -0
  170. package/lib/providers/llm-local.js +88 -0
  171. package/lib/providers/llm.js +236 -0
  172. package/lib/providers/local-host.js +197 -0
  173. package/lib/providers/merge-consistency.js +162 -0
  174. package/lib/providers/nogood.js +149 -0
  175. package/lib/providers/reason-loop.js +223 -0
  176. package/lib/providers/semiring.js +285 -0
  177. package/lib/providers/solver-fork.js +163 -0
  178. package/lib/providers/stats.js +228 -0
  179. package/lib/providers/verify.js +120 -0
  180. package/lib/runtime/index.js +135 -0
  181. package/lib/runtime/invoke-pool.js +92 -0
  182. package/lib/runtime/protocol.js +210 -0
  183. package/lib/runtime/transport-socket.js +77 -0
  184. package/lib/runtime/worker-entry.js +31 -0
  185. package/lib/sg/cli.js +601 -0
  186. package/lib/sg/log-sinks.js +214 -0
  187. package/lib/sg/mcp.js +395 -0
  188. package/lib/sg/proxy-run.js +66 -0
  189. package/lib/sg/serve-demo.js +185 -0
  190. package/lib/sg/serve.js +205 -0
  191. package/lib/sg/trace.js +118 -0
  192. package/lib/studio/protocol.js +45 -0
  193. package/lib/studio/public/app.js +310 -0
  194. package/lib/studio/public/components/ConceptEditor.js +43 -0
  195. package/lib/studio/public/components/ConceptTree.js +43 -0
  196. package/lib/studio/public/components/CorpusPanel.js +68 -0
  197. package/lib/studio/public/components/ForkTree.js +36 -0
  198. package/lib/studio/public/components/GrammarGraph.js +99 -0
  199. package/lib/studio/public/components/GraphCanvas.js +156 -0
  200. package/lib/studio/public/components/Inspector.js +48 -0
  201. package/lib/studio/public/components/LearningPanel.js +85 -0
  202. package/lib/studio/public/components/PromptConsole.js +46 -0
  203. package/lib/studio/public/components/ProviderTrace.js +39 -0
  204. package/lib/studio/public/components/SessionSplit.js +47 -0
  205. package/lib/studio/public/components/TilingOverlay.js +40 -0
  206. package/lib/studio/public/components/Timeline.js +57 -0
  207. package/lib/studio/public/index.html +26 -0
  208. package/lib/studio/public/styles.css +185 -0
  209. package/lib/studio/public/ws.js +58 -0
  210. package/lib/studio/server.js +130 -0
  211. package/lib/studio/session.js +397 -0
  212. package/lib/studio/studio.js +149 -0
  213. package/package.json +42 -0
package/README.md ADDED
@@ -0,0 +1,245 @@
1
+ <h1 align="center">skynet-graph</h1>
2
+
3
+ <p align="center">
4
+ <b>Make a small local model work a big task the way humans always have — piece by piece.</b><br>
5
+ The engine cuts the task into typed pieces, <i>zooms</i> the model onto one piece at a time with exactly
6
+ the context it needs, keeps every result as a typed fact with provenance so a late correction re-derives
7
+ for free, and steers the model's output against a certified method vocabulary. Nothing leaves the machine.
8
+ </p>
9
+
10
+ <p align="center">
11
+ <img src="./doc/img/headImg.png">
12
+ </p>
13
+
14
+ <p align="center"><i>Active R&D · a CommonJS library to embed + an <code>sg</code> CLI · Node 18+, no build step · AGPL-3.0</i></p>
15
+
16
+ <p align="center">
17
+ <a href="https://doi.org/10.5281/zenodo.21032471"><img src="https://zenodo.org/badge/DOI/10.5281/zenodo.21032471.svg" alt="DOI"></a>
18
+ <a href="https://doi.org/10.5281/zenodo.21201877"><img src="https://zenodo.org/badge/DOI/10.5281/zenodo.21201877.svg" alt="DOI"></a>
19
+ </p>
20
+
21
+ ## What you get
22
+
23
+ A 27B model crushed to 9.5 GB (IQ2) runs on your GPU — but quantization broke part of its judgment,
24
+ and any big task overflows it. This engine gives that model four things, **each measured on real GPUs,
25
+ with negative controls and deterministic re-runs**:
26
+
27
+ - **Big tasks, piece by piece** — the model never sees the whole problem, only one bounded piece at a
28
+ time: accuracy **×2.5–3.2** on multi-step tasks, and where whole-context prompting **collapses (0/33)**,
29
+ the pieces hold (**10/33**).
30
+ - **Repair for low quants** — verified method shapes steer the output: SQL **8→63 %**, finance tables
31
+ **7→62 %**, at **zero big-model calls** on covered queries.
32
+ - **Task memory that reopens** — a late correction automatically un-does everything that depended on
33
+ it, and "done" steps **reopen themselves with the reason**. No stale state, ever.
34
+ - **An external think mode** — benched head-to-head: the model's *native* think budget scores
35
+ **13/24 ≈ a coin flip** on side-judgment; the external critical mind renders **0 wrong verdicts**
36
+ (24/24 provable on a declared frame, an honest UNDECIDED otherwise).
37
+
38
+ **See it in 30 seconds — no model, no GPU** (a deterministic replay of a real end-to-end run — the
39
+ 9.5 GB quant analyzing an annual report, erratum and crash included):
40
+
41
+ ```bash
42
+ git clone https://github.com/9pings/skynet-graph && cd skynet-graph
43
+ npm install && node examples/integrated-demo/run.js --replay # 7 checks, bit-identical
44
+ ```
45
+
46
+ Every claim on this page follows a standing rule: **a refuted claim is removed the day it falls**
47
+ (several are listed below on purpose). The full feature map — maturity bars, numbers, limits,
48
+ snippets — is **[doc/CAPABILITIES.md](doc/CAPABILITIES.md)**.
49
+
50
+ Where it sits in your setup — two zero-integration doors into one local loop:
51
+
52
+ ```
53
+ [your agent / app / any OpenAI client]
54
+
55
+ ├─► OpenAI-compatible endpoint sg serve → http://127.0.0.1:4747/v1
56
+ └─► MCP tools sg mcp → ask · hint · propose · state_recall · plan_sync · critique
57
+
58
+
59
+ [typed reasoning graph] plan · admission gates · typed ledger · JTMS memory
60
+
61
+
62
+ [your local GGUF model] — nothing leaves the machine
63
+ ```
64
+
65
+ ---
66
+
67
+ ## The four capabilities, measured
68
+
69
+ Small local models are fine on a *surface* step; they derail when a request makes them **compose**
70
+ several things at once. This library puts them in front of one surface at a time.
71
+
72
+ **Proof degrees:** **[live]** = measured on GPU with real local models · **[measured]** = deterministic,
73
+ replayable without a model · **[PoC]** = an accounting demonstration, not a benchmark.
74
+
75
+ | Capability | What happens | Measured |
76
+ |---|---|---|
77
+ | **Repair low-quants** | a menu of *certified* method shapes steers a heavily-quantized model's output — it recovers most of what compression broke, at **zero big-model calls** | SQL, covered queries: low-quant 8→**63 %** (high-quant 46→92 %), N=201 · finance, traffic view: 7→**62 %** (20→78 %), N=120 · [live] |
78
+ | **Task memory that reopens** | task state = typed facts with provenance (JTMS): a drifted premise **retracts its consequences in cascade**, and a "done" step **reopens itself with the reason** — it never rots | recomputable drift re-derives at **0 model calls**, selectively (independent facts untouched); crash-replay is bit-identical at 0 calls [live] · 100 % recall at **894 constant tokens/call** vs 50 % at 4 286 for a carry-everything baseline [PoC] |
79
+ | **Piece-by-piece (the zoom)** | the task becomes a typed DAG; each piece is served with ONLY its bounded neighbourhood (parent goal + resolved inputs + what to produce) — the model never sees the whole | cross-domain at N=200/domain (560 tasks total): math word problems 16 %→**52 %** (×3.2), financial-table QA 20 %→**50 %** (×2.5), bootstrap CIs hold [live] · **where the lone model collapses, the pieces hold**: deep tasks 0/33 whole vs 10/33 decomposed [live] · on 20 compound "monster" tasks (~20 ops): whole-context floors at **0/20**, hierarchical 2-level split reaches 73 % of sections [live] |
80
+ | **An external think mode** | the model proposes; the graph **refutes with the reason** and enumerates the admissible options (tested through its own gate, never guessed); the model revises — bounded, with honest refusal | one dialogue round: 17/24 → **24/24** correct at zero false admissions [live] · native think budget vs the external critical mind on side-judgment: **13/24 (≈ chance, 11 confident wrong verdicts) vs 0 wrong verdicts** — 24/24 mechanical on a declared perimeter, honest UNDECIDED otherwise [live] · disciplined argument coverage: **77 % vs 58 %** whole-context at 48 arguments [live] · anchored generation of MISSING theses: **0 fabrication** across every negative control [live] |
81
+
82
+ | Feature — details per row in [doc/CAPABILITIES.md](doc/CAPABILITIES.md) | Maturity (6-rung honest scale; rung 6 = external replications, empty pre-launch) |
83
+ |---|---|
84
+ | [F1 — Repair low-quants](doc/CAPABILITIES.md#f1-low-quant-repair) | `█████░` 5/6 — product-integrated |
85
+ | [F2 — The piece-by-piece zoom](doc/CAPABILITIES.md#f2-piece-by-piece-zoom-on-big-tasks) | `████░░` 4/6 — measured at scale, not turnkey yet |
86
+ | [F3 — Task memory that reopens](doc/CAPABILITIES.md#f3-task-memory-that-reopens) | `█████░` 5/6 — product-integrated |
87
+ | [F4 — External think mode](doc/CAPABILITIES.md#f4-external-think-mode) | `█████░` 5/6 — product-integrated |
88
+ | [F5 — External critical mind](doc/CAPABILITIES.md#f5-external-critical-mind) | `█████░` 5/6 — product-integrated |
89
+ | [F6 — Local `.sgc` rooms](doc/CAPABILITIES.md#f6-local-sgc-rooms) | `█████░` 5/6 — product-integrated |
90
+ | [F7 — The versionable reasoning substrate](doc/CAPABILITIES.md#f7-the-versionable-reasoning-substrate) | `█████░` 5/6 — product-integrated |
91
+ | [The integrated demo](doc/CAPABILITIES.md#the-integrated-demo) | `█████░` 5/6 — ships in this repo |
92
+
93
+ The certified vocabulary these capabilities lean on is **fuel, not the headline**: a *forge* (`sg forge`)
94
+ builds `.sgc` method stocks from any dataset that has an executable oracle, behind a **zero-false-admission**
95
+ gate (held across every campaign: 0 false shapes admitted, 3 datasets, 2 forge models) — each stock ships
96
+ with an auditable sha256 validation dossier.
97
+
98
+ ### Where it beats what you would reach for today
99
+
100
+ Each row is a measured delta or a checked absence — details, limits and snippets per row in
101
+ [doc/CAPABILITIES.md](doc/CAPABILITIES.md).
102
+
103
+ | You would reach for | The known weakness there | Here, measured |
104
+ |---|---|---|
105
+ | a bigger / higher-quant model | needs VRAM you don't have | certified-stock steering on *your* hardware: SQL 8→**63 %**, finance 7→**62 %**, 0 frontier calls on the covered slice |
106
+ | an agent scratchpad / vector memory | boxes only get ticked; similarity retrieval serves **stale** answers | premise drift → cascade retraction + reopen-with-reason: **12/12 vs 0/12** (stale) on drift, 0 model calls |
107
+ | a decomposition framework | free-text plans, unbounded context growth | typed needs/produces + bounded per-piece context: ×2.5–3.2 at N=200, and **0/33 → 10/33** where the whole-task baseline collapses |
108
+ | a native think mode / self-critique loop | self-critique underperforms external feedback (2024-25 literature, + our own refutation ×3) | benched head-to-head: a native think budget scores **13/24 ≈ chance** on side-judgment (11 confident wrong verdicts) — the external critical mind renders **0 wrong verdicts**: 24/24 mechanical on a declared perimeter, honest UNDECIDED otherwise; and the gate **never yields** (17/24 → **24/24** at zero false admissions) |
109
+ | LLM-as-judge / a debate prompt | miscalibrated, gameable, no audit trail | witness-gated coverage (0 fabrication), typed ledger, and a judge that **declines by measured bound** (UNDECIDED below margin) |
110
+ | a prompt hub / RAG index for methods | anything pasted in is trusted | `.sgc` rooms: admission-gated import (a bad bundle never lands), sha256 dossiers, local files you own |
111
+ | a rules engine / event sourcing | fires rules or versions events — never versions *belief* | rollback / diff / fork / merge on what the system currently holds true, **rules included** — no market equivalent found |
112
+
113
+ **What is honestly NOT claimed** (each of these was tested, and the page follows the results):
114
+ - the guarantee is **at admission, not at execution** — at use time the stock *orients*; a suggestion is not
115
+ a correctness proof (a runtime "trusted answers" tier was tested and **refuted** — removed);
116
+ - the win lives on the **typed, recurrent slice** of the work: free prose and genuinely novel reasoning stay
117
+ in the model, without guarantee — a design boundary, not a bug;
118
+ - forge yield is a **per-domain parameter** (not model-invariant — refuted), and amortization is a property
119
+ of the *domain's* stereotypy;
120
+ - the small model executes surface steps well; it is **not** the task cutter (measured limit);
121
+ - a **verdict** (weighing which side wins) is reliable **on certified perimeters** or at wide margins;
122
+ on free, uncertified content the engine renders **counts + zero-false coverage + an honest UNDECIDED**,
123
+ not a verdict — the measured decidability bound, kept rather than papered over (graded weighting and
124
+ goal-criteria weighting were both tested and **refuted** for a low-quant judge).
125
+
126
+ ## Quick start
127
+
128
+ ```bash
129
+ npm install # no build step — pure CommonJS, Node 18+
130
+ npm test # 1350 tests — 0 failures, 2 known skips
131
+
132
+ node bin/sg run --concepts ./concepts --builtins --seed ./seed.json
133
+ node examples/integrated-demo/run.js --replay # the four capabilities assembled, no GPU
134
+ ```
135
+
136
+ ```js
137
+ const Graph = require('skynet-graph');
138
+
139
+ // boot from folders of concept rules + providers, stabilize, read facts:
140
+ const g = Graph.fromDirs({
141
+ concepts: './concepts',
142
+ builtins: true, // wire the packaged geo + LLM providers
143
+ seed: { conceptMaps: [
144
+ { _id: 'a', Node: true, Position: { lat: 48.85, lng: 2.35 } },
145
+ { _id: 'b', Node: true, Position: { lat: 1.35, lng: 103.8 } },
146
+ { _id: 's', Segment: true, originNode: 'a', targetNode: 'b' },
147
+ ]},
148
+ conf: { onStabilize: g => console.log(g.serialize().graph) }, // s now carries Distance { inKm: 10728 }
149
+ });
150
+ ```
151
+
152
+ The `LLM::complete` provider is backend-agnostic: inject any async `ask`, or use the bundled client
153
+ (`LLM_API=anthropic`, default; `LLM_API=openai` for vLLM / llama.cpp / LM-Studio).
154
+
155
+ ### Serve it — zero-integration surfaces
156
+
157
+ ```bash
158
+ # OpenAI-compatible endpoint over the local-first proxy cache: point ANY OpenAI client's baseURL at it.
159
+ # Covered queries → served from the verified local stock at 0 frontier calls; provenance headers on every
160
+ # completion (x-sg-*); 0 hallucination by construction on the covered slice.
161
+ sg serve --frontier-model <path.gguf> --store ./stock.json # → http://127.0.0.1:4747/v1
162
+
163
+ # The same capabilities as MCP TOOLS for an agent host (typed refusals arrive STRUCTURED):
164
+ claude mcp add sg -- node bin/sg mcp --frontier-model <path.gguf> --store ./stock.json
165
+
166
+ # One-command typed QA, and the visual debugger:
167
+ sg ask "your question" --concepts ./concepts --local-model <path.gguf>
168
+ sg studio # (or: sg serve --studio — live request lines in its trace panel)
169
+ ```
170
+
171
+ Runnable, deterministic, GPU-free demos of every use-case class live in **`examples/bootstrap/`** —
172
+ one short file per combo and per surface, each printing the guarantee it demonstrates.
173
+
174
+ > **The ready-made appliance** — if you just want the endpoint + local `.sgc` stock rooms without embedding
175
+ > the library, use **[skynet-dequantizer](https://github.com/9pings/skynet-dequantizer)**: `skynet-dequantizer serve` (OpenAI-compatible,
176
+ > no-egress by default, proven on real sockets) · `skynet-dequantizer rooms list|import|export|freeze` (your own
177
+ > shareable stock mini-repos — no catalog, no subscription, sha256 dossiers).
178
+ >
179
+ > **For AI agents reading this repo**: `CLAUDE.md` at the root is the machine-oriented map (architecture,
180
+ > commands, gotchas); the MCP surface is one command away (`claude mcp add sg -- node bin/sg mcp …`).
181
+
182
+ ## Two ways to use it — and how it works
183
+
184
+ The library is **one engine with two front doors**; they share the same core, and you can stop at the first.
185
+
186
+ ![the two uses](doc/img/two-uses.svg)
187
+
188
+ **Use 1 — the substrate**: a *versionable, git-like reasoning orchestrator*, standalone, **no LLM
189
+ required**. Model a domain in declarative concept rules (JSONC), wire deterministic providers, and let
190
+ stabilization keep the belief state coherent as data changes: `rollbackTo(rev)` (rules included),
191
+ `diffRevisions(a, b)`, `fork`/`merge` sub-worlds, and native cascading retraction — a falsified premise
192
+ un-casts itself *and its consequences*, with no rollback code. A complete, tested capability on its own.
193
+ → **[doc/usage.md](doc/usage.md)** · **[doc/architecture.md](doc/architecture.md)** · **[doc/API.md](doc/API.md)** · schema **[doc/original-2016-doc.md](doc/original-2016-doc.md)** (FR, EN pointer inside)
194
+
195
+ **Use 2 — the target system**, built on Use 1: a learned **concept-graph is a method** — a reusable
196
+ sub-graph carried by its **typed contract, not its body**, so each step sees only a bounded
197
+ neighbourhood. The supervisor forges methods, crystallizes the recurrent ones into reusable tools,
198
+ composes tools into bigger tools — and **un-learns** a method when its premise drifts (the moat no
199
+ RAG / skill-library has). Everything keys on **discrete, typed facts** — never free prose — which is
200
+ both what makes the memoization hit and the honest ceiling: only recurrent, typed, canonicalizable
201
+ structure amortizes; genuinely novel reasoning stays in the model.
202
+ → **[doc/concept-as-graph.md](doc/concept-as-graph.md)** · full model + roadmap **[doc/MODELISATION.md](doc/MODELISATION.md)**
203
+
204
+ > **Heads-up.** Active R&D. Use 1 is solid and tested; Use 2 is an advancing conception with measured
205
+ > PoCs (not a product). How best to organize concepts is still open — treat the shipped `concepts/`
206
+ > sets as illustrative, not a recommended ontology.
207
+
208
+ ## Papers
209
+
210
+ Two companion preprints (Nathanael Braun, 2026), open access on Zenodo, each in English and French —
211
+ with in-repo reproducibility packages ([`artifact/paper-dll/`](artifact/paper-dll/),
212
+ [`artifact/paper-lattice/`](artifact/paper-lattice/) — every table replays bit-for-bit without a GPU).
213
+
214
+ - **“Defeasible Library Learning: Typed Methods with Runtime Contracts that Un-learn on Drift”** —
215
+ the system paper. DOI v1 [10.5281/zenodo.21032471](https://doi.org/10.5281/zenodo.21032471) ·
216
+ v2 [10.5281/zenodo.21201723](https://doi.org/10.5281/zenodo.21201723)
217
+ - **“Sound online growth of a typed *isa* lattice from noisy LLM extraction …”** — the companion
218
+ admission-gate paper. DOI [10.5281/zenodo.21201877](https://doi.org/10.5281/zenodo.21201877)
219
+
220
+ <details>
221
+ <summary>BibTeX</summary>
222
+
223
+ ```bibtex
224
+ @misc{braun2026dll,
225
+ author = {Braun, Nathanael},
226
+ title = {Defeasible Library Learning: Typed Methods with Runtime Contracts that Un-learn on Drift},
227
+ year = {2026},
228
+ publisher = {Zenodo},
229
+ doi = {10.5281/zenodo.21201723},
230
+ url = {https://doi.org/10.5281/zenodo.21201723}
231
+ }
232
+ @misc{braun2026lattice,
233
+ author = {Braun, Nathanael},
234
+ title = {Sound online growth of a typed isa lattice from noisy LLM extraction, through candidate elimination made noise-tolerant by a localized-blame admission gate},
235
+ year = {2026},
236
+ publisher = {Zenodo},
237
+ doi = {10.5281/zenodo.21201877},
238
+ url = {https://doi.org/10.5281/zenodo.21201877}
239
+ }
240
+ ```
241
+ </details>
242
+
243
+ ## License
244
+
245
+ GNU AGPL-3.0-or-later — see [LICENSE](./LICENSE). © 2026 Nathanael Braun &lt;pp9ping@gmail.com&gt;
package/bin/sg ADDED
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env node
2
+ /*
3
+ * Copyright 2026 Nathanael Braun
4
+ * @author : Nathanael BRAUN <pp9ping@gmail.com>
5
+ *
6
+ * This program is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU Affero General Public License as published by
8
+ * the Free Software Foundation, either version 3 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ * GNU Affero General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Affero General Public License
17
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
18
+ */
19
+ 'use strict';
20
+ require('../lib/sg/cli.js');
@@ -0,0 +1,23 @@
1
+ # Concept sets — the shipped grammars
2
+
3
+ Each sub-directory is a **concept set**: a hand-authored grammar of declarative rules (JSONC) that cast
4
+ typed facts + child segments as the graph stabilizes. They are loaded with
5
+ `Graph.fromDirs({ concepts: './concepts' })` or `Graph.loadConceptMap(dir)`; `conf.conceptSets` selects
6
+ which are active. See [../doc/usage.md](../doc/usage.md) §3 (concept sets) and
7
+ [../doc/doc.md](../doc/doc.md) (the full schema reference).
8
+
9
+ > These are **examples of hand-authored grammars** — the base, standalone use of the engine (no LLM
10
+ > required). They are *illustrative*, not a recommended ontology (concept-organization strategy is WIP).
11
+ > The LLM-driven master-graph supervisor is layered *on top of* this substrate, not a prerequisite for it.
12
+
13
+ | Set | Layer | What it shows |
14
+ |---|---|---|
15
+ | **`common/`** | base / illustrative | The original travel/geo grammar. `Vertice` (nodes) + `Edge` (segments) + `Edge/Distance` (great-circle via `CommonGeo::Distance`) + `Edge/Travel/*`, `Edge/Stay/*`, `Document/*`. The canonical "hand-author a deterministic grammar for a domain" example — start here. |
16
+ | **`clinical/`** | domain grammar | **Defeasance**: `Observation → LabValue → OutOfRange` then a `Diagnosis` gated on the lab verdict → nested `Medication`; a refuted lab **retracts** the diagnosis and cascade-retracts the medication (JTMS), depositing a typed `constat` record. Shows `ensure`-driven un-casting. |
17
+ | **`supply/`** | domain grammar | **Pavage / tiling**: `Procurement` + `Inventory` + `Transport` sub-domains under a `Fulfillment` hub; `forkPlan` derives the tiles + their separator alphabet. Shows TTL defeasance (a stale ETA re-plans). |
18
+ | **`_substrate/`** | universal spine | The acyclic backbone (`Task`, `Claim`, `Frontier`) the **problem-solving grammar** builds on (decompose → rollup → claim, with a snapped frontier). Underpins the `examples/poc/problem-*.js` use 2 demos; usable on its own as a generic decomposition skeleton. |
19
+
20
+ **Authoring invariants the loader honors** (see usage §3): a child concept's key must equal its `_id`;
21
+ `_id` is globally unique; `_name` (the flag written on entities) defaults to the file basename; and the
22
+ **typed-fact discipline** — `require`/`assert`/`ensure` key only on discrete typed facts (enums/ids/numbers/
23
+ booleans), never on free-text prose. `lib/authoring/validate.js` enforces this at author time.
@@ -0,0 +1,6 @@
1
+ {
2
+ // Trust gate on the SNAPPED band. R2 audit: GATES on a discrete enum the LLM wrote; a
3
+ // low-confidence claim uncasts its dependents (defeasance via the watched ensure).
4
+ "require": ["Confidence"],
5
+ "ensure": ["$confBand == 'high'"]
6
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ // Graded confidence SNAPPED to a band (enum, not a raw float — gating on a raw float
3
+ // churns the memo every run, K1/A2). The LLM grades; the rule carries the snapped fact.
4
+ "require": ["Claim"],
5
+ "provider": ["AI::confidence"],
6
+ "prompt": {
7
+ "facts": { "confBand": { "enum": ["low", "medium", "high"] } },
8
+ "prose": "confRationale"
9
+ }
10
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ // Cast == "is fresh"; when the clock passes the TTL the ensure falls -> uncast -> the
3
+ // stale claim's dependents cascade-retract (cache-poisoning fix). Note the DOUBLE-$ on the
4
+ // global clock free-node (a single $clock would read the local scope, the #1 standing bug).
5
+ "require": ["Freshness", "producedAt"],
6
+ "ensure": ["$$clock:tick - $producedAt < $ttl"]
7
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ // Attaches a TTL to a claim (N1). R2 audit: ORIENTS (declares a freshness budget).
3
+ "require": ["Claim"],
4
+ "applyMutations": { "$_id": "_parent", "ttl": 100 }
5
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ // Refutation = defeasance. Exists only to CARRY the retraction: when the verdict flips
3
+ // to 'fail', dependents nested under the claim cascade-uncast (the Zep foil). R2-safe.
4
+ "require": ["Verification"],
5
+ "ensure": ["$claimVerdict == 'fail'"]
6
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ // Independent verdict as a SIBLING fact (never overwrites the claim). The deterministic
3
+ // checker is R2-safe (a range/schema check is verification, not domain decision).
4
+ "require": ["Claim"],
5
+ "provider": ["Verify::check"]
6
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ // An answered task asserts something verifiable. R2 audit: ORIENTS (marks "checkable").
3
+ "require": ["Task", "Answered"]
4
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ // Beam membership by budget (the global budget free-node, double-$). Eviction (budget
3
+ // falls below estCost) uncasts -> the sub-tree cascade-retracts (beam-by-retraction).
4
+ "require": ["Frontier", "estCost"],
5
+ "ensure": ["$$budget:remaining > $estCost"]
6
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ // No strategy left -> triggers the supervisor / self-mod (supervise.js). R2 audit:
3
+ // ORIENTS the supervisor; does not itself decide the repair.
4
+ "require": ["Frontier"],
5
+ "ensure": ["$strategiesExhausted"]
6
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ // An open node competing for budget. Cast while NOT yet answered. R2 audit: ORIENTS.
3
+ "require": ["Task"],
4
+ "assert": ["!$Answered"]
5
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ // Intake→Task BRIDGE (roadmap P1.a / GAP B of doc/WIP/2026-07-05-combos-design.md §11).
3
+ //
4
+ // A TYPED intake is the prose→typed front door — but on its own it is a DEAD END: the answer
5
+ // loop (Task → Complexity → Answer / Rollup) runs on a Task *Segment*, and nothing converts a
6
+ // typed Intake node into one. Without this concept the intake and the answer loop are two
7
+ // disconnected sub-graphs, so an appliance can only ever emit typed refusals, never answers.
8
+ //
9
+ // This closes the gap: on a FAITHFUL (typed) intake it seeds a root Task Segment carrying the
10
+ // question, so the loop has something to run on. Gated on the DISCRETE `IntakeStatus` (never the
11
+ // untracked prose): an untyped/partial intake does NOT cast, so a barrier miss stays a visible
12
+ // typed refusal (IntakeStatus + IntakeMissing) instead of silently seeding a task. If the typing
13
+ // premise later falls, JTMS un-casts this and its whole sub-tree (the seeded task + its answers).
14
+ //
15
+ // The seed TEMPLATE is the provider's job — AI::seedTask (lib/providers/reason-loop.js) reads the
16
+ // node's rawText and emits the origin/goal nodes + the `_task` Segment. Self-flags `ToTask`
17
+ // (provider-cast-marker gotcha). No answer logic here: this concept ORIENTS (a typed question is
18
+ // a unit of work); the decompose/answer is the AI:: loop.
19
+ "require": ["Intake"],
20
+ "ensure": ["$IntakeStatus == 'typed'"],
21
+ "provider": ["AI::seedTask"]
22
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ // The downstream-gate CONTRACT, made explicit and re-usable: anything that consumes intake
3
+ // facts MUST gate on the discrete `IntakeStatus=='typed'`, NEVER on the (untracked) prose.
4
+ // A required out-of-vocabulary miss makes the intake `untyped`, so this gate does NOT cast —
5
+ // the boundary is gated, not crossed silently; a later premise fall (re-intake flips the
6
+ // status) auto-retracts this and its dependents (JTMS). No provider: a pure assert gate that
7
+ // self-casts when the typed projection is faithful.
8
+ "require": ["Intake"],
9
+ "ensure": ["$IntakeStatus=='typed'"]
10
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ // C0 — the prose→typed FRONT DOOR (roadmap §3.2): the ONE place free text crosses into the
3
+ // typed world, and the system's declared SOUNDNESS BOUNDARY. `Intake::type` reuses the
4
+ // canonicalization barrier (lib/providers/canonicalize.js) and adds a discrete gate fact
5
+ // `IntakeStatus ∈ typed|partial|untyped`. A host wires `createIntake({ ask })`
6
+ // (lib/providers/intake.js) and supplies the CLOSED `facts` vocabulary for its domain.
7
+ //
8
+ // This shipped `facts` vocab is a domain-NEUTRAL template (classify an inbound message kind);
9
+ // a real domain specializes it via childConcepts. Fires on any object carrying inbound prose
10
+ // (`rawText`); a required key that comes back out-of-vocabulary makes the intake `untyped`
11
+ // (visible + escalated), never a silent wrong snap.
12
+ //
13
+ // The prompt MUST offer an honest out-of-enum escape ('other', deliberately NOT in the enum, so
14
+ // it lands OOV → `untyped`): a closed list with no escape pressures a compliant model to force-
15
+ // pick in-vocab — measured live (Qwen3.6-27B, 2026-07-05): without the escape an un-typeable
16
+ // "..." snaps to "statement" (silent wrong snap INVITED by the prompt); with it, "other" → typed
17
+ // refusal, while real questions still type cleanly. Same doctrine as snapToVocab's OOV-kept-raw.
18
+ "require": ["rawText"],
19
+ "provider": ["Intake::type"],
20
+ "prompt": {
21
+ "system": "Classify the inbound message kind. Reply only JSON with a 'kind' field (one of question, request, statement — or 'other' if none of them faithfully fits) and a short 'prose' restatement.",
22
+ "user": "${rawText}",
23
+ "facts": { "kind": { "enum": ["question", "request", "statement"] } },
24
+ "prose": "intakeNarrative"
25
+ },
26
+ "intake": { "required": ["kind"] }
27
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ // Leaf answer for an atomic task. The answer is TERMINAL prose (untracked); only the
3
+ // discrete `Answered` flag crosses downstream (the K1 barrier — prose never on an edge).
4
+ "require": ["Task", "Atomic"],
5
+ "provider": ["AI::answer"],
6
+ "prompt": {
7
+ "system": "Answer this atomic step directly and concisely.",
8
+ "user": "Step: ${label}",
9
+ "prose": "answer"
10
+ },
11
+ "applyMutations": { "$_id": "_parent", "Answered": true }
12
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ // Gate on the LLM's verdict; do not re-decide. R2 audit: GATES on a fact the LLM wrote.
3
+ "require": ["Complexity"],
4
+ "ensure": ["$complexityClass == 'atomic'"]
5
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ // LLM-meta: the provider SYNTHESIZES the expansion template (the AND hyper-edge of child
3
+ // sub-segments) and writes `expandedInto`. R2 audit: carries STRUCTURE, not the "how to
4
+ // split" judgment (that is the provider's).
5
+ "require": ["Compound"],
6
+ "provider": ["AI::expand"]
7
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ // The compound branch. R2 audit: GATES on the LLM enum verdict; the split itself is the
3
+ // provider's job (Expansion), not a rule.
4
+ "require": ["Complexity"],
5
+ "ensure": ["$complexityClass == 'compound'"]
6
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ // Structural classifier node. The mutually-exclusive Atomic/Compound branches nest under
3
+ // it and gate on the LLM's `complexityClass` enum fact (the engine's `type:"enum"` self-cast
4
+ // is unused — Concept.js:239 — so the discriminant is a fact, not the cast machinery).
5
+ "require": ["EvalComplexity"]
6
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ // The LLM JUDGES atomic-vs-compound; the rule only structures the verdict into a typed
3
+ // enum fact. R2 audit: the LLM decides (prompt.facts.Complexity); the rule never gates on
4
+ // domain judgment.
5
+ "require": ["Task"],
6
+ "provider": ["AI::evalComplexity"],
7
+ "prompt": {
8
+ "system": "Classify whether this step is atomic or needs decomposition.",
9
+ "user": "Step: ${label}",
10
+ "facts": { "complexityClass": { "enum": ["atomic", "compound"] } },
11
+ "prose": "complexityRationale"
12
+ }
13
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ // Orchestration: post self-id upward (race-free {__push} into the parent's answeredBy);
3
+ // calls no other concept. R2 audit: ORCHESTRATES (stigmergic), decides nothing.
4
+ "require": ["Task", "Answered", "parentSeg"],
5
+ "provider": ["AI::reportUp"]
6
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ // Bounded bottom-up synthesis. GATES on a DISCRETE cardinality equality (.length on both
3
+ // sides — never on prose), so it fires exactly once when the last child has reported. The
4
+ // fold is the LLM's job; the rule carries only the bounded-cardinality trigger.
5
+ "require": ["Task", "Expansion"],
6
+ "ensure": ["$answeredBy.length == $expandedInto.length"],
7
+ "provider": ["AI::rollup"],
8
+ "prompt": { "system": "Synthesize one bounded answer from the child answers.", "prose": "answer" },
9
+ "applyMutations": { "$_id": "_parent", "Answered": true }
10
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ // Universal layer — the answer-loop spine root. A Segment carrying a sub-problem.
3
+ // R2 audit: ORIENTS (declares a unit of work); decides nothing.
4
+ "require": "Segment"
5
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ // Nested under Diagnosis so a refuted diagnosis CASCADE-retracts it (finding #10b: a child
3
+ // concept un-casts when its parent falls — `require` alone would NOT defease). R2: ORIENTS.
4
+ "require": ["Diagnosis"],
5
+ "provider": ["Dx::prescribe"]
6
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ // THE niche edge (the Zep foil). The LLM writes the diagnosis enum (prompt.facts.diagnosis);
3
+ // the rule only GATES on the lab verdict and RETRACTS when it falls (defeasance) — it never
4
+ // decides the diagnosis itself (R2). A refuted/corrected lab => labVerdict flips => Diagnosis
5
+ // uncasts => Medication (nested child) cascade-retracts => the cleaner deposits a constat.
6
+ "require": ["Observation", "LabValue"],
7
+ "ensure": ["$labVerdict == 'pass'"],
8
+ "provider": ["Dx::diagnose"],
9
+ "cleaner": ["Constat::record"],
10
+ "constat": { "claimKey": "diagnosis", "because": "labVerdict" },
11
+ "prompt": {
12
+ "facts": { "diagnosis": { "enum": ["t2dm", "ckd", "hyperkalemia", "anemia"] } },
13
+ "prose": "diagnosisRationale"
14
+ }
15
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ // Deterministic R2-SAFE checker: the reference bounds are DATA, not judgment — it CHECKS
3
+ // whether the value is out of range, it does not DECIDE a diagnosis (R11.3).
4
+ "require": ["LabValue"],
5
+ "ensure": ["$value > $refHigh || $value < $refLow"]
6
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ // A typed lab measurement. In production an LLM::complete extracts the enum/grain facts
3
+ // (analyte, value, unit) via prompt.facts (the barrier); here they are seeded. R2: ORIENTS.
4
+ "require": ["Observation"]
5
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ // Clinical domain grammar — plugs under the universal Claim (here rooted at an encounter
3
+ // for a self-contained defeasance demo). A clinical observation on an encounter.
4
+ // R2 audit: ORIENTS (declares a verifiable observation); decides nothing.
5
+ "require": ["encounter"]
6
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "applyMutations" : {
3
+ "$_id" : "_parent",
4
+ "pathBasket" : []
5
+ }
6
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "require": "Record"// entryPoints for Segment primitive
3
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ // must wait the needed cast in originNode & targetNode
3
+ "require": [
4
+ "originNode:Position",
5
+ "targetNode:Position"
6
+ ],
7
+ // "ensure" : [
8
+ // ],
9
+ "provider": [
10
+ // if a distance object is requiered ask :
11
+ "CommonGeo::Distance"
12
+ ]
13
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "require": [
3
+ "Stay"
4
+ ],
5
+ "assert": [
6
+ "$TimePeriod.length > 1000*60*60*24 || $FuzzyTimePeriod.length > 1000*60*60*24"
7
+ ]
8
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ // "require": "Distance",
3
+ // entryPoints for the Segment primitive,
4
+ "assert": [
5
+ "!$Travel",
6
+ "$Undefined||$Distance&&$Distance.inKm==0"
7
+ ]
8
+ }