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.
- package/CONTRIBUTING.md +22 -0
- package/LICENSE +661 -0
- package/README.md +245 -0
- package/bin/sg +20 -0
- package/concepts/README.md +23 -0
- package/concepts/_substrate/Claim/Confidence/Trusted.json +6 -0
- package/concepts/_substrate/Claim/Confidence.json +10 -0
- package/concepts/_substrate/Claim/Freshness/Stale.json +7 -0
- package/concepts/_substrate/Claim/Freshness.json +5 -0
- package/concepts/_substrate/Claim/Verification/Refuted.json +6 -0
- package/concepts/_substrate/Claim/Verification.json +6 -0
- package/concepts/_substrate/Claim.json +4 -0
- package/concepts/_substrate/Frontier/InBeam.json +6 -0
- package/concepts/_substrate/Frontier/Stuck.json +6 -0
- package/concepts/_substrate/Frontier.json +5 -0
- package/concepts/_substrate/Intake/ToTask.json +22 -0
- package/concepts/_substrate/Intake/Typed.json +10 -0
- package/concepts/_substrate/Intake.json +27 -0
- package/concepts/_substrate/Task/Answer.json +12 -0
- package/concepts/_substrate/Task/Complexity/Atomic.json +5 -0
- package/concepts/_substrate/Task/Complexity/Compound/Expansion.json +7 -0
- package/concepts/_substrate/Task/Complexity/Compound.json +6 -0
- package/concepts/_substrate/Task/Complexity.json +6 -0
- package/concepts/_substrate/Task/EvalComplexity.json +13 -0
- package/concepts/_substrate/Task/ReportUp.json +6 -0
- package/concepts/_substrate/Task/Rollup.json +10 -0
- package/concepts/_substrate/Task.json +5 -0
- package/concepts/clinical/Diagnosis/Medication.json +6 -0
- package/concepts/clinical/Diagnosis.json +15 -0
- package/concepts/clinical/Observation/LabValue/OutOfRange.json +6 -0
- package/concepts/clinical/Observation/LabValue.json +5 -0
- package/concepts/clinical/Observation.json +6 -0
- package/concepts/common/Document/pathBasket.json +6 -0
- package/concepts/common/Document.json +3 -0
- package/concepts/common/Edge/Distance.json +13 -0
- package/concepts/common/Edge/Stay/LongStay.json +8 -0
- package/concepts/common/Edge/Stay.json +8 -0
- package/concepts/common/Edge/Travel/LongTravel.json +16 -0
- package/concepts/common/Edge/Travel/ShortTravel.json +11 -0
- package/concepts/common/Edge/Travel/targetNode.json +7 -0
- package/concepts/common/Edge/Travel.json +7 -0
- package/concepts/common/Edge.json +3 -0
- package/concepts/common/Vertice.json +3 -0
- package/concepts/supply/Fulfillment.json +10 -0
- package/concepts/supply/Inventory/Reorder.json +7 -0
- package/concepts/supply/Inventory.json +5 -0
- package/concepts/supply/Procurement/SupplierConfirm.json +6 -0
- package/concepts/supply/Procurement.json +8 -0
- package/concepts/supply/Transport.json +5 -0
- package/doc/API.md +556 -0
- package/doc/CAPABILITIES.md +373 -0
- package/doc/MODELISATION.md +511 -0
- package/doc/architecture.md +267 -0
- package/doc/concept-as-graph.md +379 -0
- package/doc/concept-learning.md +168 -0
- package/doc/creative-loop-map.md +202 -0
- package/doc/original-2016-doc.md +148 -0
- package/doc/usage.md +501 -0
- package/lib/authoring/abstract.js +401 -0
- package/lib/authoring/abstraction.js +190 -0
- package/lib/authoring/adapt.js +393 -0
- package/lib/authoring/ancestry.js +216 -0
- package/lib/authoring/author.js +147 -0
- package/lib/authoring/bounded-merge.js +57 -0
- package/lib/authoring/canon.js +158 -0
- package/lib/authoring/clock.js +123 -0
- package/lib/authoring/combinator.js +92 -0
- package/lib/authoring/compete.js +76 -0
- package/lib/authoring/compose-hotspot.js +314 -0
- package/lib/authoring/compress.js +279 -0
- package/lib/authoring/concept-net.js +254 -0
- package/lib/authoring/concepts.js +66 -0
- package/lib/authoring/context-project.js +277 -0
- package/lib/authoring/contract.js +476 -0
- package/lib/authoring/corpus-pack.js +125 -0
- package/lib/authoring/cost-probe.js +86 -0
- package/lib/authoring/crystallize.js +555 -0
- package/lib/authoring/dag-decompose.js +256 -0
- package/lib/authoring/dataset-adapter.js +253 -0
- package/lib/authoring/debug-provider.js +92 -0
- package/lib/authoring/decompose.js +343 -0
- package/lib/authoring/emittability.js +236 -0
- package/lib/authoring/equilibrium.js +160 -0
- package/lib/authoring/extract.js +153 -0
- package/lib/authoring/forest.js +55 -0
- package/lib/authoring/forge-fallback.js +116 -0
- package/lib/authoring/givens.js +121 -0
- package/lib/authoring/glossary.js +177 -0
- package/lib/authoring/grammar-graph.js +191 -0
- package/lib/authoring/granularity.js +80 -0
- package/lib/authoring/graph-net.js +108 -0
- package/lib/authoring/ground.js +148 -0
- package/lib/authoring/higher-order.js +85 -0
- package/lib/authoring/hotspot.js +132 -0
- package/lib/authoring/hysteresis.js +85 -0
- package/lib/authoring/index.js +106 -0
- package/lib/authoring/lattice-morphism.js +61 -0
- package/lib/authoring/lattice-pack.js +148 -0
- package/lib/authoring/leaf-io.js +77 -0
- package/lib/authoring/library.js +156 -0
- package/lib/authoring/lifecycle.js +92 -0
- package/lib/authoring/loop.js +193 -0
- package/lib/authoring/master-loop.js +132 -0
- package/lib/authoring/mdl.js +209 -0
- package/lib/authoring/memo-stability.js +122 -0
- package/lib/authoring/method-explorer.js +138 -0
- package/lib/authoring/method-pack.js +181 -0
- package/lib/authoring/method.js +202 -0
- package/lib/authoring/mine.js +510 -0
- package/lib/authoring/mount.js +119 -0
- package/lib/authoring/negotiate.js +100 -0
- package/lib/authoring/parametric.js +139 -0
- package/lib/authoring/reaggregate.js +75 -0
- package/lib/authoring/rebalance.js +157 -0
- package/lib/authoring/recall.js +135 -0
- package/lib/authoring/registry.js +350 -0
- package/lib/authoring/relearn.js +147 -0
- package/lib/authoring/retention.js +89 -0
- package/lib/authoring/segment-proxy.js +114 -0
- package/lib/authoring/serve-leaf.js +64 -0
- package/lib/authoring/slot-aware-serve.js +77 -0
- package/lib/authoring/sound-invoke.js +59 -0
- package/lib/authoring/split-serve.js +74 -0
- package/lib/authoring/ste.js +239 -0
- package/lib/authoring/stock.js +101 -0
- package/lib/authoring/store.js +94 -0
- package/lib/authoring/supervise.js +138 -0
- package/lib/authoring/support.js +131 -0
- package/lib/authoring/task-mirror.js +51 -0
- package/lib/authoring/typed-loop.js +160 -0
- package/lib/authoring/validate.js +569 -0
- package/lib/authoring/widen.js +88 -0
- package/lib/combos/appliance.js +189 -0
- package/lib/combos/critique.js +377 -0
- package/lib/combos/defaults.js +86 -0
- package/lib/combos/durable-runner.js +115 -0
- package/lib/combos/forge.js +209 -0
- package/lib/combos/index.js +86 -0
- package/lib/combos/learning-library.js +253 -0
- package/lib/combos/mixture-serve.js +193 -0
- package/lib/combos/plan-loop.js +192 -0
- package/lib/combos/proxy-cache.js +272 -0
- package/lib/combos/self-mod.js +94 -0
- package/lib/durable/audit.js +102 -0
- package/lib/durable/checkpoint-store.js +550 -0
- package/lib/durable/fold.js +62 -0
- package/lib/durable/interpreter.js +242 -0
- package/lib/durable/xlate.js +185 -0
- package/lib/graph/Graph.js +2486 -0
- package/lib/graph/expr.js +307 -0
- package/lib/graph/index.js +26 -0
- package/lib/graph/log.js +134 -0
- package/lib/graph/objects/Concept.js +382 -0
- package/lib/graph/objects/Entity.js +503 -0
- package/lib/graph/objects/Node.js +57 -0
- package/lib/graph/objects/PathMap.js +557 -0
- package/lib/graph/objects/Segment.js +100 -0
- package/lib/graph/tasks/stabilize.js +59 -0
- package/lib/graph/tasks/taskflow.js +247 -0
- package/lib/index.js +122 -0
- package/lib/load.js +132 -0
- package/lib/providers/backends.js +117 -0
- package/lib/providers/borderline.js +129 -0
- package/lib/providers/cache.js +226 -0
- package/lib/providers/canonicalize.js +198 -0
- package/lib/providers/constat.js +107 -0
- package/lib/providers/geo.js +53 -0
- package/lib/providers/index.js +116 -0
- package/lib/providers/intake.js +263 -0
- package/lib/providers/llm-local.js +88 -0
- package/lib/providers/llm.js +236 -0
- package/lib/providers/local-host.js +197 -0
- package/lib/providers/merge-consistency.js +162 -0
- package/lib/providers/nogood.js +149 -0
- package/lib/providers/reason-loop.js +223 -0
- package/lib/providers/semiring.js +285 -0
- package/lib/providers/solver-fork.js +163 -0
- package/lib/providers/stats.js +228 -0
- package/lib/providers/verify.js +120 -0
- package/lib/runtime/index.js +135 -0
- package/lib/runtime/invoke-pool.js +92 -0
- package/lib/runtime/protocol.js +210 -0
- package/lib/runtime/transport-socket.js +77 -0
- package/lib/runtime/worker-entry.js +31 -0
- package/lib/sg/cli.js +601 -0
- package/lib/sg/log-sinks.js +214 -0
- package/lib/sg/mcp.js +395 -0
- package/lib/sg/proxy-run.js +66 -0
- package/lib/sg/serve-demo.js +185 -0
- package/lib/sg/serve.js +205 -0
- package/lib/sg/trace.js +118 -0
- package/lib/studio/protocol.js +45 -0
- package/lib/studio/public/app.js +310 -0
- package/lib/studio/public/components/ConceptEditor.js +43 -0
- package/lib/studio/public/components/ConceptTree.js +43 -0
- package/lib/studio/public/components/CorpusPanel.js +68 -0
- package/lib/studio/public/components/ForkTree.js +36 -0
- package/lib/studio/public/components/GrammarGraph.js +99 -0
- package/lib/studio/public/components/GraphCanvas.js +156 -0
- package/lib/studio/public/components/Inspector.js +48 -0
- package/lib/studio/public/components/LearningPanel.js +85 -0
- package/lib/studio/public/components/PromptConsole.js +46 -0
- package/lib/studio/public/components/ProviderTrace.js +39 -0
- package/lib/studio/public/components/SessionSplit.js +47 -0
- package/lib/studio/public/components/TilingOverlay.js +40 -0
- package/lib/studio/public/components/Timeline.js +57 -0
- package/lib/studio/public/index.html +26 -0
- package/lib/studio/public/styles.css +185 -0
- package/lib/studio/public/ws.js +58 -0
- package/lib/studio/server.js +130 -0
- package/lib/studio/session.js +397 -0
- package/lib/studio/studio.js +149 -0
- 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
|
+

|
|
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 <pp9ping@gmail.com>
|
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,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,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,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
|
+
// 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,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,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
|
+
// 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
|
+
}
|