@hviana/sema 0.5.3 → 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 +6 -6
- package/HOW_IT_WORKS.md +16 -0
- package/jsr.json +1 -1
- package/package.json +1 -1
- package/src/mind/match.ts +81 -0
- package/src/mind/mechanisms/recall.ts +29 -3
- package/test/76-reference-binding.test.mjs +72 -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 -37
- package/dist/src/mind/bridge.js +0 -907
- package/dist/src/mind/canonical.d.ts +0 -34
- package/dist/src/mind/canonical.js +0 -93
- 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 -351
- package/dist/src/mind/match.js +0 -959
- 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/prefix-completion.d.ts +0 -22
- package/dist/src/mind/mechanisms/prefix-completion.js +0 -243
- package/dist/src/mind/mechanisms/recall.d.ts +0 -16
- package/dist/src/mind/mechanisms/recall.js +0 -460
- package/dist/src/mind/mechanisms/reference.d.ts +0 -6
- package/dist/src/mind/mechanisms/reference.js +0 -296
- 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 -238
- package/dist/src/mind/pipeline-mechanism.js +0 -622
- package/dist/src/mind/pipeline.d.ts +0 -49
- package/dist/src/mind/pipeline.js +0 -343
- 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 -196
- package/dist/src/mind/traverse.js +0 -806
- 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
|
@@ -1,265 +0,0 @@
|
|
|
1
|
-
// learning.ts — ingest and deposition (Section 7 of the mind).
|
|
2
|
-
//
|
|
3
|
-
// Learning is DEPOSITION: perceive a stream into a tree and intern every
|
|
4
|
-
// node. A fact is an EDGE between node ids; recall traverses edges.
|
|
5
|
-
import { bindSeat, companySignature, isChunk } from "../sema.js";
|
|
6
|
-
import { changedNodes } from "./types.js";
|
|
7
|
-
import { inputBytes, perceiveDeposit, resolve, } from "./primitives.js";
|
|
8
|
-
import { canonicalWindows, leafIdPrefix } from "./canonical.js";
|
|
9
|
-
import { fold as foldVecs } from "../sema.js";
|
|
10
|
-
/** Intern a perceived tree into node ids, bottom-up, sharing equal subtrees.
|
|
11
|
-
* Returns the root node id and a map from tree nodes to their ids.
|
|
12
|
-
*
|
|
13
|
-
* Memoized by NODE IDENTITY (ctx._internIds): the pyramid fold shares a
|
|
14
|
-
* prefix's subtree OBJECTS across an accumulated context's deposits, and a
|
|
15
|
-
* node already interned needs nothing again — its id is permanent
|
|
16
|
-
* (content-addressed) and its intern-time side effects (gist capture, kid
|
|
17
|
-
* rows) fired at first mint; re-interning was pure lookups. A memo hit
|
|
18
|
-
* therefore skips the WHOLE shared subtree, making the intern walk
|
|
19
|
-
* O(new nodes) per deposit instead of O(context). Only the hit node
|
|
20
|
-
* itself enters `ids`; descendants stay reachable via the memo (see
|
|
21
|
-
* idOf in indexSubSpans and the changedNodes prune). */
|
|
22
|
-
export async function internTreeIds(ctx, node, ids) {
|
|
23
|
-
const known = ctx._internIds.get(node);
|
|
24
|
-
if (known !== undefined) {
|
|
25
|
-
ids.set(node, known);
|
|
26
|
-
return known;
|
|
27
|
-
}
|
|
28
|
-
let id;
|
|
29
|
-
if (node.kids === null) {
|
|
30
|
-
id = await ctx.store.putLeaf(node.leaf ?? new Uint8Array(0), node.v);
|
|
31
|
-
}
|
|
32
|
-
else {
|
|
33
|
-
const kds = [];
|
|
34
|
-
for (const k of node.kids)
|
|
35
|
-
kds.push(await internTreeIds(ctx, k, ids));
|
|
36
|
-
id = await ctx.store.putBranch(kds, node.v);
|
|
37
|
-
}
|
|
38
|
-
ids.set(node, id);
|
|
39
|
-
ctx._internIds.set(node, id);
|
|
40
|
-
return id;
|
|
41
|
-
}
|
|
42
|
-
/** Index flat branches for sub-spans of a deposit's byte stream, linked to
|
|
43
|
-
* their structural chunks via durable CONTAINMENT edges. */
|
|
44
|
-
export async function indexSubSpans(ctx, tree, ids) {
|
|
45
|
-
const chunkOf = [];
|
|
46
|
-
const streamIds = [];
|
|
47
|
-
const streamVecs = [];
|
|
48
|
-
const collect = (n) => {
|
|
49
|
-
if (isChunk(n)) {
|
|
50
|
-
// A chunk inside a memo-skipped shared subtree is absent from `ids`;
|
|
51
|
-
// the intern memo still knows it (same object). A miss on both (the
|
|
52
|
-
// WeakMap entry was collected) only forfeits the seenBefore skip.
|
|
53
|
-
const chunkId = ids.get(n) ?? ctx._internIds.get(n);
|
|
54
|
-
for (const k of n.kids) {
|
|
55
|
-
const lid = k.leaf ? ctx.store.findLeaf(k.leaf) : null;
|
|
56
|
-
if (lid === null)
|
|
57
|
-
return false;
|
|
58
|
-
streamIds.push(lid);
|
|
59
|
-
streamVecs.push(k.v);
|
|
60
|
-
chunkOf.push(chunkId);
|
|
61
|
-
}
|
|
62
|
-
return true;
|
|
63
|
-
}
|
|
64
|
-
if (n.kids) {
|
|
65
|
-
for (const k of n.kids)
|
|
66
|
-
if (!collect(k))
|
|
67
|
-
return false;
|
|
68
|
-
}
|
|
69
|
-
return true;
|
|
70
|
-
};
|
|
71
|
-
if (!collect(tree))
|
|
72
|
-
return false;
|
|
73
|
-
const W = ctx.space.maxGroup; // write side of the canonical contract
|
|
74
|
-
const prev = ctx._prevSeen;
|
|
75
|
-
const seenBefore = (off, len) => {
|
|
76
|
-
if (!prev)
|
|
77
|
-
return false;
|
|
78
|
-
for (let i = off; i < off + len; i++) {
|
|
79
|
-
const c = chunkOf[i];
|
|
80
|
-
if (c === undefined || !prev.has(c))
|
|
81
|
-
return false;
|
|
82
|
-
}
|
|
83
|
-
return true;
|
|
84
|
-
};
|
|
85
|
-
const lens = streamIds.length >= W ? canonicalWindows(W) : [streamIds.length];
|
|
86
|
-
for (const len of lens) {
|
|
87
|
-
if (len < 1)
|
|
88
|
-
continue;
|
|
89
|
-
for (let off = 0; off + len <= streamIds.length; off++) {
|
|
90
|
-
if (seenBefore(off, len))
|
|
91
|
-
continue;
|
|
92
|
-
const winIds = streamIds.slice(off, off + len);
|
|
93
|
-
const flatId = ctx.store.findBranch(winIds) ??
|
|
94
|
-
await ctx.store.putBranch(winIds, foldVecs(ctx.space, streamVecs.slice(off, off + len)));
|
|
95
|
-
for (let i = off; i < off + len; i++) {
|
|
96
|
-
const c = chunkOf[i];
|
|
97
|
-
if (c !== undefined)
|
|
98
|
-
ctx.store.addContainer(flatId, c);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
return true;
|
|
103
|
-
}
|
|
104
|
-
/** Perceive, intern, and index a single input. Returns the perceived tree,
|
|
105
|
-
* root id, id map, and the changed (new) subtrees for halo reinforcement. */
|
|
106
|
-
export async function deposit(ctx, input, track, conversational = false) {
|
|
107
|
-
const bytes = inputBytes(ctx, input);
|
|
108
|
-
// Deposit-shaped perception: stable-prefix tree SEEDING (see
|
|
109
|
-
// perceiveDeposit) — an accumulated context re-folds only its new suffix,
|
|
110
|
-
// O(turn) instead of O(context) per conversation turn. Cache-only here
|
|
111
|
-
// (no store-probe fallback): a knownPrefixLength scan on every novel fact
|
|
112
|
-
// would cost O(n²) hashing, while conversation replays are always warm —
|
|
113
|
-
// re-deposition replays from the first turn, rebuilding the cache as it
|
|
114
|
-
// goes. `conversational` scopes the STABLE-PREFIX variant (turn-boundary
|
|
115
|
-
// folding, matching query-time perception) to ingestPair's own growing
|
|
116
|
-
// context argument — a bare ingestOne deposit whose bytes merely happen
|
|
117
|
-
// to extend an earlier UNRELATED deposit (no conversational relationship)
|
|
118
|
-
// must keep the plain fold, or two coincidentally-prefix-sharing facts
|
|
119
|
-
// would stop sharing structure with each other.
|
|
120
|
-
const tree = perceiveDeposit(ctx, bytes, conversational);
|
|
121
|
-
const ids = new Map();
|
|
122
|
-
const rootId = await internTreeIds(ctx, tree, ids);
|
|
123
|
-
const indexed = await indexSubSpans(ctx, tree, ids);
|
|
124
|
-
const leafIds = leafIdPrefix(ctx, bytes);
|
|
125
|
-
if (leafIds.length === bytes.length && leafIds.length >= 2) {
|
|
126
|
-
await ctx.store.putBranch(leafIds, tree.v);
|
|
127
|
-
}
|
|
128
|
-
const changed = (track && ctx._prevSeen)
|
|
129
|
-
? changedNodes(tree, ids, ctx._prevSeen)
|
|
130
|
-
: [tree];
|
|
131
|
-
if (track)
|
|
132
|
-
ctx._prevSeen = indexed ? new Set(ids.values()) : null;
|
|
133
|
-
return { tree, rootId, ids, changed };
|
|
134
|
-
}
|
|
135
|
-
/** Ingest a single input (a bare experience, no continuation). */
|
|
136
|
-
export async function ingestOne(ctx, input) {
|
|
137
|
-
const { tree, rootId, ids } = await deposit(ctx, input, true);
|
|
138
|
-
ctx.store.indexTarget(rootId);
|
|
139
|
-
const parts = tree.kids
|
|
140
|
-
? tree.kids.map((k) => ids.get(k))
|
|
141
|
-
: [rootId];
|
|
142
|
-
const stride = ctx.space.maxGroup;
|
|
143
|
-
if (parts.length > stride) {
|
|
144
|
-
for (let i = 0; i + stride < parts.length; i += stride) {
|
|
145
|
-
await ctx.store.link(parts[i], parts[i + stride]);
|
|
146
|
-
}
|
|
147
|
-
if ((parts.length - 1) % stride !== 0) {
|
|
148
|
-
const lastStart = Math.floor((parts.length - 1) / stride) * stride;
|
|
149
|
-
if (lastStart < parts.length - 1) {
|
|
150
|
-
await ctx.store.link(parts[lastStart], parts[parts.length - 1]);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
else {
|
|
155
|
-
for (const id of parts)
|
|
156
|
-
ctx.store.indexTarget(id);
|
|
157
|
-
}
|
|
158
|
-
return Object.assign(tree, { id: rootId });
|
|
159
|
-
}
|
|
160
|
-
/** For each right-edge suffix of the context bytes, resolve it against the
|
|
161
|
-
* store. A suffix whose resolved node is already a known form inherits the
|
|
162
|
-
* continuation edge. Gate: ≥ 2 structural parents (reused across deposits),
|
|
163
|
-
* or (halo > 0 ∧ already an edge source). Pure answers do not qualify. */
|
|
164
|
-
async function propagateSuffixes(ctx, src, dst) {
|
|
165
|
-
const W = ctx.space.maxGroup;
|
|
166
|
-
const bytes = ctx.store.bytes(src);
|
|
167
|
-
const n = bytes.length;
|
|
168
|
-
if (n < 2 * W)
|
|
169
|
-
return;
|
|
170
|
-
// Existence prefilter — the write side of the canonical contract: every
|
|
171
|
-
// deposit interns its WHOLE byte stream as a flat branch of per-byte leaf
|
|
172
|
-
// ids (deposit(), canonical.ts). A suffix is a stored form exactly when
|
|
173
|
-
// that flat twin exists, so one content-hash probe per offset decides;
|
|
174
|
-
// only a hit pays for resolve()'s deposit-shaped perception. This keeps
|
|
175
|
-
// the scan free of river folds — O(1) probes over cheap byte hashes
|
|
176
|
-
// instead of O(suffix) vector folds per offset.
|
|
177
|
-
const leafIds = leafIdPrefix(ctx, bytes);
|
|
178
|
-
for (let i = 1; i <= n - W; i++) {
|
|
179
|
-
if (ctx.store.findBranch(leafIds.slice(i)) === null)
|
|
180
|
-
continue;
|
|
181
|
-
const id = resolve(ctx, bytes.subarray(i));
|
|
182
|
-
if (id === null || id === src)
|
|
183
|
-
continue;
|
|
184
|
-
const known = ctx.store.parentsFirst(id, 2).length >= 2 ||
|
|
185
|
-
(ctx.store.haloMass(id) > 0 && ctx.store.hasNext(id));
|
|
186
|
-
if (!known)
|
|
187
|
-
continue;
|
|
188
|
-
await ctx.store.link(id, dst);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
/** Ingest a pair (context, continuation) — learn an edge and pour halos.
|
|
192
|
-
* Returns the deposited root ids (context, continuation) — a pure
|
|
193
|
-
* read-out; callers that ignore it behave exactly as before. */
|
|
194
|
-
export async function ingestPair(ctx, ctxInput, cont) {
|
|
195
|
-
const c = await deposit(ctx, ctxInput, true, true);
|
|
196
|
-
const cont_ = await deposit(ctx, cont, false);
|
|
197
|
-
const ctxId = c.rootId, contId = cont_.rootId;
|
|
198
|
-
// NO CONTINUATION STAMP. A longer ctxInput reusing this one's folded
|
|
199
|
-
// segments needs no proof that it is "really" the next turn: the deposit
|
|
200
|
-
// fold imposes no boundaries, so reuse is bit-identical to refolding and a
|
|
201
|
-
// coincidental byte prefix gets the tree it would have got anyway. The
|
|
202
|
-
// stamp existed only to gate a boundary guess that no longer happens.
|
|
203
|
-
await ctx.store.link(ctxId, contId);
|
|
204
|
-
await propagateSuffixes(ctx, ctxId, contId);
|
|
205
|
-
// Halos pour company SIGNATURES (identity), not gists (content) — see
|
|
206
|
-
// companySignature in sema.ts.
|
|
207
|
-
const contSeat = bindSeat(ctx.space, companySignature(ctx.space, contId), 1);
|
|
208
|
-
for (const part of c.changed) {
|
|
209
|
-
const partId = c.ids.get(part);
|
|
210
|
-
await ctx.store.pourHalo(partId, contSeat);
|
|
211
|
-
await ctx.store.pourHalo(contId, bindSeat(ctx.space, companySignature(ctx.space, partId), 0));
|
|
212
|
-
}
|
|
213
|
-
return { ctxId, contId };
|
|
214
|
-
}
|
|
215
|
-
/** Dispatch the public ingest input shapes onto one-input / pair handlers —
|
|
216
|
-
* THE one reading of ingest's polymorphic surface (scalar, (context,
|
|
217
|
-
* continuation) pair, or a list mixing bare inputs and pairs). Both ingest
|
|
218
|
-
* paths — the direct one below and {@link CachedIngest} — route through
|
|
219
|
-
* this, so the shape-detection can never drift between them again (the
|
|
220
|
-
* ingest cache once re-implemented it and drifted). */
|
|
221
|
-
export async function dispatchIngest(input, second, onOne, onPair) {
|
|
222
|
-
if (Array.isArray(input) && !(input instanceof Uint8Array) &&
|
|
223
|
-
input.width === undefined) {
|
|
224
|
-
const arr = input;
|
|
225
|
-
if (arr.length === 2 && !Array.isArray(arr[0]) && !Array.isArray(arr[1])) {
|
|
226
|
-
await onPair(arr[0], arr[1]);
|
|
227
|
-
return undefined;
|
|
228
|
-
}
|
|
229
|
-
for (const item of arr) {
|
|
230
|
-
if (Array.isArray(item) && item.length === 2) {
|
|
231
|
-
await onPair(item[0], item[1]);
|
|
232
|
-
}
|
|
233
|
-
else
|
|
234
|
-
await onOne(item);
|
|
235
|
-
}
|
|
236
|
-
return undefined;
|
|
237
|
-
}
|
|
238
|
-
if (second === undefined)
|
|
239
|
-
return onOne(input);
|
|
240
|
-
await onPair(input, second);
|
|
241
|
-
return undefined;
|
|
242
|
-
}
|
|
243
|
-
/** Ingest an input or array of inputs/pairs. The public ingest entry point.
|
|
244
|
-
*
|
|
245
|
-
* `onDeposit`, when given, is invoked once per ingested item with the
|
|
246
|
-
* deposited root node ids ({@link DepositReport}) — item-level provenance
|
|
247
|
-
* for tooling that needs to know which stored node an ingested item became.
|
|
248
|
-
* Purely observational: the callback runs after the item's deposit
|
|
249
|
-
* completed and nothing reads its result. */
|
|
250
|
-
export async function ingest(ctx, input, second, onDeposit) {
|
|
251
|
-
let index = 0;
|
|
252
|
-
return dispatchIngest(input, second, async (i) => {
|
|
253
|
-
const r = await ingestOne(ctx, i);
|
|
254
|
-
onDeposit?.({ index: index++, kind: "one", contextId: r.id });
|
|
255
|
-
return r;
|
|
256
|
-
}, async (a, b) => {
|
|
257
|
-
const { ctxId, contId } = await ingestPair(ctx, a, b);
|
|
258
|
-
onDeposit?.({
|
|
259
|
-
index: index++,
|
|
260
|
-
kind: "pair",
|
|
261
|
-
contextId: ctxId,
|
|
262
|
-
continuationId: contId,
|
|
263
|
-
});
|
|
264
|
-
});
|
|
265
|
-
}
|
package/dist/src/mind/match.d.ts
DELETED
|
@@ -1,351 +0,0 @@
|
|
|
1
|
-
import { Vec } from "../vec.js";
|
|
2
|
-
import type { Hit } from "../store.js";
|
|
3
|
-
import type { MindContext } from "./types.js";
|
|
4
|
-
import type { Site } from "./graph-search.js";
|
|
5
|
-
/** The graded LOCATE ladder: find `needle` in `haystack` starting at
|
|
6
|
-
* `fromPos`, strictest matcher first, relaxing only when the stricter one
|
|
7
|
-
* fails. This is the read-out matcher skill extraction locates exemplar
|
|
8
|
-
* frames with.
|
|
9
|
-
*
|
|
10
|
-
* 1. exact — literal byte match (the fast path).
|
|
11
|
-
* 2. halo — the needle's distributional role matches a recognised query
|
|
12
|
-
* form (gate: conceptThreshold).
|
|
13
|
-
* 3. gist — the needle's perceived gist matches a query segment
|
|
14
|
-
* (gate: identityBar — scale-aware).
|
|
15
|
-
*
|
|
16
|
-
* Returns the absolute byte position, or −1. */
|
|
17
|
-
export declare function locate(ctx: MindContext, haystack: Uint8Array, needle: Uint8Array, fromPos: number, sites?: ReadonlyArray<Site>): number;
|
|
18
|
-
/** The ALIGNED matcher: maximal literal matching runs between `query` and
|
|
19
|
-
* `ct` (a learned context's bytes), by seed-and-extend over
|
|
20
|
-
* `space.maxGroup`-sized n-gram seeds. Where locate() finds ONE position of
|
|
21
|
-
* a short frame, this finds EVERY run two whole structures share — the
|
|
22
|
-
* matcher CAST detects a woven query with. Returns non-overlapping runs
|
|
23
|
-
* sorted by query position. */
|
|
24
|
-
export declare function alignRuns(ctx: MindContext, query: Uint8Array, ct: Uint8Array): Array<{
|
|
25
|
-
qs: number;
|
|
26
|
-
qe: number;
|
|
27
|
-
cs: number;
|
|
28
|
-
}>;
|
|
29
|
-
/** A run from {@link alignGraded} — the ALIGNED matcher extended with the
|
|
30
|
-
* same graded-evidence ladder as {@link locate}. Literal runs carry
|
|
31
|
-
* `weight = 1` (exact match is full evidence); halo-matched site runs carry
|
|
32
|
-
* `weight = cosine` (measured evidence — the halo similarity itself).
|
|
33
|
-
* `cs` is the structural byte position in the context regardless of run
|
|
34
|
-
* kind, so the substitution/redirection schemas work unchanged on conceptual
|
|
35
|
-
* alignment. */
|
|
36
|
-
export interface GradedRun {
|
|
37
|
-
/** True for a run the CLIMB proposed rather than the byte matcher found — see
|
|
38
|
-
* {@link computeWeave}'s phase 2. Provenance only: a proposed run reaches
|
|
39
|
-
* CAST already gated (dominant literal agreement, not frame, and over bytes
|
|
40
|
-
* no literal run claimed), so every consumer reads it exactly like any other
|
|
41
|
-
* run. Filtering seat-shaped reads by this flag was tried and is NOT
|
|
42
|
-
* needed — the gates, not the flag, are what make it safe. */
|
|
43
|
-
proposed?: boolean;
|
|
44
|
-
qs: number;
|
|
45
|
-
qe: number;
|
|
46
|
-
cs: number;
|
|
47
|
-
weight: number;
|
|
48
|
-
}
|
|
49
|
-
/** The GRADED alignment matcher: extends literal W-gram alignment
|
|
50
|
-
* ({@link alignRuns}) with halo-matched recognised sites in query regions
|
|
51
|
-
* that have no literal coverage. Same ladder as {@link locate}: literal
|
|
52
|
-
* first, then distributional role (halo-matched sites, gate:
|
|
53
|
-
* conceptThreshold, enforced by {@link bestHaloMate}). Returns weighted
|
|
54
|
-
* runs sorted by query position.
|
|
55
|
-
*
|
|
56
|
-
* `querySites` are the pre-computed recognition sites for the query
|
|
57
|
-
* (optional — when absent, only literal alignment fires and graded degrades
|
|
58
|
-
* to the original behaviour). Context sites are recognised internally. */
|
|
59
|
-
export declare function alignGraded(ctx: MindContext, query: Uint8Array, contextBytes: Uint8Array, querySites?: ReadonlyArray<Site>): GradedRun[];
|
|
60
|
-
/** One place two byte streams DISAGREE, between runs where they agree: the
|
|
61
|
-
* query span `[qs,qe)` standing where the candidate's `[cs,ce)` stands.
|
|
62
|
-
*
|
|
63
|
-
* Two mechanisms read the same gap and ask OPPOSITE questions of it, which is
|
|
64
|
-
* why the shape lives here rather than in either of them:
|
|
65
|
-
*
|
|
66
|
-
* • the substitution bridge asks whether the two sides MEAN THE SAME, and
|
|
67
|
-
* so EXPANDS the gap (absorbing flanking matched bytes) until the query
|
|
68
|
-
* side is corpus-attested and the pair clears the concept bar;
|
|
69
|
-
* • the frame reading asks WHERE THE SLOT IS, and so CONTRACTS it
|
|
70
|
-
* ({@link contractGap}) until the two sides share nothing at all.
|
|
71
|
-
*
|
|
72
|
-
* Neither reading is derivable from the other, and both need the same gap. */
|
|
73
|
-
export interface AlignGap {
|
|
74
|
-
qs: number;
|
|
75
|
-
qe: number;
|
|
76
|
-
cs: number;
|
|
77
|
-
ce: number;
|
|
78
|
-
}
|
|
79
|
-
/** Extend a seed match (query offset qo ↔ candidate offset co) to its maximal
|
|
80
|
-
* common run, then walk outward in both directions collecting further common
|
|
81
|
-
* runs of at least W bytes across bounded mismatch gaps (each side ≤
|
|
82
|
-
* chainReach). Returns the matched query spans and the mismatch pairs
|
|
83
|
-
* between consecutive runs.
|
|
84
|
-
*
|
|
85
|
-
* This is the SEEDED aligner, distinct from {@link alignRuns}: that one finds
|
|
86
|
-
* every run two structures share anywhere (a weave), this one reads two
|
|
87
|
-
* streams as ONE structure that diverges in bounded places (a frame with
|
|
88
|
-
* slots).
|
|
89
|
-
*
|
|
90
|
-
* Gaps come back in SWEEP order (right sweep, then left), not query order,
|
|
91
|
-
* and only the INTERIOR ones are reported — a consumer that needs the query's
|
|
92
|
-
* unmatched head or tail derives it from `matched`. Both are the bridge's
|
|
93
|
-
* contract, which prices its edges separately (see its matchStart/matchEnd
|
|
94
|
-
* window test); {@link frameSlots} takes the other reading. */
|
|
95
|
-
export declare function alignAround(ctx: MindContext, q: Uint8Array, c: Uint8Array, qo: number, co: number): {
|
|
96
|
-
matched: Array<[number, number]>;
|
|
97
|
-
gaps: AlignGap[];
|
|
98
|
-
};
|
|
99
|
-
/** Contract a gap to its VARYING CORE: strip the prefix and suffix the two
|
|
100
|
-
* sides share. {@link alignAround} cannot match a shared affix shorter than
|
|
101
|
-
* W, so that affix lands INSIDE the gap — measured, the slot of
|
|
102
|
-
* `How do I compile main.c?` against `…hello.c?` comes back as
|
|
103
|
-
* `main.c?`/`hello.c?`, three bytes of which (`.c?`) both sides hold.
|
|
104
|
-
*
|
|
105
|
-
* Splicing the uncontracted gap carries the query's own punctuation into the
|
|
106
|
-
* answer; worse, it hides what actually VARIES, which is the only thing a
|
|
107
|
-
* cohort can agree about. Returns null when nothing is left on either side —
|
|
108
|
-
* a pure insertion or deletion, which names no slot. */
|
|
109
|
-
export declare function contractGap(q: Uint8Array, c: Uint8Array, g: AlignGap): AlignGap | null;
|
|
110
|
-
/** What one place two streams disagree IS, once contracted to its varying
|
|
111
|
-
* core. A consumer decides which kinds it can use; the matcher only reports.
|
|
112
|
-
*
|
|
113
|
-
* substitution both sides carry bytes — one thing stands where another does
|
|
114
|
-
* insertion the query carries bytes the candidate does not
|
|
115
|
-
* deletion the candidate carries bytes the query does not */
|
|
116
|
-
export type SlotKind = "substitution" | "insertion" | "deletion";
|
|
117
|
-
/** One VARIABLE POSITION of a pairing: where the query and a candidate differ,
|
|
118
|
-
* contracted to the bytes that actually vary. */
|
|
119
|
-
export interface FrameSlot {
|
|
120
|
-
/** Query span (empty for a deletion). */
|
|
121
|
-
qs: number;
|
|
122
|
-
qe: number;
|
|
123
|
-
/** Candidate span (empty for an insertion). */
|
|
124
|
-
cs: number;
|
|
125
|
-
ce: number;
|
|
126
|
-
kind: SlotKind;
|
|
127
|
-
/** The candidate's own bytes here — empty for an insertion. */
|
|
128
|
-
filler: Uint8Array;
|
|
129
|
-
}
|
|
130
|
-
/** One trained context read against the query as ONE structure with variable
|
|
131
|
-
* positions.
|
|
132
|
-
*
|
|
133
|
-
* EVERYTHING THE ALIGNER SAW, NOTHING JUDGED. `slots` holds every place the
|
|
134
|
-
* pairing varies, in query order, whatever its kind or size, and `covered`
|
|
135
|
-
* says how much of the query the two hold in common. No gate is applied
|
|
136
|
-
* here — see {@link frameSlots}. */
|
|
137
|
-
export interface FrameInstance {
|
|
138
|
-
/** The trained context this reading is against. */
|
|
139
|
-
id: number;
|
|
140
|
-
/** Every variable position, in query order. */
|
|
141
|
-
slots: FrameSlot[];
|
|
142
|
-
/** Query spans the pairing literally matched — the frame itself. */
|
|
143
|
-
matched: Array<[number, number]>;
|
|
144
|
-
/** Query bytes the frame accounts for: the size of what is shared. */
|
|
145
|
-
covered: number;
|
|
146
|
-
}
|
|
147
|
-
/** THE SLOT MATCHER: read one query ↔ context pairing as one structure with
|
|
148
|
-
* variable positions.
|
|
149
|
-
*
|
|
150
|
-
* IT REPORTS; IT DOES NOT JUDGE. This returns every gap the aligner found,
|
|
151
|
-
* contracted to its varying core and tagged with its kind, plus the shared
|
|
152
|
-
* coverage — and rejects nothing. That is the whole point of the split, and
|
|
153
|
-
* it was got WRONG first: four VOICING gates (the frame must dominate the
|
|
154
|
-
* query, each slot must reach one window on both sides, an insertion or
|
|
155
|
-
* deletion disqualifies the pairing, fillers must be pairwise distinct) were
|
|
156
|
-
* applied here, and every one of them is a requirement for SUBSTITUTING AND
|
|
157
|
-
* SPEAKING, not for knowing where a pairing varies. With them in place the
|
|
158
|
-
* shared reading was reference-shaped: measured over four real pairings, three
|
|
159
|
-
* were hidden from every consumer —
|
|
160
|
-
*
|
|
161
|
-
* `What is the capital of the country where the Eiffel Tower is?`
|
|
162
|
-
* against `What is the capital of France?` (covered 23/61) HIDDEN
|
|
163
|
-
* `What is the capital of France, really?` (an insertion) HIDDEN
|
|
164
|
-
* `What is the capital of Fran?` (sub-window) HIDDEN
|
|
165
|
-
*
|
|
166
|
-
* — including the case of the one consumer that most obviously needed it. A
|
|
167
|
-
* shared layer with one usable consumer is private code at a public address.
|
|
168
|
-
* Each gate now lives with the mechanism that needs it (see reference.ts).
|
|
169
|
-
*
|
|
170
|
-
* Seeded at the origin, because a frame is shared structure the query and its
|
|
171
|
-
* instances both OPEN with: the maximal run around (0,0) is the frame's head
|
|
172
|
-
* and the sweeps find the rest.
|
|
173
|
-
*
|
|
174
|
-
* Null only for a degenerate pairing (either side empty). */
|
|
175
|
-
export declare function frameSlots(ctx: MindContext, query: Uint8Array, cand: Uint8Array, id: number): FrameInstance | null;
|
|
176
|
-
/** Whether every member is byte-distinct from the others. */
|
|
177
|
-
export declare function distinct(items: readonly Uint8Array[]): boolean;
|
|
178
|
-
/** Substitute every `needle -> repl` pair SIMULTANEOUSLY: one left-to-right
|
|
179
|
-
* pass, longest needle first at each position, and a replacement is never
|
|
180
|
-
* re-examined.
|
|
181
|
-
*
|
|
182
|
-
* SIMULTANEOUS IS NOT A DETAIL. Applying the pairs in sequence lets one
|
|
183
|
-
* substitution's OUTPUT be another's input: with slots `gcc -> zig` and
|
|
184
|
-
* `hello.c -> zig.c` a sequential pass rewrites bytes it had just written,
|
|
185
|
-
* and the result depends on the order the slots happened to be found in.
|
|
186
|
-
* Longest-first at each position makes the pass independent of pair order,
|
|
187
|
-
* which is what keeps {@link carriesFillers} and the binding it licenses the
|
|
188
|
-
* SAME operation — if they could disagree, the licence would not be testing
|
|
189
|
-
* what is voiced. */
|
|
190
|
-
export declare function substituteAll(hay: Uint8Array, pairs: ReadonlyArray<{
|
|
191
|
-
needle: Uint8Array;
|
|
192
|
-
repl: Uint8Array;
|
|
193
|
-
}>): Uint8Array;
|
|
194
|
-
/** THE CARRIAGE LICENCE — the gate that decides whether a slot may be VOICED
|
|
195
|
-
* through. Given two instances of one frame and what each one continues to,
|
|
196
|
-
* it asks one byte question:
|
|
197
|
-
*
|
|
198
|
-
* substituteAll(contA, fillersA -> fillersB) == contB
|
|
199
|
-
*
|
|
200
|
-
* When it holds, the corpus attests byte-exactly that the continuation is a
|
|
201
|
-
* function of the fillers and nothing else, so putting a NEW occupant through
|
|
202
|
-
* the same carriage is derivation rather than invention. No threshold, no
|
|
203
|
-
* similarity, no new constant: the store's own instances decide, exactly as
|
|
204
|
-
* the bridge's `unanimous` decides whether a frame is a value slot.
|
|
205
|
-
*
|
|
206
|
-
* Its FAILURE is what this is really for. A frame whose continuation carries
|
|
207
|
-
* filler-DEPENDENT content — `What is the capital of X?` answering a different
|
|
208
|
-
* city per X — fails it, and that failure is the only thing between a slot
|
|
209
|
-
* and an invented fact. Measured on the trained 15.7M-node store (325,615
|
|
210
|
-
* contexts): `What is the capital of Zamunda?` resonates to a PURE cohort,
|
|
211
|
-
* every one of the top 14 hits an instance of that frame, with an unambiguous
|
|
212
|
-
* slot; every structural gate passes and only this one refuses, on
|
|
213
|
-
* `replace("Tokyo", "Japan" -> "France") != "Paris"`.
|
|
214
|
-
*
|
|
215
|
-
* With SEVERAL slots the test is unchanged, which is the point of testing the
|
|
216
|
-
* whole substitution at once: a frame whose answer tracks one slot but
|
|
217
|
-
* invents around another fails exactly as a single-slot value slot does. */
|
|
218
|
-
export declare function carriesFillers(contA: Uint8Array, fillersA: readonly Uint8Array[], contB: Uint8Array, fillersB: readonly Uint8Array[]): boolean;
|
|
219
|
-
/** The IN-LIST halo matcher: the best halo-mate for `halo` among EXPLICIT
|
|
220
|
-
* candidates, above the concept threshold — the list counterpart of
|
|
221
|
-
* {@link haloSiblings}, which asks the halo INDEX for candidates instead.
|
|
222
|
-
* Behind locate()'s halo step and articulation's voice matching; a third
|
|
223
|
-
* "best halo among these" decision must come here, not inline. */
|
|
224
|
-
export declare function bestHaloMate<T>(ctx: MindContext, halo: Vec, items: Iterable<T>, haloOf: (item: T) => Vec | null | undefined): {
|
|
225
|
-
item: T;
|
|
226
|
-
score: number;
|
|
227
|
-
} | null;
|
|
228
|
-
export declare function haloSiblings(ctx: MindContext, id: number, halo?: Vec | null, bar?: number): Promise<Hit[]>;
|
|
229
|
-
/** Bundle the distributional company of every addressable W-window in a
|
|
230
|
-
* byte span. This is the query-time counterpart of the write-side halo
|
|
231
|
-
* pours: no lexical unit or storage row is invented; the span is represented
|
|
232
|
-
* by VSA superposition of the window concepts the store already knows.
|
|
233
|
-
*
|
|
234
|
-
* Components are normalized before bundling so repetition mass remains
|
|
235
|
-
* evidence about each stored node, not an accidental weight on one window
|
|
236
|
-
* inside the composed phrase. Returns null when the corpus provides no
|
|
237
|
-
* distributional evidence for the span. */
|
|
238
|
-
export declare function spanHalo(ctx: MindContext, bytes: Uint8Array, from?: number, to?: number): Vec | null;
|
|
239
|
-
/** Distributional synonym evidence between arbitrary byte spans. Whole words
|
|
240
|
-
* need not be independently interned: their stored W-window occurrences are
|
|
241
|
-
* lifted to episode halos, bundled, and compared. The caller chooses the
|
|
242
|
-
* derived gate appropriate to its claim (concept identity or analogy). */
|
|
243
|
-
export declare function spanSynonymStrength(ctx: MindContext, a: Uint8Array, b: Uint8Array): number;
|
|
244
|
-
/** The DISTRIBUTIONAL matcher between two nodes: mutual-nearest-neighbour
|
|
245
|
-
* strength, not a pick. Returns the direct halo cosine, or failing that the
|
|
246
|
-
* highest mutual-halo-sibling min-score (second-order analogy), or failing
|
|
247
|
-
* that the SHARED-FRAME strength (below) — the gate CAST's comparison
|
|
248
|
-
* schema validates genuine analogs with (bar: significanceBar).
|
|
249
|
-
*
|
|
250
|
-
* The result names its TIER alongside the score: `halo: true` means the
|
|
251
|
-
* score cleared a significanceBar-gated HALO tier (direct company cosine
|
|
252
|
-
* or mutual-sibling) — genuine distributional evidence; `halo: false`
|
|
253
|
-
* means only the structural shared-frame fallback matched, a coverage
|
|
254
|
-
* fraction with no bar of its own. CAST's comparison gate treats the two
|
|
255
|
-
* differently (see cast.ts): halo evidence stands alone, frame evidence
|
|
256
|
-
* needs the query to have named the analog or the climb root to be
|
|
257
|
-
* trusted. */
|
|
258
|
-
export interface AnalogyEvidence {
|
|
259
|
-
score: number;
|
|
260
|
-
halo: boolean;
|
|
261
|
-
}
|
|
262
|
-
export declare function analogyStrength(ctx: MindContext, a: number, b: number): Promise<AnalogyEvidence>;
|
|
263
|
-
/** The STRUCTURAL analogy tier: two nodes are analogs when their byte
|
|
264
|
-
* streams share a LEARNT frame — a content-addressed flat form of at least
|
|
265
|
-
* one full river window (W bytes, the perception quantum) that occurs in
|
|
266
|
-
* BOTH. This is what "playing the same role" means structurally: "Ice is
|
|
267
|
-
* cold" and "Steel is hard" share the learnt " is " frame even though they
|
|
268
|
-
* keep disjoint distributional company. Halos measure company by IDENTITY
|
|
269
|
-
* (company signatures — see sema.ts), so unrelated-company analogs must be
|
|
270
|
-
* validated by the frame itself, not by content leaking through halo
|
|
271
|
-
* vectors. Strength is the shared learnt coverage of the SHORTER side —
|
|
272
|
-
* a fraction, comparable to the cosine tiers above. Derived: the window
|
|
273
|
-
* is maxGroup, the same quantum differsByOneWindow and canonicalChunkId
|
|
274
|
-
* measure by; no tuned constants. */
|
|
275
|
-
export declare function sharedFrameStrength(ctx: MindContext, a: number, b: number): number;
|
|
276
|
-
/** The same measure over BYTES, for callers holding a role-establishing
|
|
277
|
-
* CONTEXT rather than the node whose role it establishes — CAST's comparison
|
|
278
|
-
* reads the tier this way when two candidate analogs are fillers (bare entity
|
|
279
|
-
* names) rather than frame-bearing structures themselves. A role is a
|
|
280
|
-
* property of the context that establishes a filler, never of the filler's
|
|
281
|
-
* own bytes: measured on test/29's corpus, "Michelangelo" against "Homer"
|
|
282
|
-
* reads 0.000 while their establishing contexts ("The David was sculpted
|
|
283
|
-
* by…" against "The Iliad was written by…") read 0.452, and a context in a
|
|
284
|
-
* genuinely different frame ("Water boils at…") still reads 0.000 — the tier
|
|
285
|
-
* discriminates, it was simply being asked about the wrong bytes. */
|
|
286
|
-
export declare function sharedFrameStrengthOf(ctx: MindContext, A: Uint8Array, B: Uint8Array): number;
|
|
287
|
-
/** FORWARD through a synonym: the continuation an edge-less node borrows from
|
|
288
|
-
* a concept (halo) sibling — resonate the node's halo, take the first
|
|
289
|
-
* sibling above the concept threshold that itself has a direct edge. */
|
|
290
|
-
export declare function conceptHop(ctx: MindContext, id: number): Promise<number | null>;
|
|
291
|
-
/** FORWARD projection: follow continuation edges from a node to its fixpoint.
|
|
292
|
-
* The first hop may cross a concept (halo) link — a synonym. The rest
|
|
293
|
-
* follow direct edges. Convergence is intrinsic: the seen set guards
|
|
294
|
-
* against cycles. `guide` disambiguates multi-continuation nodes by
|
|
295
|
-
* resonance. */
|
|
296
|
-
export declare function follow(ctx: MindContext, id: number, guide?: Vec | null): Promise<Uint8Array | null>;
|
|
297
|
-
/** REVERSE projection: the context a learnt continuation follows, voiced as
|
|
298
|
-
* bytes. A common continuation ("Yes.") follows MANY contexts; with a
|
|
299
|
-
* `guide` the context whose gist resonates with the query wins (seat
|
|
300
|
-
* symmetry) — without one, the most-corroborated context wins (poured halo
|
|
301
|
-
* MASS, the direct measure of how many episodes established it), falling
|
|
302
|
-
* back to first-learnt on equal mass. Among many predecessors RECIPROCAL
|
|
303
|
-
* ones (mutual edges) are preferred when any exist (RC5). Callers that
|
|
304
|
-
* HAVE a query gist must pass it, or they silently change disambiguation
|
|
305
|
-
* regime.
|
|
306
|
-
*
|
|
307
|
-
* `rev`, when the caller has already materialised prevOf (one read per
|
|
308
|
-
* relation — a hub's reverse fan-in is corpus-sized), is reused instead of
|
|
309
|
-
* refetched. Returns null when there is no predecessor or the picked
|
|
310
|
-
* context reads empty (a zero-length context is no grounding: an empty
|
|
311
|
-
* Uint8Array is truthy, and returning it would flow a hollow "answer"
|
|
312
|
-
* onward). */
|
|
313
|
-
export declare function reverseContext(ctx: MindContext, id: number, guide?: Vec | null, rev?: readonly number[]): Uint8Array | null;
|
|
314
|
-
/** THE projection: ground a matched node to answer bytes — FORWARD to its
|
|
315
|
-
* continuation fixpoint (which may cross a concept hop), else REVERSE to
|
|
316
|
-
* the context it follows. This is the direction ladder every mechanism's
|
|
317
|
-
* final grounding step reduces to. */
|
|
318
|
-
export declare function project(ctx: MindContext, id: number, guide?: Vec | null): Promise<Uint8Array | null>;
|
|
319
|
-
/** Check whether an anchor is a span-shaped skill exemplar: it represents a
|
|
320
|
-
* fact whose context and answer together form a span-in-context pattern.
|
|
321
|
-
* If the anchor has a nextOf continuation, that is the answer and the anchor
|
|
322
|
-
* itself is the context. Otherwise the anchor's prevOf parents provide
|
|
323
|
-
* candidate contexts, and the longest one whose span is span-shaped wins. */
|
|
324
|
-
export declare function skillExemplar(ctx: MindContext, anchor: number, guide?: Vec | null): Promise<{
|
|
325
|
-
contextBytes: Uint8Array;
|
|
326
|
-
answerBytes: Uint8Array;
|
|
327
|
-
} | null>;
|
|
328
|
-
/** Whether the answer is a SPARSE subsequence of the context (bytes in
|
|
329
|
-
* order, arbitrary gaps) — the OPEN span-shape reading (see the section
|
|
330
|
-
* note above). This is what lets extraction validate a MULTI-PIECE
|
|
331
|
-
* exemplar whose answer is stitched from several context runs — but it is
|
|
332
|
-
* deliberately permissive, so it must never be used as evidence that one
|
|
333
|
-
* span was "drawn from" another (see {@link containsSpan} for that).
|
|
334
|
-
*
|
|
335
|
-
* There is deliberately NO containsSpan pre-check here: strict containment
|
|
336
|
-
* IMPLIES the subsequence embedding (a contiguous run, or a resolved node —
|
|
337
|
-
* whose content-addressed identity means its bytes occur contiguously — is
|
|
338
|
-
* an in-order embedding with zero gaps), so the scan below decides alone,
|
|
339
|
-
* with the same truth value. The old pre-check re-perceived the context
|
|
340
|
-
* (a full river fold) per CANDIDATE in skillExemplar's √N-capped loop —
|
|
341
|
-
* pure cost, no discrimination. */
|
|
342
|
-
export declare function isSpanShaped(_ctx: MindContext, context: Uint8Array, answer: Uint8Array): boolean;
|
|
343
|
-
/** STRICT containment: the answer's resolved node appears in the context's
|
|
344
|
-
* folded tree, or the answer occurs as one CONTIGUOUS byte run of the
|
|
345
|
-
* context. This is real evidence the answer was drawn from the context.
|
|
346
|
-
* Fusion gates on this — the sparse-subsequence reading of
|
|
347
|
-
* {@link isSpanShaped} is trivially satisfied by short answers over long
|
|
348
|
-
* queries ("cold" is a gap-tolerant subsequence of most sentences holding
|
|
349
|
-
* c…o…l…d in order), and gating fusion on it silently starved multi-topic
|
|
350
|
-
* queries of their further points of attention. */
|
|
351
|
-
export declare function containsSpan(ctx: MindContext, context: Uint8Array, answer: Uint8Array): boolean;
|