@hviana/sema 0.5.2 → 0.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +115 -53
- package/HOW_IT_WORKS.md +291 -184
- package/jsr.json +6 -0
- package/package.json +1 -1
- package/src/mind/bridge.ts +10 -104
- package/src/mind/match.ts +497 -7
- package/src/mind/{prefix-completion.ts → mechanisms/prefix-completion.ts} +66 -92
- package/src/mind/mechanisms/recall.ts +38 -129
- package/src/mind/mechanisms/reference.ts +343 -0
- package/src/mind/mind.ts +12 -8
- package/src/mind/pipeline-mechanism.ts +120 -3
- package/src/mind/pipeline.ts +16 -2
- package/src/mind/traverse.ts +92 -1
- package/src/store.ts +13 -4
- package/test/33-multi-candidate.test.mjs +21 -11
- package/test/70-prefix-completion.test.mjs +1 -1
- package/test/72-prefix-candidate-supply.test.mjs +7 -9
- package/test/74-prefix-trap-not-sprung-early.test.mjs +1 -1
- package/test/76-reference-binding.test.mjs +543 -0
- package/dist/example/demo.d.ts +0 -1
- package/dist/example/demo.js +0 -39
- package/dist/example/train_base.d.ts +0 -93
- package/dist/example/train_base.js +0 -2269
- package/dist/src/alphabet.d.ts +0 -7
- package/dist/src/alphabet.js +0 -33
- package/dist/src/alu/src/alu.d.ts +0 -185
- package/dist/src/alu/src/alu.js +0 -440
- package/dist/src/alu/src/expr.d.ts +0 -61
- package/dist/src/alu/src/expr.js +0 -318
- package/dist/src/alu/src/index.d.ts +0 -11
- package/dist/src/alu/src/index.js +0 -19
- package/dist/src/alu/src/kernel-arith.d.ts +0 -16
- package/dist/src/alu/src/kernel-arith.js +0 -264
- package/dist/src/alu/src/kernel-bits.d.ts +0 -19
- package/dist/src/alu/src/kernel-bits.js +0 -152
- package/dist/src/alu/src/kernel-logic.d.ts +0 -4
- package/dist/src/alu/src/kernel-logic.js +0 -60
- package/dist/src/alu/src/kernel-nd.d.ts +0 -3
- package/dist/src/alu/src/kernel-nd.js +0 -208
- package/dist/src/alu/src/kernel-numeric.d.ts +0 -54
- package/dist/src/alu/src/kernel-numeric.js +0 -366
- package/dist/src/alu/src/operation.d.ts +0 -168
- package/dist/src/alu/src/operation.js +0 -189
- package/dist/src/alu/src/parser.d.ts +0 -221
- package/dist/src/alu/src/parser.js +0 -577
- package/dist/src/alu/src/resonance.d.ts +0 -55
- package/dist/src/alu/src/resonance.js +0 -126
- package/dist/src/alu/src/text.d.ts +0 -31
- package/dist/src/alu/src/text.js +0 -73
- package/dist/src/alu/src/value.d.ts +0 -109
- package/dist/src/alu/src/value.js +0 -300
- package/dist/src/alu/test/alu.test.d.ts +0 -1
- package/dist/src/alu/test/alu.test.js +0 -764
- package/dist/src/bytes.d.ts +0 -14
- package/dist/src/bytes.js +0 -59
- package/dist/src/canon.d.ts +0 -45
- package/dist/src/canon.js +0 -85
- package/dist/src/config.d.ts +0 -111
- package/dist/src/config.js +0 -91
- package/dist/src/derive/src/deduction.d.ts +0 -136
- package/dist/src/derive/src/deduction.js +0 -159
- package/dist/src/derive/src/index.d.ts +0 -8
- package/dist/src/derive/src/index.js +0 -11
- package/dist/src/derive/src/priority-queue.d.ts +0 -20
- package/dist/src/derive/src/priority-queue.js +0 -73
- package/dist/src/derive/src/rewrite.d.ts +0 -56
- package/dist/src/derive/src/rewrite.js +0 -100
- package/dist/src/derive/src/trie.d.ts +0 -90
- package/dist/src/derive/src/trie.js +0 -217
- package/dist/src/derive/test/derive.test.d.ts +0 -1
- package/dist/src/derive/test/derive.test.js +0 -122
- package/dist/src/extension.d.ts +0 -37
- package/dist/src/extension.js +0 -7
- package/dist/src/geometry.d.ts +0 -233
- package/dist/src/geometry.js +0 -1089
- package/dist/src/index.d.ts +0 -17
- package/dist/src/index.js +0 -19
- package/dist/src/ingest-cache.d.ts +0 -41
- package/dist/src/ingest-cache.js +0 -165
- package/dist/src/meter.d.ts +0 -176
- package/dist/src/meter.js +0 -274
- package/dist/src/mind/articulation.d.ts +0 -6
- package/dist/src/mind/articulation.js +0 -99
- package/dist/src/mind/attention.d.ts +0 -430
- package/dist/src/mind/attention.js +0 -2418
- package/dist/src/mind/bridge.d.ts +0 -39
- package/dist/src/mind/bridge.js +0 -998
- package/dist/src/mind/canonical.d.ts +0 -34
- package/dist/src/mind/canonical.js +0 -93
- package/dist/src/mind/frame-filler.d.ts +0 -15
- package/dist/src/mind/frame-filler.js +0 -535
- package/dist/src/mind/graph-search.d.ts +0 -294
- package/dist/src/mind/graph-search.js +0 -996
- package/dist/src/mind/index.d.ts +0 -9
- package/dist/src/mind/index.js +0 -5
- package/dist/src/mind/junction.d.ts +0 -137
- package/dist/src/mind/junction.js +0 -358
- package/dist/src/mind/learning.d.ts +0 -75
- package/dist/src/mind/learning.js +0 -265
- package/dist/src/mind/match.d.ts +0 -192
- package/dist/src/mind/match.js +0 -666
- package/dist/src/mind/mechanisms/alu.d.ts +0 -4
- package/dist/src/mind/mechanisms/alu.js +0 -36
- package/dist/src/mind/mechanisms/cast.d.ts +0 -89
- package/dist/src/mind/mechanisms/cast.js +0 -1186
- package/dist/src/mind/mechanisms/confluence.d.ts +0 -24
- package/dist/src/mind/mechanisms/confluence.js +0 -271
- package/dist/src/mind/mechanisms/cover.d.ts +0 -6
- package/dist/src/mind/mechanisms/cover.js +0 -232
- package/dist/src/mind/mechanisms/extraction.d.ts +0 -33
- package/dist/src/mind/mechanisms/extraction.js +0 -327
- package/dist/src/mind/mechanisms/recall.d.ts +0 -16
- package/dist/src/mind/mechanisms/recall.js +0 -558
- package/dist/src/mind/mind.d.ts +0 -386
- package/dist/src/mind/mind.js +0 -754
- package/dist/src/mind/pipeline-mechanism.d.ts +0 -183
- package/dist/src/mind/pipeline-mechanism.js +0 -521
- package/dist/src/mind/pipeline.d.ts +0 -49
- package/dist/src/mind/pipeline.js +0 -331
- package/dist/src/mind/prefix-completion.d.ts +0 -59
- package/dist/src/mind/prefix-completion.js +0 -270
- package/dist/src/mind/primitives.d.ts +0 -85
- package/dist/src/mind/primitives.js +0 -333
- package/dist/src/mind/rationale.d.ts +0 -139
- package/dist/src/mind/rationale.js +0 -163
- package/dist/src/mind/reasoning.d.ts +0 -42
- package/dist/src/mind/reasoning.js +0 -305
- package/dist/src/mind/recognition.d.ts +0 -20
- package/dist/src/mind/recognition.js +0 -696
- package/dist/src/mind/resonance.d.ts +0 -35
- package/dist/src/mind/resonance.js +0 -365
- package/dist/src/mind/trace.d.ts +0 -15
- package/dist/src/mind/trace.js +0 -73
- package/dist/src/mind/traverse.d.ts +0 -158
- package/dist/src/mind/traverse.js +0 -716
- package/dist/src/mind/types.d.ts +0 -418
- package/dist/src/mind/types.js +0 -179
- package/dist/src/rabitq-ivf/src/database.d.ts +0 -113
- package/dist/src/rabitq-ivf/src/database.js +0 -201
- package/dist/src/rabitq-ivf/src/index.d.ts +0 -7
- package/dist/src/rabitq-ivf/src/index.js +0 -4
- package/dist/src/rabitq-ivf/src/ivf.d.ts +0 -200
- package/dist/src/rabitq-ivf/src/ivf.js +0 -1165
- package/dist/src/rabitq-ivf/src/prng.d.ts +0 -19
- package/dist/src/rabitq-ivf/src/prng.js +0 -36
- package/dist/src/rabitq-ivf/src/rabitq.d.ts +0 -95
- package/dist/src/rabitq-ivf/src/rabitq.js +0 -313
- package/dist/src/sema.d.ts +0 -41
- package/dist/src/sema.js +0 -77
- package/dist/src/store-sqlite.d.ts +0 -184
- package/dist/src/store-sqlite.js +0 -942
- package/dist/src/store.d.ts +0 -762
- package/dist/src/store.js +0 -1823
- package/dist/src/vec.d.ts +0 -31
- package/dist/src/vec.js +0 -109
- package/src/mind/frame-filler.ts +0 -604
- package/test/69-frame-filler.test.mjs +0 -115
package/src/mind/traverse.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
import { cosine, Vec } from "../vec.js";
|
|
10
10
|
import type { AncestorReach, MindContext, SaturationStop } from "./types.js";
|
|
11
11
|
import { gistOf, read } from "./primitives.js";
|
|
12
|
-
import { leafIdRun } from "./canonical.js";
|
|
12
|
+
import { canonicalWindows, leafIdPrefix, leafIdRun } from "./canonical.js";
|
|
13
13
|
|
|
14
14
|
// ── Session structural memo ─────────────────────────────────────────────
|
|
15
15
|
//
|
|
@@ -836,3 +836,94 @@ export function allWindowsAreScaffolding(
|
|
|
836
836
|
}
|
|
837
837
|
return sawOne;
|
|
838
838
|
}
|
|
839
|
+
|
|
840
|
+
// ── THE PREFIX SUPPLY ───────────────────────────────────────────────────────
|
|
841
|
+
//
|
|
842
|
+
// A RETRIEVAL capability, not a grounding one: "which trained forms does this
|
|
843
|
+
// byte run OPEN?" It lived inside a recall tier, which is the wrong altitude
|
|
844
|
+
// — it reads the write side's own leaf-id window index and answers a question
|
|
845
|
+
// about the STORE, so any mechanism may ask it.
|
|
846
|
+
|
|
847
|
+
/** Trained forms the query may OPEN, proposed from the write side's own
|
|
848
|
+
* leaf-id window index — the supply of last resort for prefix completion.
|
|
849
|
+
*
|
|
850
|
+
* WHY A SECOND SUPPLY EXISTS. The ranked list prefix completion normally reads
|
|
851
|
+
* is a resonance list, and resonance cannot rank a proper prefix: measured on
|
|
852
|
+
* the trained store, cos(prefix, form) falls from 0.9629 at a one-byte
|
|
853
|
+
* truncation to 0.6206 at three bytes, against a reachThreshold of 0.8750.
|
|
854
|
+
* Three bytes of truncation put the answer out of reach on GEOMETRY, not on a
|
|
855
|
+
* bug, so no k and no re-ranking recovers it.
|
|
856
|
+
*
|
|
857
|
+
* WHY THIS ROUTE WORKS WHERE THE FOLD DOES NOT. A query's own fold is
|
|
858
|
+
* useless here: content addressing is not phrase-position-invariant, so a
|
|
859
|
+
* standalone prefix folds to a DIFFERENT node than the same bytes sitting
|
|
860
|
+
* inside a longer deposit, and neither the prefix's own node nor its
|
|
861
|
+
* ancestors lead to the deposit (measured: the 22-byte prefix of the
|
|
862
|
+
* photosynthesis form resolves, is shared by 6 contexts, and does not have
|
|
863
|
+
* the form among its ancestors). Leaf ids ARE position-invariant — they are
|
|
864
|
+
* content-addressed on single bytes — and `indexSubSpans` already interns a
|
|
865
|
+
* flat branch over every canonical WINDOW of a deposit's leaf-id stream, with
|
|
866
|
+
* containment edges to the chunks that window spans. A query that is a
|
|
867
|
+
* prefix therefore shares those window nodes exactly, and reaches the deposit
|
|
868
|
+
* by climbing containment then parents. Nothing is added to the write side;
|
|
869
|
+
* this reads an index training already built.
|
|
870
|
+
*
|
|
871
|
+
* BOUNDED (§2.8), AND WITH NO NEW THRESHOLD. The window whose containment is
|
|
872
|
+
* SMALLEST carries the most evidence, and one saturated at `hubBound` carries
|
|
873
|
+
* none — that is the same √N reading of "hub" the rest of the mind uses, not
|
|
874
|
+
* a tuned knob. The upward walk spends a budget of `hubBound` nodes and
|
|
875
|
+
* fans out by W, so a hub query enumerates nothing and the caller stays
|
|
876
|
+
* silent rather than guessing (§2.13). Measured on the trained store: the
|
|
877
|
+
* photosynthesis form at a one-byte truncation picks a window with 52
|
|
878
|
+
* containers, visits 446 nodes, and yields exactly ONE candidate that
|
|
879
|
+
* survives the caller's byte compare — the form itself.
|
|
880
|
+
*
|
|
881
|
+
* These are PROPOSALS only. Every candidate still faces the byte-exact
|
|
882
|
+
* prefix compare and all three guards below, so a wrong proposal costs one
|
|
883
|
+
* bounded read and can never be voiced (§2.3). */
|
|
884
|
+
export function formsOpenedBy(
|
|
885
|
+
ctx: MindContext,
|
|
886
|
+
query: Uint8Array,
|
|
887
|
+
): number[] {
|
|
888
|
+
const store = ctx.store;
|
|
889
|
+
const W = ctx.space.maxGroup;
|
|
890
|
+
const run = leafIdPrefix(ctx, query);
|
|
891
|
+
// The widest canonical window is the most discriminative one the write side
|
|
892
|
+
// ever interned; a query too short to spell one carries no window evidence.
|
|
893
|
+
const len = canonicalWindows(W)[1];
|
|
894
|
+
if (run.length < len) return [];
|
|
895
|
+
const bound = hubBound(ctx);
|
|
896
|
+
|
|
897
|
+
let best: number | null = null;
|
|
898
|
+
let bestN = 0;
|
|
899
|
+
for (let off = 0; off + len <= run.length; off++) {
|
|
900
|
+
const wid = store.findBranch(run.slice(off, off + len));
|
|
901
|
+
if (wid === null) continue;
|
|
902
|
+
const n = store.containersSlice(wid, 0, bound).length;
|
|
903
|
+
// Empty says the window spans no chunk; saturated says it is a hub, whose
|
|
904
|
+
// containment discriminates nothing. Neither is evidence.
|
|
905
|
+
if (n === 0 || n >= bound) continue;
|
|
906
|
+
if (best === null || n < bestN) {
|
|
907
|
+
best = wid;
|
|
908
|
+
bestN = n;
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
if (best === null) return [];
|
|
912
|
+
|
|
913
|
+
let frontier = store.containersSlice(best, 0, bound);
|
|
914
|
+
const seen = new Set<number>(frontier);
|
|
915
|
+
let budget = bound;
|
|
916
|
+
while (frontier.length > 0 && budget > 0) {
|
|
917
|
+
const next: number[] = [];
|
|
918
|
+
for (const f of frontier) {
|
|
919
|
+
if (budget-- <= 0) break;
|
|
920
|
+
for (const p of store.parentsFirst(f, W)) {
|
|
921
|
+
if (seen.has(p)) continue;
|
|
922
|
+
seen.add(p);
|
|
923
|
+
next.push(p);
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
frontier = next;
|
|
927
|
+
}
|
|
928
|
+
return [...seen];
|
|
929
|
+
}
|
package/src/store.ts
CHANGED
|
@@ -970,16 +970,25 @@ export abstract class AbstractStore implements Store {
|
|
|
970
970
|
/** Content (gist) index write buffer. */
|
|
971
971
|
protected _contentBuffer: Array<{ id: NodeId; vector: Float32Array }> = [];
|
|
972
972
|
/** Halo index write buffer — keyed by id so repeats within a batch coalesce. */
|
|
973
|
-
protected _haloBuffer
|
|
973
|
+
protected _haloBuffer: Map<NodeId, Float32Array> = new Map<
|
|
974
|
+
NodeId,
|
|
975
|
+
Float32Array
|
|
976
|
+
>();
|
|
974
977
|
/** Containment write buffer: child → new parents, merged on flush cadence. */
|
|
975
|
-
protected _containBuf
|
|
978
|
+
protected _containBuf: Map<NodeId, Set<NodeId>> = new Map<
|
|
979
|
+
NodeId,
|
|
980
|
+
Set<NodeId>
|
|
981
|
+
>();
|
|
976
982
|
|
|
977
983
|
/** Dedup-target candidates still in the write buffer (keyed by id). Only
|
|
978
984
|
* roots that have gained an edge/halo are targets; a fresh intermediate
|
|
979
985
|
* branch is never folded onto. */
|
|
980
|
-
protected _nearDedupBuf
|
|
986
|
+
protected _nearDedupBuf: Map<NodeId, Float32Array> = new Map<
|
|
987
|
+
NodeId,
|
|
988
|
+
Float32Array
|
|
989
|
+
>();
|
|
981
990
|
/** Ids currently in `_contentBuffer` (not yet flushed) — O(1) membership. */
|
|
982
|
-
protected _bufferedIds = new Set<NodeId>();
|
|
991
|
+
protected _bufferedIds: Set<NodeId> = new Set<NodeId>();
|
|
983
992
|
|
|
984
993
|
// ── Transparent-chain cache ────────────────────────────────────────────
|
|
985
994
|
|
|
@@ -171,18 +171,28 @@ test("3 — a near-tie between the winner and runner-up emits narrowDecision", a
|
|
|
171
171
|
["water is frigid so water is freezing", "freezing"],
|
|
172
172
|
]);
|
|
173
173
|
// The near-tie has to be REAL: two candidates whose accounted spans are the
|
|
174
|
-
// same, separated by a single move. `
|
|
175
|
-
// extraction and recall both explain the
|
|
176
|
-
//
|
|
174
|
+
// same, separated by a single move. `water is hard so water is ???` is that
|
|
175
|
+
// — extraction and recall both explain the same span (grades 25011 and
|
|
176
|
+
// 25010, margin 1).
|
|
177
177
|
//
|
|
178
|
-
//
|
|
179
|
-
//
|
|
180
|
-
//
|
|
181
|
-
//
|
|
182
|
-
//
|
|
183
|
-
//
|
|
184
|
-
//
|
|
185
|
-
|
|
178
|
+
// THIS FIXTURE HAS NOW BEEN REPLACED TWICE, BOTH TIMES FOR THE SAME REASON:
|
|
179
|
+
// a mechanism that genuinely explains the query started firing, and a
|
|
180
|
+
// decisive win is the opposite of what this test pins.
|
|
181
|
+
//
|
|
182
|
+
// * `steel is frigid so steel is ???` was a near-tie only while CAST could
|
|
183
|
+
// not fire on it — CAST's subject gate used to reject any point whose
|
|
184
|
+
// alignment continued PAST the seat, which that fixture's recurrence
|
|
185
|
+
// guarantees. With CAST firing it wins by 22008.
|
|
186
|
+
// * `steel is hard so steel is` was a near-tie only while prefix
|
|
187
|
+
// completion was a buried recall TIER. As a market mechanism it grounds
|
|
188
|
+
// that query for what it is — the literal opening of exactly one trained
|
|
189
|
+
// form — at grade 1 against 21010, and answers `steel is hard so steel
|
|
190
|
+
// is strong`. That is a better answer, not a regression.
|
|
191
|
+
//
|
|
192
|
+
// The lesson for whoever re-fixtures this next: pick a query no mechanism can
|
|
193
|
+
// explain OUTRIGHT. A trailing `???` is what keeps this one honest — it is
|
|
194
|
+
// not the prefix of anything trained.
|
|
195
|
+
const { steps } = await trace(m, "water is hard so water is ???");
|
|
186
196
|
const narrow = stepsNamed(steps, "narrowDecision");
|
|
187
197
|
assert.equal(narrow.length, 1, "expected exactly one narrowDecision step");
|
|
188
198
|
assert.ok(/margin \d+ grade-unit/.test(narrow[0].note), narrow[0].note);
|
|
@@ -36,7 +36,7 @@ import { test } from "node:test";
|
|
|
36
36
|
import assert from "node:assert/strict";
|
|
37
37
|
import { Mind } from "../dist/src/index.js";
|
|
38
38
|
import { SQliteStore } from "../dist/src/store-sqlite.js";
|
|
39
|
-
import { prefixCompletion } from "../dist/src/mind/prefix-completion.js";
|
|
39
|
+
import { prefixCompletion } from "../dist/src/mind/mechanisms/prefix-completion.js";
|
|
40
40
|
|
|
41
41
|
const enc = (s) => new TextEncoder().encode(s);
|
|
42
42
|
const dec = new TextDecoder();
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// 0.9629 at a one-byte truncation to 0.6206 at three bytes, against a
|
|
9
9
|
// reachThreshold of 0.8750. The mechanism's guards were therefore never
|
|
10
10
|
// reached — the trace read `candidates: 24, opened: 0` — and the query answered
|
|
11
|
-
// nothing. `
|
|
11
|
+
// nothing. `formsOpenedBy` is the second SUPPLY that closes it, reading the
|
|
12
12
|
// leaf-id WINDOW index `indexSubSpans` already writes at deposit time. No
|
|
13
13
|
// ingestion, storage or fold change is involved: this test would pass on a
|
|
14
14
|
// store trained before the supply existed.
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
// WHY THE ASSERTIONS ARE SHAPED THIS WAY. On a small fixture resonance may
|
|
17
17
|
// well return the form by luck, and then an end-to-end "does it answer?" test
|
|
18
18
|
// would pass with the supply deleted — pinning nothing. So the contract is
|
|
19
|
-
// asserted on `
|
|
19
|
+
// asserted on `formsOpenedBy` DIRECTLY, and the resonance list is asserted
|
|
20
20
|
// to lack the form, which is what makes the supply load-bearing rather than
|
|
21
21
|
// redundant.
|
|
22
22
|
//
|
|
@@ -27,10 +27,8 @@ import { test } from "node:test";
|
|
|
27
27
|
import assert from "node:assert/strict";
|
|
28
28
|
import { Mind } from "../dist/src/index.js";
|
|
29
29
|
import { SQliteStore } from "../dist/src/store-sqlite.js";
|
|
30
|
-
import {
|
|
31
|
-
|
|
32
|
-
prefixCompletion,
|
|
33
|
-
} from "../dist/src/mind/prefix-completion.js";
|
|
30
|
+
import { prefixCompletion } from "../dist/src/mind/mechanisms/prefix-completion.js";
|
|
31
|
+
import { formsOpenedBy } from "../dist/src/mind/traverse.js";
|
|
34
32
|
import { gistOf, resolve } from "../dist/src/mind/primitives.js";
|
|
35
33
|
|
|
36
34
|
const enc = (s) => new TextEncoder().encode(s);
|
|
@@ -71,7 +69,7 @@ test("a proper prefix reaches its trained form through the window supply", async
|
|
|
71
69
|
// prefix is a LARGE-CORPUS property — cos falls to 0.6206 at a three-byte
|
|
72
70
|
// truncation against a 0.8750 bar, on a 15.7M-node store — and cannot be
|
|
73
71
|
// reproduced at this scale. That is why the contract below is asserted on
|
|
74
|
-
// `
|
|
72
|
+
// `formsOpenedBy` DIRECTLY: deleting or emptying the supply fails this
|
|
75
73
|
// test regardless of what resonance happens to return.
|
|
76
74
|
const ranked = (await m.store.resonate(gistOf(m, query), 64)).map((h) =>
|
|
77
75
|
h.id
|
|
@@ -84,7 +82,7 @@ test("a proper prefix reaches its trained form through the window supply", async
|
|
|
84
82
|
);
|
|
85
83
|
|
|
86
84
|
// THE CONTRACT — the write side's own window index proposes the form.
|
|
87
|
-
const proposed =
|
|
85
|
+
const proposed = formsOpenedBy(m, query);
|
|
88
86
|
assert.ok(
|
|
89
87
|
proposed.includes(formId),
|
|
90
88
|
`the window supply must propose the trained form the query opens ` +
|
|
@@ -105,7 +103,7 @@ test("a proper prefix reaches its trained form through the window supply", async
|
|
|
105
103
|
// supply that widened until it found something would be the real defect.
|
|
106
104
|
const hub = enc("The ");
|
|
107
105
|
assert.equal(
|
|
108
|
-
prefixCompletion(m, hub,
|
|
106
|
+
prefixCompletion(m, hub, formsOpenedBy(m, hub)),
|
|
109
107
|
null,
|
|
110
108
|
"a query carrying no discriminative window must stay silent",
|
|
111
109
|
);
|
|
@@ -31,7 +31,7 @@ import { test } from "node:test";
|
|
|
31
31
|
import assert from "node:assert/strict";
|
|
32
32
|
import { Mind } from "../dist/src/index.js";
|
|
33
33
|
import { SQliteStore } from "../dist/src/store-sqlite.js";
|
|
34
|
-
import { prefixCompletion } from "../dist/src/mind/prefix-completion.js";
|
|
34
|
+
import { prefixCompletion } from "../dist/src/mind/mechanisms/prefix-completion.js";
|
|
35
35
|
import { resolve } from "../dist/src/mind/primitives.js";
|
|
36
36
|
|
|
37
37
|
const enc = (s) => new TextEncoder().encode(s);
|