@hviana/sema 0.8.2 → 0.8.5
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/AGENTS.md +38 -37
- package/README.md +17 -38
- package/TRADEMARKS.md +0 -1
- package/dist/example/demo.js +85 -34
- package/dist/src/config.d.ts +11 -0
- package/dist/src/config.js +2 -0
- package/dist/src/geometry.d.ts +21 -10
- package/dist/src/geometry.js +21 -12
- package/dist/src/meter.d.ts +62 -0
- package/dist/src/meter.js +62 -0
- package/dist/src/mind/articulation.js +1 -1
- package/dist/src/mind/attention.d.ts +4 -0
- package/dist/src/mind/attention.js +167 -17
- package/dist/src/mind/canonical.d.ts +16 -0
- package/dist/src/mind/canonical.js +41 -0
- package/dist/src/mind/derivation.d.ts +201 -0
- package/dist/src/mind/derivation.js +327 -0
- package/dist/src/mind/graph-search.d.ts +2 -1
- package/dist/src/mind/graph-search.js +70 -29
- package/dist/src/mind/match.d.ts +3 -1
- package/dist/src/mind/match.js +7 -3
- package/dist/src/mind/mechanisms/alu.js +0 -2
- package/dist/src/mind/mechanisms/cast.d.ts +1 -5
- package/dist/src/mind/mechanisms/cast.js +16 -19
- package/dist/src/mind/mechanisms/confluence.d.ts +0 -3
- package/dist/src/mind/mechanisms/confluence.js +27 -9
- package/dist/src/mind/mechanisms/cover.js +17 -20
- package/dist/src/mind/mechanisms/extraction.d.ts +0 -1
- package/dist/src/mind/mechanisms/extraction.js +13 -8
- package/dist/src/mind/mechanisms/prefix-completion.js +0 -1
- package/dist/src/mind/mechanisms/recall.d.ts +0 -1
- package/dist/src/mind/mechanisms/recall.js +40 -13
- package/dist/src/mind/mechanisms/reference.js +3 -4
- package/dist/src/mind/mind.d.ts +4 -2
- package/dist/src/mind/mind.js +5 -4
- package/dist/src/mind/pipeline-mechanism.d.ts +7 -3
- package/dist/src/mind/pipeline.js +136 -44
- package/dist/src/mind/primitives.js +9 -1
- package/dist/src/mind/rationale.d.ts +21 -5
- package/dist/src/mind/rationale.js +16 -21
- package/dist/src/mind/reasoning.d.ts +12 -20
- package/dist/src/mind/reasoning.js +190 -106
- package/dist/src/mind/recognition.js +4 -8
- package/dist/src/mind/resonance.js +20 -1
- package/dist/src/mind/trace.js +1 -0
- package/dist/src/mind/traverse.js +6 -2
- package/dist/src/mind/types.d.ts +36 -13
- package/dist/src/mind/types.js +6 -3
- package/docs/INDEX.md +23 -24
- package/docs/INVARIANTS.md +16 -17
- package/docs/architecture/bounded-reads.md +5 -5
- package/docs/architecture/closure.md +65 -0
- package/docs/architecture/commonality.md +29 -20
- package/docs/architecture/cost-model.md +7 -7
- package/docs/architecture/determinism.md +7 -7
- package/docs/architecture/exact-vs-approximate.md +4 -4
- package/docs/architecture/factored-machinery.md +14 -14
- package/docs/architecture/match-project.md +2 -3
- package/docs/architecture/mechanism-market.md +16 -16
- package/docs/architecture/meter.md +10 -11
- package/docs/architecture/store.md +4 -4
- package/docs/architecture/thresholds.md +1 -1
- package/docs/failures/tempting-but-wrong.md +14 -5
- package/docs/harness/gates.md +7 -7
- package/docs/mechanisms/cast.md +2 -2
- package/docs/mechanisms/cover.md +4 -5
- package/docs/mechanisms/extraction.md +7 -7
- package/docs/mechanisms/recall.md +8 -9
- package/example/demo.ts +90 -37
- package/jsr.json +1 -1
- package/package.json +1 -1
- package/src/alu/README.md +11 -12
- package/src/config.ts +13 -0
- package/src/geometry.ts +21 -13
- package/src/meter.ts +62 -0
- package/src/mind/articulation.ts +0 -1
- package/src/mind/attention.ts +169 -17
- package/src/mind/canonical.ts +43 -0
- package/src/mind/derivation.ts +473 -0
- package/src/mind/graph-search.ts +76 -34
- package/src/mind/match.ts +7 -3
- package/src/mind/mechanisms/alu.ts +0 -2
- package/src/mind/mechanisms/cast.ts +20 -22
- package/src/mind/mechanisms/confluence.ts +27 -13
- package/src/mind/mechanisms/cover.ts +17 -20
- package/src/mind/mechanisms/extraction.ts +13 -9
- package/src/mind/mechanisms/prefix-completion.ts +0 -1
- package/src/mind/mechanisms/recall.ts +39 -13
- package/src/mind/mechanisms/reference.ts +2 -3
- package/src/mind/mind.ts +6 -4
- package/src/mind/pipeline-mechanism.ts +7 -3
- package/src/mind/pipeline.ts +160 -52
- package/src/mind/primitives.ts +9 -1
- package/src/mind/rationale.ts +27 -23
- package/src/mind/reasoning.ts +227 -120
- package/src/mind/recognition.ts +4 -8
- package/src/mind/resonance.ts +19 -1
- package/src/mind/trace.ts +1 -0
- package/src/mind/traverse.ts +7 -5
- package/src/mind/types.ts +41 -15
- package/test/105-derive-through-reports-its-refusal.test.mjs +24 -0
- package/test/118-the-join-reaches-a-key-off-the-cut.test.mjs +74 -0
- package/test/119-the-work-does-not-grow-with-the-corpus.test.mjs +122 -0
- package/test/120-composition-is-consequence.test.mjs +132 -0
- package/test/121-the-extension-does-not-grow-with-the-corpus.test.mjs +128 -0
- package/test/122-the-climb-search-does-not-grow-with-the-corpus.test.mjs +117 -0
- package/test/123-the-paired-formulas-agree.test.mjs +90 -0
- package/test/125-the-post-grounding-branch-publishes-its-operand.test.mjs +51 -0
- package/test/126-the-pipeline-does-not-name-mechanisms.test.mjs +42 -0
- package/test/128-the-leads-somewhere-pair-agrees.test.mjs +83 -0
- package/test/129-the-trace-payload-shape.test.mjs +164 -0
- package/test/133-the-decision-point-renders-the-state.test.mjs +204 -0
- package/test/134-the-law-explains-the-engines-own-refusal.test.mjs +237 -0
- package/test/135-one-law-any-producer.test.mjs +289 -0
- package/test/136-the-two-named-limits.test.mjs +205 -0
- package/test/137-the-law-lives-once-and-below.test.mjs +400 -0
- package/test/138-the-remainder-drains-only-what-a-move-declares.test.mjs +62 -0
- package/test/139-the-witness-is-engagement-not-explanation.test.mjs +51 -0
- package/test/140-irrelevant-supply-does-not-change-an-answer.test.mjs +48 -0
- package/test/141-the-question-is-paid-at-construction.test.mjs +98 -0
- package/test/32-confluence.test.mjs +68 -0
- package/test/36-already-answered-fusion.test.mjs +20 -2
- package/test/37-cluster-dispersion-fusion.test.mjs +30 -3
- package/test/38-reason-restate-guard.test.mjs +28 -2
- package/test/43-cast-analog-seat.test.mjs +10 -0
- package/test/55-cost-meter.test.mjs +862 -0
package/AGENTS.md
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
The working manual for anyone (human or AI agent) changing Sema. For pattern
|
|
4
4
|
detail, see `docs/INDEX.md` → `docs/architecture/*.md`. You should be able to
|
|
5
|
-
develop against this document and docs/ alone; read
|
|
6
|
-
|
|
5
|
+
develop against this document and docs/ alone; read `docs/architecture/` for why
|
|
6
|
+
a pattern holds.
|
|
7
7
|
|
|
8
8
|
## 1. Orientation
|
|
9
9
|
|
|
@@ -14,7 +14,7 @@ accelerators), and a cost-based search that composes answers from stored facts
|
|
|
14
14
|
the only runtime dependency.
|
|
15
15
|
|
|
16
16
|
```bash
|
|
17
|
-
npm install # dev tooling + parquet reader
|
|
17
|
+
npm install # dev tooling + parquet reader for one example
|
|
18
18
|
npm run build # tsc → dist/
|
|
19
19
|
npm test # tsc && node --test test/**/*.test.mjs
|
|
20
20
|
npm run demo # example/demo.ts — the four-note README demo
|
|
@@ -55,13 +55,15 @@ Five invariants. Violate one and the system degrades silently — tests pin them
|
|
|
55
55
|
| 4 | One cost currency | Single ladder `MICRO`/`STEP`/`CONCEPT`/`PASS`; `weight = moves + PASS·unaccounted`; compare at `STEP` grade | `docs/architecture/cost-model.md` → `src/mind/graph-search.ts`, `src/derive/` |
|
|
56
56
|
| 5 | Bounded reads | No per-query read grows with N; cap is `hubBound = √N` enforced at the store via `LIMIT` reads, existence probes, and `bytesPrefix` caps | `docs/architecture/bounded-reads.md` → `src/store.ts`, `src/mind/traverse.ts` |
|
|
57
57
|
|
|
58
|
-
Cross-cutting contracts (single-definition,
|
|
59
|
-
in `src/geometry.ts` is the one boundary rule;
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
`src/mind/pipeline-mechanism.ts` is
|
|
63
|
-
is the write-only work accounting surface.
|
|
64
|
-
|
|
58
|
+
Cross-cutting contracts (single-definition, imported everywhere):
|
|
59
|
+
`contentLevels` in `src/geometry.ts` is the one boundary rule;
|
|
60
|
+
`src/mind/derivation.ts` is the closure law; `src/mind/canonical.ts` is the
|
|
61
|
+
canonical segmentation contract; `src/mind/junction.ts` is the shared
|
|
62
|
+
content-addressed ascent; `Precomputed` in `src/mind/pipeline-mechanism.ts` is
|
|
63
|
+
the per-response memo; `src/meter.ts` is the write-only work accounting surface.
|
|
64
|
+
See `docs/INDEX.md` and `factored-machinery.md` for the contract table and
|
|
65
|
+
ownership. Tie-breaks are corpus-determined, not interchangeable
|
|
66
|
+
(`determinism.md`).
|
|
65
67
|
|
|
66
68
|
## 3. Where things live
|
|
67
69
|
|
|
@@ -89,15 +91,15 @@ contract table and `docs/architecture/factored-machinery.md` for ownership.
|
|
|
89
91
|
| Sublibraries (own READMEs) | `src/derive/`, `src/alu/`, `src/rabitq-ivf/` |
|
|
90
92
|
|
|
91
93
|
Mind functions are free functions over `MindContext` (`src/mind/types.ts`), not
|
|
92
|
-
methods
|
|
94
|
+
methods; `mind.ts` is a thin assembly.
|
|
93
95
|
|
|
94
96
|
## 4. Recipes
|
|
95
97
|
|
|
96
98
|
### Add a grounding mechanism or extension
|
|
97
99
|
|
|
98
100
|
Implement `PipelineMechanism` (`floor` → admissible bound or `null`; `run` →
|
|
99
|
-
candidates with `bytes`/`accounted`/`moves
|
|
100
|
-
`scaffolding`/`complete`). Register via
|
|
101
|
+
candidates with `bytes`/`accounted`/`moves` + optional
|
|
102
|
+
`scaffolding`/`complete`/`used`/`provenance`). Register via
|
|
101
103
|
`new Mind({ mechanismFactories: [host => yourMechanism(host)] })`. Verify the
|
|
102
104
|
four market constraints (decoupled, declared competence, visible budget,
|
|
103
105
|
evidence travels). → `docs/architecture/mechanism-market.md`
|
|
@@ -125,14 +127,13 @@ Run the full suite with your store substituted. → `docs/architecture/store.md`
|
|
|
125
127
|
## 5. Testing norms
|
|
126
128
|
|
|
127
129
|
Tests are `node:test` suites in `test/*.test.mjs`, numbered by theme, run
|
|
128
|
-
against built `dist/` (`npm test`;
|
|
129
|
-
`node --test test/22-multihop.test.mjs`
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
`src/{alu,derive,rabitq-ivf}/test/` with zero Sema dependency.
|
|
130
|
+
against built `dist/` (`npm test`; one suite:
|
|
131
|
+
`node --test test/22-multihop.test.mjs`). New behaviour ⇒ a test in the matching
|
|
132
|
+
numbered suite. Many tests pin contracts that look like implementation details
|
|
133
|
+
(ladder order, span-shape readings, `MechanismResult.complete`, fold invariance,
|
|
134
|
+
recognition idempotence, honest silence). A simplification that fails an
|
|
135
|
+
existing test is wrong until the test is proven wrong. Sublibraries test
|
|
136
|
+
themselves in `src/{alu,derive,rabitq-ivf}/test/` with zero Sema dependency.
|
|
136
137
|
|
|
137
138
|
## 6. Instrumentation — the meter and the rationale ARE the dev surface
|
|
138
139
|
|
|
@@ -143,17 +144,17 @@ instrumentation, and the only ones. Both are read through the public path —
|
|
|
143
144
|
and the `inspectRationale` callback on `respond`/`respondText`/`respondTurn`.
|
|
144
145
|
|
|
145
146
|
When a change needs to be seen, measured, or proved, EXTEND THEM: a counter in
|
|
146
|
-
`meter.ts` (the one place a counter name exists
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
`
|
|
155
|
-
`danglingReads`/`compactFailures` and the `console.warn`s that report them
|
|
156
|
-
|
|
147
|
+
`meter.ts` (the one place a counter name exists), a step or note where the
|
|
148
|
+
mechanism emits it (`src/mind/trace.ts` holds the move vocabulary). A gap in
|
|
149
|
+
instrumentation is a defect IN the instrumentation: close it there, once, so the
|
|
150
|
+
next person sees it too. Never add a parallel channel for a single investigation
|
|
151
|
+
— no ad-hoc logging or timing probes left in `src/` (`performance.now()` belongs
|
|
152
|
+
in `meter.ts`, not at a call site), no private per-layer counter where a
|
|
153
|
+
`meter.ts` field belongs, and no trace channel of your own: a callback threaded
|
|
154
|
+
through a call chain must FEED the rationale, the way `GraphSearch`'s
|
|
155
|
+
`onDerivation` feeds `traceDerivation`. (`store.ts`'s
|
|
156
|
+
`danglingReads`/`compactFailures` and the `console.warn`s that report them stay:
|
|
157
|
+
session-lifetime HEALTH counters, not per-response work.)
|
|
157
158
|
|
|
158
159
|
## 7. Dependencies and licensing
|
|
159
160
|
|
|
@@ -161,8 +162,8 @@ PolyForm Noncommercial 1.0.0 with separate commercial licensing (see
|
|
|
161
162
|
`LICENSE.md`, `COMMERCIAL-LICENSE.md`, `TRADEMARKS.md`). The library has **no
|
|
162
163
|
runtime dependencies** — pinned by `test/88-dependency-footprint.test.mjs`
|
|
163
164
|
(`dist/src` may import only `node:` builtins and relative paths; `package.json`
|
|
164
|
-
has no `dependencies`). Examples may use dev dependencies
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
165
|
+
has no `dependencies`). Examples may use dev dependencies via dynamic import
|
|
166
|
+
only where needed (`example/train_base` + `hyparquet` is the reference).
|
|
167
|
+
Training corpora: a store retains text verbatim, so upstream licences apply in
|
|
168
|
+
full — NonCommercial and ShareAlike corpora cannot enter a trainer; see
|
|
169
|
+
`DATASETS.md`.
|
package/README.md
CHANGED
|
@@ -179,39 +179,16 @@ in the same pass — reasons onward to a separate fact about that painter. Nothi
|
|
|
179
179
|
in the reply but the painter's own name comes from the question.
|
|
180
180
|
|
|
181
181
|
```ts
|
|
182
|
-
// demo.ts —
|
|
183
|
-
|
|
184
|
-
import { Mind } from "../src/index.js";
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
await mind.ingest([
|
|
193
|
-
// One relation, shown three times — a pattern taught purely by example:
|
|
194
|
-
["The Mona Lisa was painted by Leonardo da Vinci.", "Leonardo da Vinci"],
|
|
195
|
-
["The Starry Night was painted by Vincent van Gogh.", "Vincent van Gogh"],
|
|
196
|
-
[
|
|
197
|
-
"The Night Watch was painted by Rembrandt van Rijn.",
|
|
198
|
-
"Rembrandt van Rijn",
|
|
199
|
-
],
|
|
200
|
-
// One stray fact, keyed on a name none of the examples mention:
|
|
201
|
-
["Pablo Picasso", "Pablo Picasso co-founded the Cubist movement"],
|
|
202
|
-
]);
|
|
203
|
-
|
|
204
|
-
// 1) GENERALIZE — apply the learned pattern to an unseen sentence and read out
|
|
205
|
-
// the painter, then keep going into what is known about him.
|
|
206
|
-
console.log(await ask("The Weeping Woman was painted by Pablo Picasso."));
|
|
207
|
-
|
|
208
|
-
// 2) COMPUTE — exact arithmetic, grounded right where the notes go silent.
|
|
209
|
-
console.log(await ask("a museum charges 12*4 for a family ticket"));
|
|
210
|
-
|
|
211
|
-
await mind.store.close();
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
main();
|
|
182
|
+
// demo.ts — a corpus goes in, and the memory is read back out.
|
|
183
|
+
|
|
184
|
+
import { Mind, SQliteStore } from "../src/index.js";
|
|
185
|
+
|
|
186
|
+
const mind = new Mind({ store: new SQliteStore({ path: ":memory:" }) });
|
|
187
|
+
await mind.ingest(CORPUS); // (context -> what follows) notes, the deposit shape
|
|
188
|
+
|
|
189
|
+
mind.sampleCorpus(4); // what the memory HOLDS
|
|
190
|
+
mind.searchCorpusText("Pablo Picasso"); // which notes a question REACHES
|
|
191
|
+
await mind.respond("The Weeping Woman was painted by Pablo Picasso.");
|
|
215
192
|
```
|
|
216
193
|
|
|
217
194
|
```text
|
|
@@ -224,7 +201,7 @@ Ask for the receipt instead of the text, and each answer says how it was reached
|
|
|
224
201
|
the route, and, on request, the complete replayable trace behind it:
|
|
225
202
|
|
|
226
203
|
```text
|
|
227
|
-
"The Weeping Woman was painted by Pablo Picasso." → provenance:
|
|
204
|
+
"The Weeping Woman was painted by Pablo Picasso." → provenance: cover
|
|
228
205
|
( structure carried across the three worked examples )
|
|
229
206
|
|
|
230
207
|
"a museum charges 12*4 for a family ticket" → provenance: cover
|
|
@@ -233,10 +210,12 @@ the route, and, on request, the complete replayable trace behind it:
|
|
|
233
210
|
|
|
234
211
|
> [!NOTE]
|
|
235
212
|
> This is **[example/demo.ts](example/demo.ts)** — run it with `npm run demo`.
|
|
236
|
-
>
|
|
237
|
-
>
|
|
238
|
-
>
|
|
239
|
-
>
|
|
213
|
+
> It reads the memory back two ways: `sampleCorpus` browses what it holds, and
|
|
214
|
+
> `searchCorpusText` reports which stored notes a question reaches — exactly, so
|
|
215
|
+
> a question overlapping nothing is answered with a note saying so, never with
|
|
216
|
+
> an invention. The first answer names a painting Sema was never shown and still
|
|
217
|
+
> returns a fact about Cubism that appears **nowhere** in it; the second is
|
|
218
|
+
> computed. Every step traces back to the five notes above.
|
|
240
219
|
|
|
241
220
|
---
|
|
242
221
|
|
package/TRADEMARKS.md
CHANGED
package/dist/example/demo.js
CHANGED
|
@@ -1,39 +1,90 @@
|
|
|
1
|
-
// demo.ts —
|
|
1
|
+
// demo.ts — a corpus goes in, and the memory is read back out.
|
|
2
2
|
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
|
|
11
|
-
|
|
3
|
+
// Sema is given a small corpus of plain notes, each one the shape every deposit
|
|
4
|
+
// has: a context, and what follows it. Then the memory is read two ways — what
|
|
5
|
+
// it HOLDS (`sampleCorpus`), and which of its notes a question REACHES
|
|
6
|
+
// (`searchCorpusText`). Both run through the same content-addressed machinery an
|
|
7
|
+
// answer uses (src/mind/corpus.ts); nothing is indexed and nothing is written.
|
|
8
|
+
//
|
|
9
|
+
// The search addresses content EXACTLY, not by keyword: a question reaches a
|
|
10
|
+
// note when it shares chunk-aligned content with it, so a question with no such
|
|
11
|
+
// overlap is reported as exactly that — a STATE, rendered by the text layer
|
|
12
|
+
// (`CorpusTextResult.note`), never as prose the engine invented.
|
|
13
|
+
//
|
|
14
|
+
// The last act is two ordinary answers, each with its derivation streamed as it
|
|
15
|
+
// unfolds, the PROVENANCE that names the route it grounded on, and the work it
|
|
16
|
+
// cost read off the meter: the rationale and the meter ARE the explanation
|
|
17
|
+
// surface (AGENTS.md §6).
|
|
18
|
+
import { decodeText, formatReport, Mind, SQliteStore } from "../src/index.js";
|
|
19
|
+
// One relation shown three times — a pattern taught purely by example — plus a
|
|
20
|
+
// stray fact keyed on a name none of the examples mention.
|
|
21
|
+
const CORPUS = [
|
|
22
|
+
["The Mona Lisa was painted by Leonardo da Vinci.", "Leonardo da Vinci"],
|
|
23
|
+
["The Starry Night was painted by Vincent van Gogh.", "Vincent van Gogh"],
|
|
24
|
+
[
|
|
25
|
+
"The Night Watch was painted by Rembrandt van Rijn.",
|
|
26
|
+
"Rembrandt van Rijn",
|
|
27
|
+
],
|
|
28
|
+
["Pablo Picasso", "Pablo Picasso co-founded the Cubist movement"],
|
|
29
|
+
["The Weeping Woman was painted by Pablo Picasso.", "Pablo Picasso"],
|
|
30
|
+
];
|
|
31
|
+
// Questions the corpus can address, and one it cannot — the honest miss.
|
|
32
|
+
const QUERIES = [
|
|
33
|
+
"The Mona Lisa was painted by Leonardo da Vinci.",
|
|
34
|
+
"Pablo Picasso",
|
|
35
|
+
"xylophone",
|
|
36
|
+
];
|
|
37
|
+
// One question answered by composing across the notes, and one answered by
|
|
38
|
+
// computing: the two routes the corpus search does not take.
|
|
39
|
+
const ASKS = [
|
|
40
|
+
"The Weeping Woman was painted by Pablo Picasso.",
|
|
41
|
+
"a museum charges 12*4 for a family ticket",
|
|
42
|
+
];
|
|
12
43
|
async function main() {
|
|
13
|
-
const mind = new Mind({
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
//
|
|
44
|
+
const mind = new Mind({
|
|
45
|
+
store: new SQliteStore({ path: ":memory:" }),
|
|
46
|
+
profile: true,
|
|
47
|
+
});
|
|
48
|
+
await mind.ingest(CORPUS);
|
|
49
|
+
// 1) WHAT THE MEMORY HOLDS — real pairs, browsed, no query and no random draw.
|
|
50
|
+
console.log("— the corpus, as the memory holds it —");
|
|
51
|
+
for (const p of mind.sampleCorpus(4).pairs) {
|
|
52
|
+
console.log(` ${decodeText(p.context)} → ${decodeText(p.continuation)}`);
|
|
53
|
+
}
|
|
54
|
+
// 2) SEARCH — which stored notes does a question reach? A question that
|
|
55
|
+
// addresses the corpus answers with pairs; one that shares nothing with it
|
|
56
|
+
// answers with a note saying so.
|
|
57
|
+
for (const q of QUERIES) {
|
|
58
|
+
const r = mind.searchCorpusText(q, 3);
|
|
59
|
+
console.log(`\n— "${q}" — ${r.resolved} resolved / ${r.reached} reached`);
|
|
60
|
+
if (r.note !== undefined)
|
|
61
|
+
console.log(` ${r.note}`);
|
|
62
|
+
for (const p of r.pairs) {
|
|
63
|
+
console.log(` ${p.context} → ${p.continuation} (${p.matchedBytes} matched)`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// 3) ANSWERS, WITH THEIR DERIVATION — the same pipeline, read as data. Steps
|
|
67
|
+
// repeat (recognise re-enters under every mechanism that needs it), so each
|
|
68
|
+
// distinct mechanism-and-note is printed once, in the order it first ran.
|
|
69
|
+
for (const q of ASKS) {
|
|
70
|
+
const seen = new Set();
|
|
71
|
+
const trace = [];
|
|
72
|
+
const r = await mind.respond(q, (s) => {
|
|
73
|
+
const line = `${s.mechanism.join(" › ")}${s.note ? ` — ${s.note}` : ""}`;
|
|
74
|
+
if (seen.has(line))
|
|
75
|
+
return;
|
|
76
|
+
seen.add(line);
|
|
77
|
+
trace.push(`${" ".repeat(Math.max(0, s.mechanism.length - 1))}${line}`);
|
|
78
|
+
});
|
|
79
|
+
console.log(`\n— "${q}" — ${r.provenance ?? "no answer"}`);
|
|
80
|
+
console.log(` ${decodeText(r.bytes).trim()}`);
|
|
81
|
+
console.log("— how —");
|
|
82
|
+
for (const s of trace)
|
|
83
|
+
console.log(s);
|
|
84
|
+
if (mind.lastCost !== null) {
|
|
85
|
+
console.log(`— what it cost —\n${formatReport(mind.lastCost)}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
37
88
|
await mind.store.close();
|
|
38
89
|
}
|
|
39
90
|
main();
|
package/dist/src/config.d.ts
CHANGED
|
@@ -100,6 +100,17 @@ export interface MindConfig {
|
|
|
100
100
|
seed: number;
|
|
101
101
|
recallQueryK: number;
|
|
102
102
|
haloQueryK: number;
|
|
103
|
+
/** Branch nodes the pivot sweep may PROBE looking for the learnt context an
|
|
104
|
+
* answer contains — the pivot's own shortlist capacity, separate from
|
|
105
|
+
* `recallQueryK` because they are different quantities: this one bounds a
|
|
106
|
+
* MECHANICAL sweep over the answer's tree (breadth-first, largest regions
|
|
107
|
+
* first, so an exhausted allowance drops the far ones and never the near
|
|
108
|
+
* ones), while `recallQueryK` bounds the bridge's candidate reads. Sharing
|
|
109
|
+
* one number for both meant that tightening either silently starved the
|
|
110
|
+
* other — measured: at `recallQueryK: 1` the pivot cannot find a pivot at
|
|
111
|
+
* all. (`rationaleSampleK` was split out of `recallQueryK` for the same
|
|
112
|
+
* reason, found by an adversarial review.) */
|
|
113
|
+
pivotProbeK: number;
|
|
103
114
|
/** Corpus reading (see src/mind/corpus.ts): results per call, resolved
|
|
104
115
|
* nodes climbed from, contexts requested per climb, probes used to stride
|
|
105
116
|
* the id space when browsing, bytes of each side a preview keeps, and the
|
package/dist/src/config.js
CHANGED
|
@@ -5,6 +5,7 @@ export const DEFAULT_CONFIG = {
|
|
|
5
5
|
seed: 42,
|
|
6
6
|
recallQueryK: 12,
|
|
7
7
|
haloQueryK: 12,
|
|
8
|
+
pivotProbeK: 12,
|
|
8
9
|
rationaleSampleK: 12,
|
|
9
10
|
corpusLimitMax: 24,
|
|
10
11
|
corpusClimbs: 24,
|
|
@@ -51,6 +52,7 @@ export function resolveConfig(opts = {}) {
|
|
|
51
52
|
seed: opts.seed ?? DEFAULT_CONFIG.seed,
|
|
52
53
|
recallQueryK: opts.recallQueryK ?? DEFAULT_CONFIG.recallQueryK,
|
|
53
54
|
haloQueryK: opts.haloQueryK ?? DEFAULT_CONFIG.haloQueryK,
|
|
55
|
+
pivotProbeK: opts.pivotProbeK ?? DEFAULT_CONFIG.pivotProbeK,
|
|
54
56
|
rationaleSampleK: opts.rationaleSampleK ?? DEFAULT_CONFIG.rationaleSampleK,
|
|
55
57
|
corpusLimitMax: opts.corpusLimitMax ?? DEFAULT_CONFIG.corpusLimitMax,
|
|
56
58
|
corpusClimbs: opts.corpusClimbs ?? DEFAULT_CONFIG.corpusClimbs,
|
package/dist/src/geometry.d.ts
CHANGED
|
@@ -106,17 +106,28 @@ export declare function dominates(partLen: number, wholeLen: number): boolean;
|
|
|
106
106
|
* Consumer: `companyProfile` (mind/learning.ts), which sizes its constituent
|
|
107
107
|
* sketch at this capacity instead of a visit budget. */
|
|
108
108
|
export declare function profileCapacity(D: number): number;
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
*
|
|
112
|
-
*
|
|
109
|
+
/**
|
|
110
|
+
* The POOLED-vote significance floor, and the derivation lives here because
|
|
111
|
+
* its PREMISE is a property of the caller's weighting.
|
|
112
|
+
*
|
|
113
|
+
* DERIVATION (docs/architecture/thresholds.md §2): a maximally-specific region
|
|
114
|
+
* contributes at most `ln N` to a pooled vote, so `ln(N) + 1/2` sits half a
|
|
115
|
+
* unit above ONE region's ceiling — it demands corroboration BEYOND a single
|
|
116
|
+
* region, which is what makes it a consensus bar rather than a resonance bar.
|
|
113
117
|
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
|
|
118
|
+
* PREMISE: that per-region ceiling is an IDF, `ln(N/c)` — attention.ts's
|
|
119
|
+
* `inverse` mode, the mode every non-test caller runs. The other two modes
|
|
120
|
+
* weight a region by `ln(1+c)` (`direct`) or `ln(N/c) + ln(1+c)` (`combined`),
|
|
121
|
+
* i.e. `ln N + ln(1 + 1/c)`, so they exceed the premise's ceiling by at most
|
|
122
|
+
* `ln 2` — a DERIVED bound, not a hole: the floor stays within `ln 2` of its
|
|
123
|
+
* own premise in every mode, and exactly on it in `inverse`.
|
|
124
|
+
*
|
|
125
|
+
* MEASURED: the floor is read on the pooled vote (`commitVotes`, `recall`,
|
|
126
|
+
* `cast`). Across 27 anchors on 6 queries, 11 cleared it by the sum and NONE
|
|
127
|
+
* by a single region's peak — gating on one region would refuse every elected
|
|
128
|
+
* root.
|
|
129
|
+
*/
|
|
130
|
+
export declare function consensusFloor(N: number): number;
|
|
120
131
|
export interface Folded {
|
|
121
132
|
tree: Sema;
|
|
122
133
|
/** Byte length of the subtree — carried incrementally so the stable-prefix
|
package/dist/src/geometry.js
CHANGED
|
@@ -143,21 +143,30 @@ export function dominates(partLen, wholeLen) {
|
|
|
143
143
|
export function profileCapacity(D) {
|
|
144
144
|
return Math.max(1, Math.floor(Math.sqrt(D)));
|
|
145
145
|
}
|
|
146
|
+
/**
|
|
147
|
+
* The POOLED-vote significance floor, and the derivation lives here because
|
|
148
|
+
* its PREMISE is a property of the caller's weighting.
|
|
149
|
+
*
|
|
150
|
+
* DERIVATION (docs/architecture/thresholds.md §2): a maximally-specific region
|
|
151
|
+
* contributes at most `ln N` to a pooled vote, so `ln(N) + 1/2` sits half a
|
|
152
|
+
* unit above ONE region's ceiling — it demands corroboration BEYOND a single
|
|
153
|
+
* region, which is what makes it a consensus bar rather than a resonance bar.
|
|
154
|
+
*
|
|
155
|
+
* PREMISE: that per-region ceiling is an IDF, `ln(N/c)` — attention.ts's
|
|
156
|
+
* `inverse` mode, the mode every non-test caller runs. The other two modes
|
|
157
|
+
* weight a region by `ln(1+c)` (`direct`) or `ln(N/c) + ln(1+c)` (`combined`),
|
|
158
|
+
* i.e. `ln N + ln(1 + 1/c)`, so they exceed the premise's ceiling by at most
|
|
159
|
+
* `ln 2` — a DERIVED bound, not a hole: the floor stays within `ln 2` of its
|
|
160
|
+
* own premise in every mode, and exactly on it in `inverse`.
|
|
161
|
+
*
|
|
162
|
+
* MEASURED: the floor is read on the pooled vote (`commitVotes`, `recall`,
|
|
163
|
+
* `cast`). Across 27 anchors on 6 queries, 11 cleared it by the sum and NONE
|
|
164
|
+
* by a single region's peak — gating on one region would refuse every elected
|
|
165
|
+
* root.
|
|
166
|
+
*/
|
|
146
167
|
export function consensusFloor(N) {
|
|
147
168
|
return Math.log(N) + 1 / 2;
|
|
148
169
|
}
|
|
149
|
-
/** The coverage bar for the reach (interior) index, when vector-similarity
|
|
150
|
-
* gating is used. Returns the concept threshold — the structural midpoint
|
|
151
|
-
* (~0.5 at D=1024) where two forms are "more similar than not."
|
|
152
|
-
*
|
|
153
|
-
* Currently UNUSED in the hot training path: interior nodes are indexed
|
|
154
|
-
* unconditionally (hash-cons dedup bounds the index naturally).
|
|
155
|
-
* Post-hoc structural compaction ({@link Store.compactContentIndex})
|
|
156
|
-
* replaces runtime coverage gating with a batch pass that removes
|
|
157
|
-
* structurally-isolated entries. Derived, never tuned. */
|
|
158
|
-
export function coverageBar(_maxGroup, D) {
|
|
159
|
-
return conceptThreshold(D);
|
|
160
|
-
}
|
|
161
170
|
// ---- folding ----
|
|
162
171
|
//
|
|
163
172
|
// The river fold is a hierarchical prefix network: each level contracts
|
package/dist/src/meter.d.ts
CHANGED
|
@@ -162,9 +162,71 @@ export declare class Meter {
|
|
|
162
162
|
joinNoKey: number;
|
|
163
163
|
/** Refused: the fact contains no entity that leads anywhere. */
|
|
164
164
|
joinNoEntity: number;
|
|
165
|
+
/** `recompleteNode` re-covered a produced form — the descent that decomposes
|
|
166
|
+
* a completion by ITS OWN kids. Without this the descent is invisible: a
|
|
167
|
+
* caller could see the chain's result but not whether the recomposition
|
|
168
|
+
* happened, so "the recursion stopped" and "the recursion never ran" were
|
|
169
|
+
* indistinguishable from the counters alone. */
|
|
170
|
+
recompletes: number;
|
|
165
171
|
/** Times the reasoner pivoted on a span its answer contains and stepped
|
|
166
172
|
* across that fact. */
|
|
167
173
|
pivotSteps: number;
|
|
174
|
+
/** Canon probes REFUSED because the canon budget ran out — the one thing the
|
|
175
|
+
* budget does that nothing could see. The budget itself is derived
|
|
176
|
+
* (`bytes.length · chainReach(W)²`, recognition.ts), and the cheap exact route
|
|
177
|
+
* is deliberately unbudgeted, so this counter says exactly when the expensive
|
|
178
|
+
* route was priced out. Counted where the fact happens (the `!canonBudget`
|
|
179
|
+
* refusal), not where the probe is called. */
|
|
180
|
+
canonProbesDenied: number;
|
|
181
|
+
/** The pipeline's remainder AT THE DECISION POINT, in bytes: what the grounded
|
|
182
|
+
* answer plus the pre-computed spans left unexplained, after the same W floor
|
|
183
|
+
* the fuse gate uses. This is the quantity that licenses (or refuses) the
|
|
184
|
+
* post-grounding extension and the fusion — it was computed, used, and never
|
|
185
|
+
* published, so nothing could measure what a search had LEFT when it decided.
|
|
186
|
+
* Read with {@link postGroundingRemainderSpans}. */
|
|
187
|
+
postGroundingRemainderBytes: number;
|
|
188
|
+
/** How many spans that remainder consists of (each at least one W window). */
|
|
189
|
+
postGroundingRemainderSpans: number;
|
|
190
|
+
/** Times `fuseAttention` produced a FUSED answer — not times it was called.
|
|
191
|
+
* It is entered whenever the query has a remainder ≥ W and returns early when
|
|
192
|
+
* there is nothing to bridge (`containsSpan`, a lone root, an empty pass), so
|
|
193
|
+
* the call and the fact are different things and only the fact is counted.
|
|
194
|
+
* Its own rationale step reports the fusion; this is the untraced view, and
|
|
195
|
+
* its cost is one bridging edge: `fuseRuns · STEP`. */
|
|
196
|
+
fuseRuns: number;
|
|
197
|
+
/** Steps the post-grounding EXTENSION took — pivots plus forward-absorbs.
|
|
198
|
+
* `pivotSteps` counts only the former, so before this the extension's COST was
|
|
199
|
+
* not computable at all. With it, the price of extending the answer is
|
|
200
|
+
* `reasonSteps · STEP`, the ladder's own value for following an edge. */
|
|
201
|
+
reasonSteps: number;
|
|
202
|
+
/** Bytes of the grounding's UNCOVERED material the extension was justified by
|
|
203
|
+
* — the union of the spans each step carried a `W`-window of. The gate
|
|
204
|
+
* already computed WHICH span carried it per step and kept only a boolean;
|
|
205
|
+
* this is that fact, accumulated. Read with {@link reasonSteps}: one is the
|
|
206
|
+
* price, the other the explanation. */
|
|
207
|
+
reasonCarriedBytes: number;
|
|
208
|
+
/** Bytes of the question's REMAINDER a step CONSUMED — the drop the law's own
|
|
209
|
+
* `advance` makes when a declared move carries the material it accounts for.
|
|
210
|
+
* Read with {@link reasonSteps} and {@link reasonCarriedBytes}: carrying is
|
|
211
|
+
* the engagement, this is the consumption, and before it the second was
|
|
212
|
+
* invisible. */
|
|
213
|
+
closureDrainedBytes: number;
|
|
214
|
+
/** Bytes of the question the grounding PRICED but whose material its answer does
|
|
215
|
+
* NOT carry, at or above one quantum — the debt the construction leaves for the
|
|
216
|
+
* walk to pay by carrying it. Zero means the grounding's coverage is honest:
|
|
217
|
+
* everything it priced is either held by the answer or under the W floor. */
|
|
218
|
+
groundingWithheldBytes: number;
|
|
219
|
+
/** Branch-node probes the pivot sweep actually spent looking for the learnt
|
|
220
|
+
* context an answer contains (one `resonate` per probe). The untraced view
|
|
221
|
+
* of what the multi-hop's shortlist costs. */
|
|
222
|
+
pivotProbes: number;
|
|
223
|
+
/** Branch nodes the pivot's probe cap withheld (`branchCount − probeCap`, over
|
|
224
|
+
* every call). A capacity fact, not a verdict: the sweep is breadth-first,
|
|
225
|
+
* so the probes it DOES spend are the largest regions, and recognition still
|
|
226
|
+
* contributes every exact containment candidate regardless of the budget.
|
|
227
|
+
* Read it with {@link pivotProbes} — one says the work, the other the
|
|
228
|
+
* shortfall. */
|
|
229
|
+
pivotBranchesUnprobed: number;
|
|
168
230
|
/** `bridge` calls the cover makes assembling connectors (pairwise + n-ary). */
|
|
169
231
|
coverBridges: number;
|
|
170
232
|
/** Continuations a CHAIN hop offered the search. Bounded by the question
|
package/dist/src/meter.js
CHANGED
|
@@ -166,6 +166,12 @@ export class Meter {
|
|
|
166
166
|
joinNoKey = 0;
|
|
167
167
|
/** Refused: the fact contains no entity that leads anywhere. */
|
|
168
168
|
joinNoEntity = 0;
|
|
169
|
+
/** `recompleteNode` re-covered a produced form — the descent that decomposes
|
|
170
|
+
* a completion by ITS OWN kids. Without this the descent is invisible: a
|
|
171
|
+
* caller could see the chain's result but not whether the recomposition
|
|
172
|
+
* happened, so "the recursion stopped" and "the recursion never ran" were
|
|
173
|
+
* indistinguishable from the counters alone. */
|
|
174
|
+
recompletes = 0;
|
|
169
175
|
// ── Mind: the multi-hop pivot (EXTENSION) ───────────────────────────────
|
|
170
176
|
//
|
|
171
177
|
// `pivotStep` was observable only through the rationale, and the rationale
|
|
@@ -175,6 +181,62 @@ export class Meter {
|
|
|
175
181
|
/** Times the reasoner pivoted on a span its answer contains and stepped
|
|
176
182
|
* across that fact. */
|
|
177
183
|
pivotSteps = 0;
|
|
184
|
+
/** Canon probes REFUSED because the canon budget ran out — the one thing the
|
|
185
|
+
* budget does that nothing could see. The budget itself is derived
|
|
186
|
+
* (`bytes.length · chainReach(W)²`, recognition.ts), and the cheap exact route
|
|
187
|
+
* is deliberately unbudgeted, so this counter says exactly when the expensive
|
|
188
|
+
* route was priced out. Counted where the fact happens (the `!canonBudget`
|
|
189
|
+
* refusal), not where the probe is called. */
|
|
190
|
+
canonProbesDenied = 0;
|
|
191
|
+
/** The pipeline's remainder AT THE DECISION POINT, in bytes: what the grounded
|
|
192
|
+
* answer plus the pre-computed spans left unexplained, after the same W floor
|
|
193
|
+
* the fuse gate uses. This is the quantity that licenses (or refuses) the
|
|
194
|
+
* post-grounding extension and the fusion — it was computed, used, and never
|
|
195
|
+
* published, so nothing could measure what a search had LEFT when it decided.
|
|
196
|
+
* Read with {@link postGroundingRemainderSpans}. */
|
|
197
|
+
postGroundingRemainderBytes = 0;
|
|
198
|
+
/** How many spans that remainder consists of (each at least one W window). */
|
|
199
|
+
postGroundingRemainderSpans = 0;
|
|
200
|
+
/** Times `fuseAttention` produced a FUSED answer — not times it was called.
|
|
201
|
+
* It is entered whenever the query has a remainder ≥ W and returns early when
|
|
202
|
+
* there is nothing to bridge (`containsSpan`, a lone root, an empty pass), so
|
|
203
|
+
* the call and the fact are different things and only the fact is counted.
|
|
204
|
+
* Its own rationale step reports the fusion; this is the untraced view, and
|
|
205
|
+
* its cost is one bridging edge: `fuseRuns · STEP`. */
|
|
206
|
+
fuseRuns = 0;
|
|
207
|
+
/** Steps the post-grounding EXTENSION took — pivots plus forward-absorbs.
|
|
208
|
+
* `pivotSteps` counts only the former, so before this the extension's COST was
|
|
209
|
+
* not computable at all. With it, the price of extending the answer is
|
|
210
|
+
* `reasonSteps · STEP`, the ladder's own value for following an edge. */
|
|
211
|
+
reasonSteps = 0;
|
|
212
|
+
/** Bytes of the grounding's UNCOVERED material the extension was justified by
|
|
213
|
+
* — the union of the spans each step carried a `W`-window of. The gate
|
|
214
|
+
* already computed WHICH span carried it per step and kept only a boolean;
|
|
215
|
+
* this is that fact, accumulated. Read with {@link reasonSteps}: one is the
|
|
216
|
+
* price, the other the explanation. */
|
|
217
|
+
reasonCarriedBytes = 0;
|
|
218
|
+
/** Bytes of the question's REMAINDER a step CONSUMED — the drop the law's own
|
|
219
|
+
* `advance` makes when a declared move carries the material it accounts for.
|
|
220
|
+
* Read with {@link reasonSteps} and {@link reasonCarriedBytes}: carrying is
|
|
221
|
+
* the engagement, this is the consumption, and before it the second was
|
|
222
|
+
* invisible. */
|
|
223
|
+
closureDrainedBytes = 0;
|
|
224
|
+
/** Bytes of the question the grounding PRICED but whose material its answer does
|
|
225
|
+
* NOT carry, at or above one quantum — the debt the construction leaves for the
|
|
226
|
+
* walk to pay by carrying it. Zero means the grounding's coverage is honest:
|
|
227
|
+
* everything it priced is either held by the answer or under the W floor. */
|
|
228
|
+
groundingWithheldBytes = 0;
|
|
229
|
+
/** Branch-node probes the pivot sweep actually spent looking for the learnt
|
|
230
|
+
* context an answer contains (one `resonate` per probe). The untraced view
|
|
231
|
+
* of what the multi-hop's shortlist costs. */
|
|
232
|
+
pivotProbes = 0;
|
|
233
|
+
/** Branch nodes the pivot's probe cap withheld (`branchCount − probeCap`, over
|
|
234
|
+
* every call). A capacity fact, not a verdict: the sweep is breadth-first,
|
|
235
|
+
* so the probes it DOES spend are the largest regions, and recognition still
|
|
236
|
+
* contributes every exact containment candidate regardless of the budget.
|
|
237
|
+
* Read it with {@link pivotProbes} — one says the work, the other the
|
|
238
|
+
* shortfall. */
|
|
239
|
+
pivotBranchesUnprobed = 0;
|
|
178
240
|
// ── Mind: the cover's connector assembly (LIMIT) ────────────────────────
|
|
179
241
|
//
|
|
180
242
|
// The cover's `run` is 91% of a hub query's time (`"Hello."`: 2.7 s of 3.0 s)
|
|
@@ -96,7 +96,7 @@ export async function articulate(ctx, answer, query) {
|
|
|
96
96
|
s.end,
|
|
97
97
|
])),
|
|
98
98
|
]);
|
|
99
|
-
const solved = ctx.search.cover(answer.length, voicedSites, new Map(), ans.leaves, ans.splits,
|
|
99
|
+
const solved = ctx.search.cover(answer.length, voicedSites, new Map(), ans.leaves, ans.splits, substitutions, undefined, undefined, ctx.trace ? (steps) => traceDerivation(ctx, steps) : undefined);
|
|
100
100
|
const segs = solved && solved.segs;
|
|
101
101
|
tArtCover?.done(segs === null
|
|
102
102
|
? []
|