mindsmith 0.1.0 → 0.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 (3) hide show
  1. package/README.md +174 -107
  2. package/bin/mindsmith +71 -4
  3. package/package.json +8 -2
package/README.md CHANGED
@@ -1,153 +1,220 @@
1
- # Mindsmith
2
-
3
- > **Pre-launch — nothing is field-adopted yet (rung 6/6 is empty on every bar below).**
4
- > We publish maturity per feature and keep refuted claims on the page. Honesty is the product's USP,
5
- > so it is also the documentation's. See [docs/honesty.html](docs/honesty.html).
6
-
7
- **Mindsmith is an external reasoning layer for your local LLM — an auditable critical mind, gated
8
- think-mode lanes, and verified-stock answers at zero frontier calls, from a mixture of certified
9
- graph-experts fronting your model. OpenAI-compatible endpoint + MCP tools over shareable `.sgc` rooms;
10
- nothing leaves your machine by default.**
11
-
12
- A small quantized gguf fits your VRAM, but quantization costs it judgment and on its own it has no
13
- external check on its reasoning. Mindsmith, a thin surface over the
14
- [skynet-graph](https://github.com/9pings/skynet-graph) engine, hands the model tools it doesn't have
15
- alone: answers steered against a certified **method vocabulary** (covered queries served from verified
16
- local stock at 0 frontier calls); gated **assistant lanes** (`propose` / `hint` an external think-mode
17
- that returns a tested verdict or refuses, never a guess); and an external **critical mind** (`critique` —
18
- weigh a question over a witness-gated pool of arguments, with an honest, certification-aware verdict).
19
- The judgment repair is measured on the same model at two quant levels (protocols in the engine repo):
20
- SQL covered queries low-quant **8→63 %** (high-quant reference 46→92 %, N=201) · finance-table traffic
21
- **7→62 %** (20→78 %, N=120) — zero big-model calls at runtime on the covered slice.
22
-
23
- No accounts, no catalog, no phone-home. Stocks live in a local **room** you own: build them with the
24
- engine's forge (0 false admissions across 3 datasets × 2 forge models; sha256 validation dossier per
25
- stock), freeze them, share them as files, import someone else's a malformed bundle is refused at the
26
- gate, never written.
1
+ # mindsmith
2
+
3
+ [![npm](https://img.shields.io/npm/v/mindsmith?logo=npm&color=cb3837)](https://www.npmjs.com/package/mindsmith)
4
+ [![npm downloads](https://img.shields.io/npm/dm/mindsmith?color=cb3837)](https://www.npmjs.com/package/mindsmith)
5
+ [![node](https://img.shields.io/node/v/mindsmith)](https://nodejs.org)
6
+ [![license](https://img.shields.io/npm/l/mindsmith?color=blue)](./LICENSE)
7
+
8
+ **Your small model fits your VRAM. Quantization stole its judgment on the way down.
9
+ mindsmith forges it back.** A certified method vocabulary steers it, an external critical
10
+ mind checks it, and covered questions are answered from *your* verified stock at **zero
11
+ frontier calls** — all on your box, nothing leaving by default. Point any OpenAI client at
12
+ it and go. The `-smith` is literal: you forge a mind for the model you can actually run.
13
+
14
+ > **Pre-launch. Nothing here is field-adopted yet rung 6/6 is empty on every bar below.**
15
+ > We publish maturity per feature, and **a refuted claim comes off the page the day it falls**
16
+ > (several are still listed on purpose knowing where the floor is *is* the product). The
17
+ > radical-honesty page: [honesty](https://9pings.github.io/mindsmith/honesty.html).
18
+
19
+ Built on the [skynet-graph](https://github.com/9pings/skynet-graph) reasoning engine the
20
+ substrate + the combos this appliance puts to work.
21
+
22
+ ## What it does
23
+
24
+ - **Forge repair the low-quant.** A menu of *certified* method shapes steers the model's
25
+ output; a covered query is served from your verified local stock at **0 frontier calls**
26
+ and can't hallucinate by construction. Measured on the *same* model at two quant levels:
27
+ SQL covered queries **8→63 %** (N=201; high-quant reference 46→92 %) · finance-table
28
+ traffic **7→62 %** (N=120; 20→78 %).
29
+ - **Check — an external mind, not a self-pep-talk.** `critique` weighs a question over a
30
+ witness-gated pool and returns an honest, certification-aware verdict (or an honest
31
+ UNDECIDED). `propose` / `hint` are gated think-mode lanes that hand back a *tested* verdict
32
+ or a typed refusal — never a confident guess. All as MCP tools.
33
+ - **Own it — sealed by default.** OpenAI-compatible endpoint, no accounts, no catalog, no
34
+ phone-home, **no-egress by default (enforced fail-closed on real sockets, with a negative
35
+ control that proves the guard has teeth)**. Your stock lives in a local **room** you own:
36
+ freeze it, checksum it, hand it to a colleague, import theirs — a malformed bundle is
37
+ refused at the gate, never written.
27
38
 
28
39
  ## 60-second quickstart
29
40
 
30
41
  ```bash
31
- # Pre-launch note: not on npm yet. Until the release:
32
- # git clone <this repo> && cd mindsmith && npm install && npm test # 26/26, GPU-free
33
- # Once published, the same commands work via: npm i -g mindsmith or npx mindsmith
34
-
35
- # 1 serve (embedded gguf as the escalation):
42
+ # Install (on npm):
43
+ npm i -g mindsmith # per-project: npm i mindsmith · one-shot: npx mindsmith
44
+ # Running a local .gguf (embedded or single-model) needs the local runtime once prebuilt, no compile:
45
+ npm install node-llama-cpp
46
+ # On WSL, export this or the gguf silently falls back to CPU:
47
+ export LD_LIBRARY_PATH=/usr/lib/wsl/lib:/usr/lib/x86_64-linux-gnu
48
+
49
+ # 1 — serve. Escalation is ONE of: an embedded gguf, an OpenAI endpoint, or an N-tier routing config.
36
50
  FRONTIER_MODEL=/path/model.gguf mindsmith serve --room ./sgc
37
- # → mindsmith → http://127.0.0.1:4747/v1 (OpenAI-compatible)
51
+ # → mindsmith → http://127.0.0.1:4747/v1 (OpenAI-compatible, binds 127.0.0.1)
52
+ # (no local runtime? point at an endpoint instead: LLM_BASE=<url> mindsmith serve)
38
53
 
39
54
  # 2 — point ANY OpenAI client at it (official SDKs, LangChain, Open WebUI, curl):
40
- # baseURL = http://127.0.0.1:4747/v1 apiKey = anything
55
+ # baseURL = http://127.0.0.1:4747/v1 apiKey = anything
41
56
  curl -si http://127.0.0.1:4747/v1/chat/completions \
42
57
  -H 'content-type: application/json' \
43
58
  -d '{"messages":[{"role":"user","content":"your question"}]}'
44
- # every completion carries provenance headers:
59
+ # every completion carries provenance headers, so you always know what you got:
45
60
  # x-sg-served-from: local|frontier · x-sg-arm · x-sg-cost · x-sg-coverage · x-sg-saved · x-sg-sgc-version
46
61
 
47
- # 3 — your stock rooms (local .sgc mini-repos, gate-checked):
62
+ # 3 — your stock rooms (local .sgc mini-repos, gate-checked on every load):
48
63
  mindsmith rooms list # inventory: name@version, classes, sha256, ❄ frozen
49
- mindsmith rooms import ./fin-tables-stock.sgc # gate-checked (a bad bundle never lands)
64
+ mindsmith rooms import ./fin-tables-stock.sgc # a bad bundle never lands
50
65
  mindsmith rooms freeze fin-tables-stock # writes the auditable sha256 dossier
51
66
  mindsmith rooms export fin-tables-stock ./out # bundle + dossier, ready to share
52
67
 
53
- # 4 — or as MCP tools for an agent host (Claude Code, any MCP client):
68
+ # 4 — or wire it into an agent host as MCP tools (Claude Code, any MCP client):
54
69
  claude mcp add mindsmith -- mindsmith mcp --routing routing.json
55
- # tools: ask · drift · metrics · lattice_load · hint · propose · critique
70
+ # tools: ask · drift · metrics · lattice_load · critique (+ hint · propose once a methods stock is loaded)
56
71
  ```
57
72
 
58
- `GET /healthz` is the ops readout (no key, no query content): policy, configured vs reachable tiers,
59
- loaded `.sgc` versions, stock size.
73
+ The demo and the test suite live in the [repo](https://github.com/9pings/mindsmith), not the
74
+ npm tarball — `git clone` for those; npm is for *running* the appliance and *embedding* the
75
+ engine. `GET /healthz` is the ops readout (no key, no query content): policy, configured vs
76
+ reachable tiers, loaded `.sgc` versions, stock size.
60
77
 
61
- ## Features × maturity
78
+ ## One model. One load. The whole appliance.
79
+
80
+ Most VRAM-constrained boxes have room for exactly **one** model. Fine — that's all mindsmith
81
+ needs:
62
82
 
63
- Maturity uses a fixed 6-rung scale — 1 coherent idea · 2 design with pre-registered kill-gates ·
64
- 3 mechanics proven · 4 measured at scale · 5 product-integrated · 6 field-adopted. Nothing is at 6:
65
- this is pre-launch. Scale details: [docs/honesty.html](docs/honesty.html).
83
+ ```bash
84
+ mindsmith serve --model /path/model.gguf # ONE gguf, ONE VRAM load
85
+ ```
86
+
87
+ That single load is doing **both** jobs at once. Your users get a full local LLM server whose
88
+ answers run **with** native reasoning (think). The graph's structured work — coverage,
89
+ `critique`, `propose` — runs on the **same** weights **without** think. How? The thinking
90
+ budget is **per-call, not per-load**: one set of weights in VRAM, two behaviours out of it. A
91
+ box that can hold a single model still gets the entire appliance — server *and* value-add — for
92
+ one model's worth of memory.
93
+
94
+ Tune the load: `--ctx <N>` · `--gpu auto|cuda|metal|vulkan|false` · `--gpu-layers <N>` ·
95
+ `--think <tokens>` (the answer-side reasoning budget, default 1024). Need a custom llama.cpp
96
+ build? `--no-prebuilt` builds from source, `--llama-build auto|forceRebuild|never` controls it,
97
+ and `LLAMA_CMAKE=<json>` passes cmake options through.
98
+
99
+ ## Features × maturity
66
100
 
67
- | Feature | Maturity | Measured | Docs |
68
- |---|---|---|---|
69
- | **F1 — Low-quant repair** (certified stock steers the model; covered 0 frontier calls) | `█████░` 5/6 product-integrated | SQL 8→63 % (N=201) · finance tables 7→62 % (N=120) · forge 0 false admissions | [docs](docs/features.html#f1) |
70
- | **F4 — External think mode** (`propose` → gated verdict + blame + tested options; `hint` menu) | `█████░` 5/6 product-integrated | one dialogue round 17/24 → 24/24 at zero false admissions | [docs](docs/features.html#f4) |
71
- | **F5 — External critical mind** (`critique`: witness gate, anchored generation, honest verdict) | `█████░` 5/6 surface · campaign numbers at 4/6 | coverage 77 % vs 58 % (48 args) · certified perimeter 12/24 → 24/24 · 0 fabrication in negative controls | [docs](docs/features.html#f5) |
72
- | **F6 — Local `.sgc` rooms** (list/import/export/freeze, sha256 dossiers, engine-gated loads) | `█████░` 5/6 product-integrated | gate-checked import; loads never bypass the engine gates | [docs](docs/features.html#f6) |
73
- | **F2 — Piece-by-piece zoom** (typed DAG on big tasks) | `████░░` 4/6 measured — **library-only today, not surfaced here (the known gap)** | math word problems ×3.25 [2.4–4.8] · financial-table QA ×2.54 [1.96–3.5], 560 tasks | [docs](docs/features.html#f2-gap) |
101
+ Maturity uses a fixed 6-rung scale: **1** coherent idea · **2** design with pre-registered
102
+ kill-gates · **3** mechanics proven · **4** measured at scale · **5** product-integrated ·
103
+ **6** field-adopted (external replications). **Nothing is at 6 this is pre-launch.** Scale
104
+ detail: [honesty](https://9pings.github.io/mindsmith/honesty.html).
105
+
106
+ | Feature | Maturity | Measured |
107
+ |---|---|---|
108
+ | **F1 — Low-quant repair** — certified stock steers the model; covered → 0 frontier calls | `█████░` 5/6 product-integrated | SQL **8→63 %** (N=201) · finance tables **7→62 %** (N=120) · forge **0 false admissions** (3 datasets × 2 forge models) |
109
+ | **F4 — External think mode** — `propose` → gated verdict + blame + gate-tested options; `hint` menu | `█████░` 5/6 product-integrated | one dialogue round **17/24 → 24/24** at **zero false admissions**; a forced write lands UNTRUSTED, never admitted |
110
+ | **F5 — External critical mind** — `critique`: witness gate, anchored generation, honest verdict | `█████░` 5/6 surface (campaign numbers at 4/6) | coverage **77 % vs 58 %** (48 args) · certified perimeter **12/24 → 24/24** · **0 fabrication** in negative controls (8/8 injected theses retracted) |
111
+ | **F6 — Local `.sgc` rooms** — list/import/export/freeze, sha256 dossiers, engine-gated loads | `█████░` 5/6 product-integrated | gate-checked import; loads never bypass the engine gates |
112
+ | **F2 — Piece-by-piece zoom** — typed DAG on big tasks | `████░░` 4/6 measured — **library-only in the engine today; NOT surfaced here (the known gap)** | math word problems **×3.25** [2.4–4.8] · financial-table QA **×2.54** [1.96–3.5], 560 tasks |
113
+
114
+ ## The illusion this kills
115
+
116
+ Ask a low-quant model to weigh two sides of a real question and it picks a winner with total
117
+ confidence — and is right about as often as a coin. In a head-to-head (24 composed perimeters,
118
+ gold hidden, every arm re-run bit-identical), the naive single call and the *same model with a
119
+ 1024-token native think budget* both score **13/24 ≈ chance**, each throwing 11 confident wrong
120
+ verdicts and refusing zero times. And it doesn't know: measured self-believed coverage runs
121
+ **~106 %** against a real gold of **64–77 %** — it's sure it covered everything when it didn't.
122
+
123
+ The external critical mind renders **0 wrong verdicts across all 48 debates**. Two things buy
124
+ that. First, it decides mechanically **only at a measured margin** — and below it returns counts
125
+ + coverage + an honest **UNDECIDED** instead of flipping a coin. Second, a **certified
126
+ perimeter closes the illusion**: declaring what you're judging against takes the decision from
127
+ **12/24 to 24/24**. mindsmith declines; it doesn't guess. That's the whole point.
74
128
 
75
129
  ## Why not just…?
76
130
 
77
- - **…run a bigger model?** If it fits your VRAM, do. This exists for the model you *can* run:
78
- certified-stock steering recovers most of what quantization broke (SQL 8→63 %, finance 7→62 %),
79
- at 0 frontier calls on the covered slice.
80
- - **…use the model's think mode / a self-critique prompt?** The 2024-25 literature (and our own
81
- 3-form refutation) agree: self-critique underperforms *external* feedback with localized blame.
82
- The `propose` gate and `critique` tool are that external feedback — structural, auditable, and
83
- un-arguable-with (a forced write lands UNTRUSTED, never admitted).
84
- - **…RAG / a prompt library?** Retrieval trusts whatever is indexed. A room only admits what
85
- passes the gate (0 false admissions measured at the forge), and every completion tells you
86
- which slice you can trust (`x-sg-served-from`, `x-sg-coverage`).
87
- - **…an agent framework's memory?** None we checked reopens a task whose premise drifted; the
88
- engine's typed task state retracts and reopens with the reason, at 0 model calls (surfaced here
89
- via MCP `state_recall` / `plan_sync` on the engine side).
131
+ - **…run a bigger model?** If it fits your VRAM, do. mindsmith is for the model you *can*
132
+ run: certified-stock steering recovers most of what quantization broke (SQL 8→63 %, finance
133
+ 7→62 %), at 0 frontier calls on the covered slice.
134
+ - **…use the model's think mode, or a self-critique prompt?** The 202425 literature and our
135
+ own 3-form refutation agree: self-critique underperforms *external* feedback with localized
136
+ blame. A low-quant can't audit itself. The `propose` gate and `critique` tool are that
137
+ external feedback — structural, auditable, and un-arguable-with (a forced write lands
138
+ UNTRUSTED, never admitted). A prompt can always be talked out of it; a gate can't.
139
+ - **…RAG or a prompt library?** Retrieval trusts whatever got indexed. A room only admits
140
+ what passes the gate (**0 false admissions** measured at the forge), and every completion
141
+ tells you which slice you can trust (`x-sg-served-from`, `x-sg-coverage`).
142
+ - **…an agent framework's memory?** None we checked reopens a task whose premise drifted. The
143
+ engine's typed task state retracts and reopens *with the reason*, at 0 model calls (surfaced
144
+ on the engine side via MCP `state_recall` / `plan_sync`).
90
145
 
91
146
  ## What actually runs
92
147
 
93
- - **`serve`** — `POST /v1/chat/completions`, `GET /v1/models`, `GET /healthz`. Default port 4747,
94
- binds 127.0.0.1 on purpose. A covered query is served from verified local stock at 0 frontier calls;
95
- a miss escalates (you always get an answer); the local side never fabricates — 0 hallucination by
96
- construction on the covered slice.
97
- - **Escalation** — either a single frontier (`FRONTIER_MODEL=<path.gguf>` embedded, or `LLM_BASE=<url>`
98
- any OpenAI-compatible endpoint), or **N-tier routing** (`--routing config.json`): ordered tiers, each
99
- tagged with an egress class (`none` / `mid` / `frontier`), governed by a policy ceiling
100
- `no-egress` (default for routing configs) · `allow-mid` · `allow-all`. A query is **never** silently
101
- sent to a forbidden tier: if the policy leaves nothing reachable, you get a typed `NO_REACHABLE_TIER`
102
- refusal. The no-egress guarantee is enforced fail-closed on real sockets in the test suite, with a
103
- negative control proving the guard has teeth.
148
+ - **`serve`** — `POST /v1/chat/completions`, `GET /v1/models`, `GET /healthz`. Default port
149
+ 4747, binds 127.0.0.1 on purpose. Covered query served from verified local stock at 0
150
+ frontier calls; a miss escalates (you always get an answer); the local side never fabricates.
151
+ - **Escalation — pick one.** A **single model** (`--model <path.gguf>`, the shared-load mode
152
+ above) · a **single frontier** (`FRONTIER_MODEL=<path.gguf>` embedded, or `LLM_BASE=<url>`
153
+ any OpenAI-compatible endpoint) · or **N-tier routing** (`--routing config.json`): ordered
154
+ tiers, each tagged with an egress class (`none` / `mid` / `frontier`), under a policy ceiling
155
+ `no-egress` (default for routing configs) · `allow-mid` · `allow-all`. A query is **never**
156
+ silently sent to a forbidden tier: if the policy leaves nothing reachable you get a typed
157
+ `NO_REACHABLE_TIER` refusal. The no-egress guarantee is enforced fail-closed on real sockets
158
+ in the test suite, with a negative control proving the guard bites.
104
159
  - **`mcp`** — the same verified stock + escalation over stdio (no HTTP socket). Tools:
105
160
  `ask` (local-first, `{answer, source, cached, cost}`) · `drift` (invalidate a stale entry) ·
106
- `metrics` (economy readout) · `lattice_load` (learn THROUGH the gate — the only registry write path) ·
107
- `hint` (SOFT lane: advisory certified-shape menu, no guarantee attached) · `propose` (HARD lane: the
108
- gate never yields; `force=true` records untrusted provenance, never admits) · `critique` (below).
109
- - **`rooms`** `list | import <file> | export <name> <dest> | freeze <name>`. Import dry-loads the
110
- bundle through the same gates the appliance uses; freeze writes the sha256 dossier that makes the
111
- bundle a fixed, auditable reference.
161
+ `metrics` (economy readout) · `lattice_load` (learn *through* the gate — the only registry
162
+ write path) · `hint` (SOFT lane: advisory certified-shape menu, no guarantee attached) ·
163
+ `propose` (HARD lane: the gate never yields; `force=true` records untrusted provenance,
164
+ never admits) · `critique` (below).
165
+ - **`rooms`** `list | import <file> | export <name> <dest> | freeze <name>`. Import
166
+ dry-loads the bundle through the same gates the appliance uses; freeze writes the sha256
167
+ dossier that makes the bundle a fixed, auditable reference.
112
168
 
113
169
  ## The `critique` iteration contract
114
170
 
115
- `critique` runs the external critical mind on a question: declared viewpoints established through a
116
- witness gate over a statement pool, anchored generation of missing theses, a typed ledger, and a
117
- certification-aware verdict. The contract: **OPEN ledger points and an UNDECIDED verdict are a typed
118
- data request, not a dead end.** The tool cannot reach the web the host (you, or your agent) gathers
119
- real statements that bear on the OPEN points, then calls `critique` again with `statements: [...]`
120
- (`"PRO: ..."` / `"CON: ..."` lines). The frame upgrades to MATERIAL and the margin can move honestly.
121
- A verdict is mechanical only at the measured margin bound (≥3 on free/declared frames, ≥2 on a
122
- certified perimeter); below it the deliverable is counts + coverage + an honest UNDECIDED — never a
123
- fake weighing.
171
+ `critique` runs the external critical mind on a question: viewpoints established through a
172
+ **witness gate** over a statement pool, anchored generation of missing theses (drafted **only**
173
+ from pool witnesses 0 fabrication across negative controls), a typed ledger, and a
174
+ certification-aware verdict. The contract: **OPEN ledger points and an UNDECIDED verdict are a
175
+ typed data request, not a dead end.** The tool can't reach the web the host (you, or your
176
+ agent) gathers real statements that bear on the OPEN points and calls `critique` again with
177
+ `statements: [...]` (`"PRO: …"` / `"CON: …"` lines). The frame upgrades to MATERIAL and the
178
+ margin can move honestly. Below the measured decidability bound the deliverable is counts +
179
+ coverage + an honest UNDECIDED — never a fake weighing.
124
180
 
125
181
  ## Honest limits (what is NOT claimed)
126
182
 
127
- - **The guarantee is at stock admission, not at execution.** Runtime steering orients; a suggestion is
128
- not a correctness proof. A runtime "trusted answers" cross-agreement tier was tested and **refuted**
129
- — it was removed, and stays listed in [docs/honesty.html](docs/honesty.html).
130
- - **The win lives on the typed, recurrent slice of your traffic.** Coverage depends on your stocks;
131
- forge yield is per-domain; amortization is a property of the domain's stereotypy.
132
- - **F2 zoom is not surfaced here.** The piece-by-piece decomposition is measured (rung 4/6) but
133
- library-only in skynet-graph today; no MCP tool exposes it yet.
134
- - **`critique` bounds**: below the measured decidability margin the verdict is UNDECIDED by design;
135
- entry templates are not yet form-robustness-tested; on FREE frames coverage is relative to the pool
136
- (the payload says so).
183
+ This is the part every hype-y AI repo leaves out. We tested these, here's exactly what broke,
184
+ and it stays on the page.
185
+
186
+ - **The guarantee is at stock admission, not at execution.** Runtime steering *orients*; a
187
+ suggestion is not a correctness proof. A runtime "trusted answers" cross-agreement tier was
188
+ tested and **refuted** removed, and still listed in
189
+ [honesty](https://9pings.github.io/mindsmith/honesty.html).
190
+ - **The win lives on the typed, recurrent slice of your traffic.** Coverage depends on your
191
+ stocks; forge yield is per-domain; amortization is a property of the domain's stereotypy.
192
+ Free prose and genuinely novel reasoning stay in the model, without guarantee — by design.
193
+ - **F2 zoom is not surfaced here.** The piece-by-piece decomposition is measured (rung 4/6)
194
+ but library-only in skynet-graph today; no MCP tool exposes it yet.
195
+ - **Verdicts are reliable only on certified perimeters or wide margins.** Below the measured
196
+ decidability bound, `critique` returns UNDECIDED by design. Its entry templates
197
+ (pool brainstorm, viewpoint naming) are not yet form-robustness-tested; on FREE frames
198
+ coverage is relative to the pool (the payload says so).
137
199
  - Streaming is simulated; no per-tier timeout yet.
138
- - **Nothing is field-adopted (rung 6/6)** no external replications yet. This is pre-launch.
200
+ - **Nothing is field-adopted (rung 6/6).** No external replications. This is pre-launch — and
201
+ that's exactly the rung you can help fill.
139
202
 
140
203
  ## Env / flags
141
204
 
142
- `FRONTIER_MODEL` (gguf, embedded) or `LLM_BASE` (any OpenAI-compatible endpoint) — the single-frontier
143
- escalation · `--routing <config.json>` / `$SG_ROUTING` (N-tier) + `--policy` / `$SG_POLICY`
144
- (`no-egress|allow-mid|allow-all`) · `LOCAL_MODEL` (gguf semantic coverage: paraphrases hit the stock,
145
- opt-in) · `--room <dir>` (default `./sgc`) · `--store <f.json>` (durable cross-restart stock,
146
- default `.skynet-stock.json`) · `--port` (default 4747, binds 127.0.0.1).
205
+ **Single-model:** `--model <path.gguf>` (or `MODEL`) · `--ctx` (`CONTEXT_SIZE`) ·
206
+ `--gpu auto|cuda|metal|vulkan|false` · `--gpu-layers` (`GPU_LAYERS`) · `--think <tokens>`
207
+ (`THINK_BUDGET`, default 1024) · custom build `--no-prebuilt` / `--llama-build` / `LLAMA_CMAKE`.
208
+ **Escalation (single frontier):** `FRONTIER_MODEL` (gguf, embedded) or `LLM_BASE` (any
209
+ OpenAI-compatible endpoint). **N-tier:** `--routing <config.json>` / `$SG_ROUTING` +
210
+ `--policy` / `$SG_POLICY` (`no-egress|allow-mid|allow-all`). **Coverage:** `LOCAL_MODEL`
211
+ (separate gguf — paraphrases hit the stock; opt-in). **Rooms/store:** `--room <dir>`
212
+ (default `sgc`) · `--store <f.json>` (durable cross-restart stock, default
213
+ `.skynet-stock.json`) · `--port` (default 4747, binds 127.0.0.1).
147
214
 
148
215
  ---
149
216
 
150
217
  AGPL-3.0-or-later · © 2026 Nathanael Braun · solo-author project ·
151
218
  engine: [github.com/9pings/skynet-graph](https://github.com/9pings/skynet-graph) ·
152
- docs site: [`docs/`](docs/) (GitHub Pages) ·
219
+ docs: [9pings.github.io/mindsmith](https://9pings.github.io/mindsmith/) ·
153
220
  **pre-launch — nothing is field-adopted yet (rung 6/6)**
package/bin/mindsmith CHANGED
@@ -26,8 +26,72 @@ const cmd = argv[0];
26
26
  const flag = ( n ) => { const i = argv.indexOf('--' + n); return i !== -1 ? argv[i + 1] : undefined; };
27
27
  const roomDir = flag('room') || flag('sgc') || 'sgc';
28
28
 
29
- // escalation resolution shared by serve + mcp: an N-tier routing config OR the legacy single frontier backend.
29
+ if ( !cmd || cmd === '--help' || cmd === '-h' || cmd === 'help' ) {
30
+ console.log([
31
+ 'mindsmith — an external reasoning layer for your local LLM: OpenAI-compatible proxy + MCP tools + local .sgc rooms.',
32
+ '',
33
+ 'Usage:',
34
+ ' mindsmith serve [--port N] [--room <dir>] [--store <f.json>] OpenAI endpoint over your verified stock',
35
+ ' escalation (ONE required): --routing <config.json> [--policy no-egress|allow-mid|allow-all]',
36
+ ' | env FRONTIER_MODEL=<path.gguf> (embedded gguf — needs `npm install node-llama-cpp`)',
37
+ ' | env LLM_BASE=<url> (any OpenAI-compatible endpoint)',
38
+ ' single model (ONE VRAM load = LLM server + the graph): --model <path.gguf>',
39
+ ' — user answers run WITH think; the graph (coverage · critique · propose) runs no-think, same load.',
40
+ ' model opts: --ctx <N> --gpu <auto|cuda|metal|vulkan|false> --gpu-layers <N> --think <tokens>',
41
+ ' custom llama.cpp build: --no-prebuilt (build from source) · --llama-build <auto|forceRebuild|never> · env LLAMA_CMAKE=<json>',
42
+ ' optional (separate coverage model): env LOCAL_MODEL=<path.gguf>. On WSL, export',
43
+ ' LD_LIBRARY_PATH=/usr/lib/wsl/lib:/usr/lib/x86_64-linux-gnu or the gguf silently runs on CPU.',
44
+ ' mindsmith mcp [same flags/env as serve] MCP tool surface over stdio (no http socket)',
45
+ ' mindsmith rooms list | import <f.sgc> | export <name> <dir> | freeze <name> [--room <dir>]',
46
+ '',
47
+ 'Docs: https://github.com/9pings/mindsmith · built on the skynet-graph engine.'
48
+ ].join('\n'));
49
+ process.exit(0);
50
+ }
51
+
52
+ const flagInt = ( n, d ) => { const v = flag(n); return v === undefined ? d : Number(v); };
53
+ const hasFlag = ( n ) => argv.indexOf('--' + n) !== -1;
54
+
55
+ // --model <gguf> (env MODEL) = the SINGLE-MODEL server mode. ONE gguf load answers BOTH the graph's structured
56
+ // work WITHOUT think (reasoningBudget 0 — coverage, critique, propose) AND the user-facing answers WITH think
57
+ // (the escalation), sharing one VRAM load (local-host keys the load by path+opts; the budget is per-call). So a
58
+ // box with room for a single model still gets a full LLM server + the graph value-add. Model/build options
59
+ // (context size, gpu, gpu-layers, a custom llama.cpp build) apply to that one load.
60
+ function modelConfig() {
61
+ const gpuRaw = flag('gpu'); // auto | cuda | metal | vulkan | false/cpu
62
+ const gpu = gpuRaw === undefined ? undefined : (/^(false|cpu|off|none)$/i.test(gpuRaw) ? false : gpuRaw);
63
+ const llama = {}; // getLlama opts = the custom-build surface
64
+ if ( flag('llama-build') ) llama.build = flag('llama-build'); // auto | forceRebuild | never
65
+ if ( hasFlag('no-prebuilt') || /^(1|true)$/i.test(process.env.LLAMA_FROM_SOURCE || '') ) llama.usePrebuiltBinaries = false; // build from source
66
+ if ( process.env.LLAMA_CMAKE ) { try { llama.cmakeOptions = JSON.parse(process.env.LLAMA_CMAKE); } catch ( _e ) {} }
67
+ const model = {}; // loadModel opts
68
+ const gl = flagInt('gpu-layers', process.env.GPU_LAYERS != null ? Number(process.env.GPU_LAYERS) : undefined);
69
+ if ( gl != null && !Number.isNaN(gl) ) model.gpuLayers = gl;
70
+ const cfg = {};
71
+ const ctx = flagInt('ctx', process.env.CONTEXT_SIZE != null ? Number(process.env.CONTEXT_SIZE) : undefined);
72
+ if ( ctx != null && !Number.isNaN(ctx) ) cfg.contextSize = ctx;
73
+ if ( gpu !== undefined ) cfg.gpu = gpu;
74
+ if ( Object.keys(llama).length ) cfg.llama = llama;
75
+ if ( Object.keys(model).length ) cfg.model = model;
76
+ return cfg;
77
+ }
78
+ let _sm;
79
+ function singleModel() {
80
+ if ( _sm !== undefined ) return _sm;
81
+ const path = flag('model') || process.env.MODEL;
82
+ if ( !path ) return (_sm = null);
83
+ const { makeLocalAsk } = require('skynet-graph/lib/providers/llm-local.js');
84
+ const base = modelConfig(); // IDENTICAL load opts for both handles → ONE shared load
85
+ const think = flagInt('think', process.env.THINK_BUDGET != null ? Number(process.env.THINK_BUDGET) : 1024);
86
+ const answerAsk = makeLocalAsk(Object.assign({ modelPath: path, reasoningBudget: think }, base)); // user answers — WITH think
87
+ const graphAsk = makeLocalAsk(Object.assign({ modelPath: path, reasoningBudget: 0 }, base)); // graph/critique/propose — no think, SAME load
88
+ return (_sm = { answerAsk, graphAsk, path, think, base });
89
+ }
90
+
91
+ // escalation resolution shared by serve + mcp: single-model, an N-tier routing config, or a single frontier backend.
30
92
  function resolveEscalation( need ) {
93
+ const sm = singleModel();
94
+ if ( sm ) return { frontierChat: sm.answerAsk };
31
95
  const routing = resolveRouting(argv, process.env);
32
96
  if ( routing ) return { tiers: routing.tiers, policy: routing.policy };
33
97
  let frontierChat;
@@ -37,7 +101,9 @@ function resolveEscalation( need ) {
37
101
  return { frontierChat };
38
102
  }
39
103
  function buildApp( escalation, extra ) {
40
- const localAsk = process.env.LOCAL_MODEL ? require('skynet-graph/lib/providers/llm-local.js').makeLocalAsk({ modelPath: process.env.LOCAL_MODEL, reasoningBudget: 0 }) : undefined;
104
+ const sm = singleModel();
105
+ const localAsk = sm ? sm.graphAsk // single-model: the graph shares the one load (no think)
106
+ : (process.env.LOCAL_MODEL ? require('skynet-graph/lib/providers/llm-local.js').makeLocalAsk({ modelPath: process.env.LOCAL_MODEL, reasoningBudget: 0 }) : undefined);
41
107
  return createApp(Object.assign({}, escalation, {
42
108
  localAsk,
43
109
  store: flag('store') || '.skynet-stock.json', sgcDir: roomDir,
@@ -65,7 +131,7 @@ if ( cmd === 'rooms' ) {
65
131
  console.log('frozen: ' + r.dossier + ' sha256 ' + r.sha256.slice(0, 16) + '… (' + r.classes + ' classes)');
66
132
  } else { console.error('usage: mindsmith rooms list|import <file>|export <name> <dest>|freeze <name> [--room <dir>]'); process.exit(1); }
67
133
  } catch ( e ) { console.error(e.message); process.exit(1); }
68
- } else if ( cmd === 'serve' || cmd === undefined ) {
134
+ } else if ( cmd === 'serve' ) {
69
135
  const app = buildApp(resolveEscalation('serve'), {
70
136
  port: Number(flag('port')) || 4747,
71
137
  onAnswer: ( row ) => console.error('[' + (row.source === 'local' ? 'cache' : 'frontier') + '] ' + row.query),
@@ -86,7 +152,8 @@ if ( cmd === 'rooms' ) {
86
152
  // the FULL tool surface over the room: proxy (ask/drift/metrics/lattice_load) + the ASSISTANT
87
153
  // lanes over the room's methods stock (hint = certified menu · propose = gated admission) +
88
154
  // the C9 critical mind on the escalation backend (critique).
89
- const wiring = { proxy: app.proxy, critiqueAsk: app.escalationAsk };
155
+ const sm = singleModel();
156
+ const wiring = { proxy: app.proxy, critiqueAsk: sm ? sm.graphAsk : app.escalationAsk }; // single-model: critique/lanes run no-think on the shared load
90
157
  const mf = first.loaded.methods[0];
91
158
  if ( mf ) { try { Object.assign(wiring, stockWiring(JSON.parse(require('fs').readFileSync(require('path').join(app.sgcDir, mf), 'utf8')))); } catch ( e ) { console.error('room stock lanes unavailable: ' + e.message); } }
92
159
  const server = createMcpServer({
package/package.json CHANGED
@@ -1,8 +1,11 @@
1
1
  {
2
2
  "name": "mindsmith",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "license": "AGPL-3.0-or-later",
5
5
  "author": "Nathanael Braun <pp9ping@gmail.com>",
6
+ "repository": { "type": "git", "url": "git+https://github.com/9pings/mindsmith.git" },
7
+ "homepage": "https://github.com/9pings/mindsmith#readme",
8
+ "bugs": "https://github.com/9pings/mindsmith/issues",
6
9
  "description": "An external reasoning layer for your local LLM — an OpenAI-compatible proxy + MCP tools (an auditable critical mind, gated think-mode lanes) backed by a mixture of certified graph-experts in your own verified .sgc rooms. Repairs low-quant judgment; nothing leaves the machine (no-egress proven on real sockets).",
7
10
  "keywords": ["llm", "local-llm", "reasoning", "critical-thinking", "mixture-of-experts", "knowledge-graph", "openai-compatible", "proxy", "mcp", "agent", "offline", "gguf", "agpl", "skynet-graph"],
8
11
  "main": "./lib/app.js",
@@ -18,6 +21,9 @@
18
21
  "test": "node --test --test-force-exit test/*.test.js"
19
22
  },
20
23
  "dependencies": {
21
- "skynet-graph": "^1.2.0"
24
+ "skynet-graph": "^1.3.0"
25
+ },
26
+ "optionalDependencies": {
27
+ "node-llama-cpp": "^3.0.0"
22
28
  }
23
29
  }