@hviana/sema 0.9.2 → 0.9.3
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/dist/src/meter.d.ts +6 -0
- package/dist/src/meter.js +6 -0
- package/dist/src/mind/evidence.d.ts +6 -0
- package/dist/src/mind/evidence.js +19 -7
- package/dist/src/mind/mechanisms/cast.d.ts +1 -1
- package/dist/src/mind/mechanisms/cast.js +73 -12
- package/dist/src/mind/mechanisms/cover.js +4 -20
- package/dist/src/mind/mechanisms/recall.js +84 -8
- package/dist/src/mind/mechanisms/reference.js +25 -0
- package/dist/src/mind/mind.d.ts +1 -0
- package/dist/src/mind/pipeline-mechanism.js +15 -1
- package/dist/src/mind/pipeline.js +5 -4
- package/dist/src/mind/reasoning.js +28 -16
- package/dist/src/mind/resonance.d.ts +3 -2
- package/dist/src/mind/resonance.js +3 -2
- package/dist/src/mind/traverse.d.ts +52 -0
- package/dist/src/mind/traverse.js +334 -7
- package/dist/src/mind/types.d.ts +4 -1
- package/docs/INDEX.md +17 -17
- package/docs/INVARIANTS.md +1 -1
- package/docs/architecture/evidence.md +172 -29
- package/jsr.json +1 -1
- package/package.json +1 -1
- package/src/meter.ts +6 -0
- package/src/mind/evidence.ts +22 -4
- package/src/mind/mechanisms/cast.ts +77 -3
- package/src/mind/mechanisms/cover.ts +6 -22
- package/src/mind/mechanisms/recall.ts +107 -9
- package/src/mind/mechanisms/reference.ts +24 -1
- package/src/mind/mind.ts +3 -1
- package/src/mind/pipeline-mechanism.ts +15 -1
- package/src/mind/pipeline.ts +5 -4
- package/src/mind/reasoning.ts +33 -15
- package/src/mind/resonance.ts +3 -2
- package/src/mind/traverse.ts +338 -6
- package/src/mind/types.ts +6 -2
- package/test/154-the-question-names-the-step.test.mjs +88 -1
- package/test/155-the-relation-read-off-another-instance.test.mjs +376 -0
- package/test/29-counterfactual.test.mjs +21 -11
- package/test/76-reference-binding.test.mjs +32 -0
|
@@ -162,6 +162,19 @@ export declare function chooseNext(ctx: MindContext, id: number, guide?: Vec | n
|
|
|
162
162
|
* ASCII without interior whitespace runs; where it is not, the raw bytes are
|
|
163
163
|
* read and a case-variant window simply does not match. */
|
|
164
164
|
export declare function offsetCanon(ctx: MindContext, bytes: Uint8Array): Uint8Array;
|
|
165
|
+
/** A FRAGMENT ANSWERS OTHER QUESTIONS. A recognised form that sits inside
|
|
166
|
+
* other forms (it has structural parents or containers) holds continuations
|
|
167
|
+
* because the forms it is a piece of were asked — suffix inheritance gives
|
|
168
|
+
* `f death` the answer of every `… place of death` question, and `director`
|
|
169
|
+
* the answer of every `… director` one. Choosing one of several such
|
|
170
|
+
* continuations by popularity voices some other question's answer. A
|
|
171
|
+
* fragment with several continuations leads somewhere FOR THIS QUESTION only
|
|
172
|
+
* when the question names one (the exact tier below). A form that is
|
|
173
|
+
* (nearly) the whole question is not a piece of it: the question says
|
|
174
|
+
* nothing beyond it, so its continuations answer THIS question. Read by
|
|
175
|
+
* every mechanism that projects through a recognised site (cover's sites,
|
|
176
|
+
* recall's argument binding). */
|
|
177
|
+
export declare function answersOtherQuestions(ctx: MindContext, id: number, queryLen: number, siteLen: number): boolean;
|
|
165
178
|
/** The continuations of `id` that `asked` NAMES (see {@link
|
|
166
179
|
* askedContinuations}) — for a caller holding material other than the whole
|
|
167
180
|
* question: the multi-hop walk asks with what of the question no product has
|
|
@@ -176,6 +189,45 @@ export declare function namedContinuations(ctx: MindContext, id: number, asked:
|
|
|
176
189
|
* evidence travels). Empty when the question names no continuation of `id`
|
|
177
190
|
* or names others. */
|
|
178
191
|
export declare function askedEvidence(ctx: MindContext, id: number, pick: number): Array<[number, number]>;
|
|
192
|
+
/** The climb's points the question HOLDS under the response's equivalence —
|
|
193
|
+
* stored forms whose canonical bytes occur in the question's, as sites. The
|
|
194
|
+
* recognition walk matches bytes and the fold's own boundaries, so a stored
|
|
195
|
+
* `Man at Bath` inside `… of film Man At Bath work at?` is no site; the
|
|
196
|
+
* consensus climb reaches it through the windows the two spellings share, and
|
|
197
|
+
* containment under the canon (offset-preserving, so the span is the
|
|
198
|
+
* question's own) decides. Approximate proposes, exact decides. Read off
|
|
199
|
+
* the `chainReach(W)` most corroborated points; empty before the climb. */
|
|
200
|
+
export declare function canonHeldPoints(ctx: MindContext, minLen: number): Array<{
|
|
201
|
+
start: number;
|
|
202
|
+
end: number;
|
|
203
|
+
payload: number;
|
|
204
|
+
}>;
|
|
205
|
+
/** A CO-INSTANCE of the question: a stored form that shares the question's
|
|
206
|
+
* FRAME — the same opening and the same close, byte for byte under the
|
|
207
|
+
* response's equivalence — around ONE different filler. `Where was Peter
|
|
208
|
+
* Jackson born?` against `Where was the director of film Beat Girl born?`
|
|
209
|
+
* shares `Where was ` and ` born?`, and leaves `Peter Jackson` against `the
|
|
210
|
+
* director of film Beat Girl`: another instance of the same question, never
|
|
211
|
+
* this one. It is the ordered limit of witnessing: a frame is not a bag of
|
|
212
|
+
* windows (an order-free reading lets `Lyon is a city in France` pass for an
|
|
213
|
+
* instance of `what if the capital of France were Lyon?`, which NAMES Lyon;
|
|
214
|
+
* and a coincidental window inside a filler splits it).
|
|
215
|
+
*
|
|
216
|
+
* The frame must reach one window, every window inside it must be held by
|
|
217
|
+
* the material (so on the walk, a frame a product already said cannot name a
|
|
218
|
+
* second step), and the form's filler must be a thing the corpus knows
|
|
219
|
+
* (below) — a record that differs from the question only inside the frame
|
|
220
|
+
* by a description (`converts sunlight into chemical energy` against
|
|
221
|
+
* `works`) is the same question about the frame's own subject. (Requiring
|
|
222
|
+
* the two fillers to share no window as well was measured redundant with
|
|
223
|
+
* this and cost two answers on the 2Wiki fixture.) Returns the form's filler span in `raw` and the
|
|
224
|
+
* question spans of the frame, or null. One reading for every consumer: the
|
|
225
|
+
* exact tier transfers the relation through it, and the readers that would
|
|
226
|
+
* VOICE such a form's own continuation refuse it. */
|
|
227
|
+
export declare function coInstanceFiller(ctx: MindContext, raw: Uint8Array, indexes: ReadonlyArray<WindowIndex>, question: Uint8Array): {
|
|
228
|
+
span: [number, number];
|
|
229
|
+
spans: Array<[number, number]>;
|
|
230
|
+
} | null;
|
|
179
231
|
/** The perceived gist of a candidate node, through the session gist cache.
|
|
180
232
|
* Re-gisting a candidate is a full river fold of its bytes — the measured
|
|
181
233
|
* recall bottleneck (a hub context offers up to √N continuations, EACH
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
// The PROJECTIONS built on these walks (follow, conceptHop, reverseContext,
|
|
7
7
|
// project) live in match.ts — the elementary match-and-project operation.
|
|
8
8
|
import { cosine } from "../vec.js";
|
|
9
|
-
import { gistOf, read } from "./primitives.js";
|
|
9
|
+
import { gistOf, read, resolve } from "./primitives.js";
|
|
10
10
|
import { canonicalWindows, chainReach, leafIdPrefix, leafIdRun, } from "./canonical.js";
|
|
11
11
|
// Imported at the TOP, where every other import is. They used to sit 800 lines
|
|
12
12
|
// down under a note claiming the position mattered ("before trace module is
|
|
@@ -14,7 +14,7 @@ import { canonicalWindows, chainReach, leafIdPrefix, leafIdRun, } from "./canoni
|
|
|
14
14
|
// file's line order never decides load order. The note described an intention
|
|
15
15
|
// the runtime does not honour; the imports move and the claim goes.
|
|
16
16
|
import { decodeText } from "./rationale.js";
|
|
17
|
-
import { latin1 } from "../bytes.js";
|
|
17
|
+
import { concatBytes, indexOf, latin1 } from "../bytes.js";
|
|
18
18
|
import { windowIndex, witness } from "./evidence.js";
|
|
19
19
|
//
|
|
20
20
|
// Budgeted on the same terms as the reach memo below (caches.md): these three
|
|
@@ -590,7 +590,9 @@ export function guidedNext(ctx, node) {
|
|
|
590
590
|
// policy climbMemo and recogniseMemo follow (every mechanism must emit its
|
|
591
591
|
// own steps; a memo hit would swallow the repeat's `disambiguate` step).
|
|
592
592
|
// Consistency does not need the memo: chooseNext is a pure function of the
|
|
593
|
-
// (read-only) store
|
|
593
|
+
// (read-only) store, the guide and the consensus climb's points once they
|
|
594
|
+
// exist (the memo is cleared when they arrive), so recomputation yields the
|
|
595
|
+
// same pick.
|
|
594
596
|
if (!ctx.trace) {
|
|
595
597
|
const memo = ctx._edgeChoice.get(node);
|
|
596
598
|
if (memo !== undefined)
|
|
@@ -723,6 +725,28 @@ export function offsetCanon(ctx, bytes) {
|
|
|
723
725
|
const c = ctx.canon(bytes);
|
|
724
726
|
return c.length === bytes.length ? c : bytes;
|
|
725
727
|
}
|
|
728
|
+
/** A FRAGMENT ANSWERS OTHER QUESTIONS. A recognised form that sits inside
|
|
729
|
+
* other forms (it has structural parents or containers) holds continuations
|
|
730
|
+
* because the forms it is a piece of were asked — suffix inheritance gives
|
|
731
|
+
* `f death` the answer of every `… place of death` question, and `director`
|
|
732
|
+
* the answer of every `… director` one. Choosing one of several such
|
|
733
|
+
* continuations by popularity voices some other question's answer. A
|
|
734
|
+
* fragment with several continuations leads somewhere FOR THIS QUESTION only
|
|
735
|
+
* when the question names one (the exact tier below). A form that is
|
|
736
|
+
* (nearly) the whole question is not a piece of it: the question says
|
|
737
|
+
* nothing beyond it, so its continuations answer THIS question. Read by
|
|
738
|
+
* every mechanism that projects through a recognised site (cover's sites,
|
|
739
|
+
* recall's argument binding). */
|
|
740
|
+
export function answersOtherQuestions(ctx, id, queryLen, siteLen) {
|
|
741
|
+
const asked = ctx._edgeAsked;
|
|
742
|
+
if (asked === null || queryLen - siteLen < ctx.space.maxGroup)
|
|
743
|
+
return false;
|
|
744
|
+
if (!(ctx.store.hasParents(id) || ctx.store.hasContainers(id)))
|
|
745
|
+
return false;
|
|
746
|
+
if (ctx.store.nextFirst(id, 2).length < 2)
|
|
747
|
+
return false;
|
|
748
|
+
return namedContinuations(ctx, id, asked) === null;
|
|
749
|
+
}
|
|
726
750
|
/** The continuations of `id` that `asked` NAMES (see {@link
|
|
727
751
|
* askedContinuations}) — for a caller holding material other than the whole
|
|
728
752
|
* question: the multi-hop walk asks with what of the question no product has
|
|
@@ -774,7 +798,11 @@ function askedEntry(ctx, id, nx, asked) {
|
|
|
774
798
|
if (hit !== undefined && !ctx.trace)
|
|
775
799
|
return hit;
|
|
776
800
|
const entry = askedContinuationsImpl(ctx, id, nx, asked);
|
|
777
|
-
|
|
801
|
+
// Nothing named before the climb has run is provisional: a co-instance
|
|
802
|
+
// read from its points may still name one.
|
|
803
|
+
if (entry.named !== null || ctx._edgeAsked?.points !== undefined) {
|
|
804
|
+
memo.set(id, entry);
|
|
805
|
+
}
|
|
778
806
|
return entry;
|
|
779
807
|
}
|
|
780
808
|
/** One pick per node per question — every mechanism of a response asks the
|
|
@@ -818,7 +846,8 @@ function askedContinuationsImpl(ctx, id, nx, asked) {
|
|
|
818
846
|
// reply established by hundreds of contexts would otherwise spend the whole
|
|
819
847
|
// allowance alone. The order changes what is READ, never what wins: scores
|
|
820
848
|
// are compared afterwards in the continuations' own order.
|
|
821
|
-
|
|
849
|
+
const allowance = Math.max(hubBound(ctx), chainReach(W));
|
|
850
|
+
let budget = allowance;
|
|
822
851
|
const order = nx
|
|
823
852
|
.map((n, at) => ({ n, at, support: cachedPrevCount(ctx, n, cache) }))
|
|
824
853
|
.filter((c) => c.support >= 2) // only `id` establishes the rest
|
|
@@ -847,6 +876,15 @@ function askedContinuationsImpl(ctx, id, nx, asked) {
|
|
|
847
876
|
continue;
|
|
848
877
|
if (!indexes.some((ix) => ix.has(latin1(head))))
|
|
849
878
|
continue;
|
|
879
|
+
// AN ESTABLISHING CONTEXT IS A DEPOSITED ONE. A span interned inside
|
|
880
|
+
// bigger forms inherits their edges (the fragment ` born?` leads to the
|
|
881
|
+
// fact of every `Where was … born?` question), so witnessing it names
|
|
882
|
+
// every one of them — measured on the 2Wiki fixture with one-hop
|
|
883
|
+
// questions deposited, ` born?` named nine strangers' birthplaces. The
|
|
884
|
+
// structural predicate pivotInto already reads: a form with parents or
|
|
885
|
+
// containers was never a context on its own.
|
|
886
|
+
if (cachedHasParents(ctx, c, cache) || ctx.store.hasContainers(c))
|
|
887
|
+
continue;
|
|
850
888
|
const form = read(ctx, c, formCap + 1);
|
|
851
889
|
if (form.length < W || form.length > formCap)
|
|
852
890
|
continue;
|
|
@@ -875,8 +913,9 @@ function askedContinuationsImpl(ctx, id, nx, asked) {
|
|
|
875
913
|
else if (score === bestBytes)
|
|
876
914
|
best.push(n);
|
|
877
915
|
}
|
|
878
|
-
if (best.length === 0)
|
|
879
|
-
return
|
|
916
|
+
if (best.length === 0) {
|
|
917
|
+
return byCoInstance(ctx, id, nx, asked, formCap, allowance);
|
|
918
|
+
}
|
|
880
919
|
if (ctx.meter)
|
|
881
920
|
ctx.meter.askedContinuations++;
|
|
882
921
|
if (ctx.trace && witnessed !== null) {
|
|
@@ -890,6 +929,294 @@ function askedContinuationsImpl(ctx, id, nx, asked) {
|
|
|
890
929
|
evidence.set(c.n, c.spans);
|
|
891
930
|
return { named: best, spans: evidence };
|
|
892
931
|
}
|
|
932
|
+
/** The climb's points the question HOLDS under the response's equivalence —
|
|
933
|
+
* stored forms whose canonical bytes occur in the question's, as sites. The
|
|
934
|
+
* recognition walk matches bytes and the fold's own boundaries, so a stored
|
|
935
|
+
* `Man at Bath` inside `… of film Man At Bath work at?` is no site; the
|
|
936
|
+
* consensus climb reaches it through the windows the two spellings share, and
|
|
937
|
+
* containment under the canon (offset-preserving, so the span is the
|
|
938
|
+
* question's own) decides. Approximate proposes, exact decides. Read off
|
|
939
|
+
* the `chainReach(W)` most corroborated points; empty before the climb. */
|
|
940
|
+
export function canonHeldPoints(ctx, minLen) {
|
|
941
|
+
const asked = ctx._edgeAsked;
|
|
942
|
+
if (asked === null || asked.points === undefined || ctx.canon === null) {
|
|
943
|
+
return [];
|
|
944
|
+
}
|
|
945
|
+
const W = ctx.space.maxGroup;
|
|
946
|
+
const out = [];
|
|
947
|
+
for (const id of asked.points.slice(0, chainReach(W))) {
|
|
948
|
+
const raw = read(ctx, id, asked.bytes.length);
|
|
949
|
+
if (raw.length < minLen || raw.length >= asked.bytes.length)
|
|
950
|
+
continue;
|
|
951
|
+
const form = ctx.canon(raw);
|
|
952
|
+
if (form.length !== raw.length)
|
|
953
|
+
continue;
|
|
954
|
+
const at = indexOf(asked.bytes, form, 0);
|
|
955
|
+
if (at >= 0)
|
|
956
|
+
out.push({ start: at, end: at + raw.length, payload: id });
|
|
957
|
+
}
|
|
958
|
+
return out;
|
|
959
|
+
}
|
|
960
|
+
/** A CO-INSTANCE of the question: a stored form that shares the question's
|
|
961
|
+
* FRAME — the same opening and the same close, byte for byte under the
|
|
962
|
+
* response's equivalence — around ONE different filler. `Where was Peter
|
|
963
|
+
* Jackson born?` against `Where was the director of film Beat Girl born?`
|
|
964
|
+
* shares `Where was ` and ` born?`, and leaves `Peter Jackson` against `the
|
|
965
|
+
* director of film Beat Girl`: another instance of the same question, never
|
|
966
|
+
* this one. It is the ordered limit of witnessing: a frame is not a bag of
|
|
967
|
+
* windows (an order-free reading lets `Lyon is a city in France` pass for an
|
|
968
|
+
* instance of `what if the capital of France were Lyon?`, which NAMES Lyon;
|
|
969
|
+
* and a coincidental window inside a filler splits it).
|
|
970
|
+
*
|
|
971
|
+
* The frame must reach one window, every window inside it must be held by
|
|
972
|
+
* the material (so on the walk, a frame a product already said cannot name a
|
|
973
|
+
* second step), and the form's filler must be a thing the corpus knows
|
|
974
|
+
* (below) — a record that differs from the question only inside the frame
|
|
975
|
+
* by a description (`converts sunlight into chemical energy` against
|
|
976
|
+
* `works`) is the same question about the frame's own subject. (Requiring
|
|
977
|
+
* the two fillers to share no window as well was measured redundant with
|
|
978
|
+
* this and cost two answers on the 2Wiki fixture.) Returns the form's filler span in `raw` and the
|
|
979
|
+
* question spans of the frame, or null. One reading for every consumer: the
|
|
980
|
+
* exact tier transfers the relation through it, and the readers that would
|
|
981
|
+
* VOICE such a form's own continuation refuse it. */
|
|
982
|
+
export function coInstanceFiller(ctx, raw, indexes, question) {
|
|
983
|
+
const W = ctx.space.maxGroup;
|
|
984
|
+
const form = offsetCanon(ctx, raw);
|
|
985
|
+
const max = Math.min(form.length, question.length);
|
|
986
|
+
let a = 0;
|
|
987
|
+
while (a < max && form[a] === question[a])
|
|
988
|
+
a++;
|
|
989
|
+
let b = 0;
|
|
990
|
+
while (b < max - a &&
|
|
991
|
+
form[form.length - 1 - b] === question[question.length - 1 - b])
|
|
992
|
+
b++;
|
|
993
|
+
const fe = form.length - b;
|
|
994
|
+
if (a + b < W || fe <= a || question.length - b <= a)
|
|
995
|
+
return null;
|
|
996
|
+
// Scaffolding is nobody's evidence, so a frame window that is a hub need not
|
|
997
|
+
// be unsaid (` is ` in `Which country Leo Mittler is from?`, which the first
|
|
998
|
+
// hop's `… is Arshad Khan.` already said).
|
|
999
|
+
const hub = hubWindows(ctx, raw);
|
|
1000
|
+
const held = (o) => {
|
|
1001
|
+
if (hub[o])
|
|
1002
|
+
return true;
|
|
1003
|
+
const key = latin1(form.subarray(o, o + W));
|
|
1004
|
+
return indexes.some((ix) => ix.has(key));
|
|
1005
|
+
};
|
|
1006
|
+
for (let o = 0; o + W <= a; o++)
|
|
1007
|
+
if (!held(o))
|
|
1008
|
+
return null;
|
|
1009
|
+
for (let o = fe; o + W <= form.length; o++)
|
|
1010
|
+
if (!held(o))
|
|
1011
|
+
return null;
|
|
1012
|
+
// THE FILLER IS A THING THE CORPUS KNOWS: a stored context with
|
|
1013
|
+
// continuations of its own, opening where the slot opens (up to one window
|
|
1014
|
+
// earlier — a filler byte can sit in a window the question holds by chance:
|
|
1015
|
+
// the `T` of `Taika` inside `as t` of `was the`). `Peter Jackson` is one;
|
|
1016
|
+
// `converts sunlight into chemical energy`, the slot of `Explain how
|
|
1017
|
+
// photosynthesis …`, is a description of the frame's own subject, and the
|
|
1018
|
+
// record answers the question. The longest such context is the filler.
|
|
1019
|
+
// One content-addressed probe per byte (the `keyEnds` reading); only a run
|
|
1020
|
+
// some deposit spelled whole is looked up.
|
|
1021
|
+
const ids = leafIdPrefix(ctx, raw);
|
|
1022
|
+
let best = null;
|
|
1023
|
+
const cache = getStructCache(ctx);
|
|
1024
|
+
const reach = Math.min(ids.length, fe + W - 1);
|
|
1025
|
+
for (let st = Math.max(0, a - W + 1); st <= a; st++) {
|
|
1026
|
+
const run = [];
|
|
1027
|
+
for (let en = st + 1; en <= reach; en++) {
|
|
1028
|
+
run.push(ids[en - 1]);
|
|
1029
|
+
if (en - st < W)
|
|
1030
|
+
continue;
|
|
1031
|
+
// The flat branch over the whole run exists only where some deposit
|
|
1032
|
+
// spelled exactly these bytes — the cheap filter; the context it names
|
|
1033
|
+
// is then looked up by content.
|
|
1034
|
+
if (ctx.store.findBranch(run) === null)
|
|
1035
|
+
continue;
|
|
1036
|
+
if (best !== null && en - st <= best[1] - best[0])
|
|
1037
|
+
continue;
|
|
1038
|
+
const id = resolve(ctx, raw.subarray(st, en));
|
|
1039
|
+
if (id !== null && cachedHasNext(ctx, id, cache))
|
|
1040
|
+
best = [st, en];
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
if (best === null)
|
|
1044
|
+
return null;
|
|
1045
|
+
const spans = [];
|
|
1046
|
+
if (a > 0)
|
|
1047
|
+
spans.push([0, a]);
|
|
1048
|
+
if (b > 0)
|
|
1049
|
+
spans.push([question.length - b, question.length]);
|
|
1050
|
+
return { span: best, spans };
|
|
1051
|
+
}
|
|
1052
|
+
/** THE RELATION, READ OFF ANOTHER INSTANCE — the exact tier's second reading,
|
|
1053
|
+
* asked only when no establishing context of `id`'s continuations is
|
|
1054
|
+
* witnessed outright.
|
|
1055
|
+
*
|
|
1056
|
+
* `When was the director of film Jinpa born?` reaches `Pema Tseden`, whose
|
|
1057
|
+
* date-of-birth fact is established by `Pema Tseden date of birth`: the
|
|
1058
|
+
* question says `born`, the corpus says `date of birth`, and no window joins
|
|
1059
|
+
* them. What can join them is ANOTHER INSTANCE of the same question. A
|
|
1060
|
+
* stored context the question witnesses in every byte but ONE contiguous span
|
|
1061
|
+
* (`When was Peter Jackson born?`, residue `Peter Jackson`) is the question's
|
|
1062
|
+
* own frame around a different filler — a CO-INSTANCE. Its continuation is
|
|
1063
|
+
* established by other contexts too (`Peter Jackson date of birth`), and one
|
|
1064
|
+
* that holds the filler is the relation spelled the way the corpus spells it.
|
|
1065
|
+
* Put this node where the filler was and look the result up by content:
|
|
1066
|
+
* `Pema Tseden date of birth` exists, and its continuation is named.
|
|
1067
|
+
*
|
|
1068
|
+
* Nothing here is stored as a unit — not `born` ≈ `date of birth`, not the
|
|
1069
|
+
* frame — and nothing is approximate: the co-instance is witnessed, the
|
|
1070
|
+
* substitution is bytes, the target is an exact lookup that either exists
|
|
1071
|
+
* with this node's continuation or does not. A frame the question shares only
|
|
1072
|
+
* partly (`Where was … born?` against `When was …`) leaves two residues and
|
|
1073
|
+
* is no co-instance.
|
|
1074
|
+
*
|
|
1075
|
+
* BOUNDED: the frames are a property of the question and are read once per
|
|
1076
|
+
* question (`relationFrames`); co-instances are proposed by the edge-bearing
|
|
1077
|
+
* ancestors of its windows (`edgeAncestors`, the climb's own memoised reach;
|
|
1078
|
+
* a saturated window proposes nothing), rarest first, at most `allowance` of
|
|
1079
|
+
* them, each read once. A node pays one exact lookup per frame. */
|
|
1080
|
+
function byCoInstance(ctx, id, nx, asked, formCap, allowance) {
|
|
1081
|
+
const none = { named: null, spans: new Map() };
|
|
1082
|
+
const frames = relationFrames(ctx, asked, allowance);
|
|
1083
|
+
if (frames.length === 0)
|
|
1084
|
+
return none;
|
|
1085
|
+
const node = read(ctx, id, formCap);
|
|
1086
|
+
const support = new Map();
|
|
1087
|
+
const spans = new Map();
|
|
1088
|
+
const via = new Map();
|
|
1089
|
+
for (const fr of frames) {
|
|
1090
|
+
const t = resolve(ctx, concatBytes([fr.prefix, node, fr.suffix]));
|
|
1091
|
+
if (t === null || t === id)
|
|
1092
|
+
continue;
|
|
1093
|
+
for (const n of ctx.store.nextFirst(t, allowance)) {
|
|
1094
|
+
if (!nx.includes(n))
|
|
1095
|
+
continue;
|
|
1096
|
+
let by = support.get(n);
|
|
1097
|
+
if (by === undefined)
|
|
1098
|
+
support.set(n, by = new Set());
|
|
1099
|
+
for (const q of fr.by)
|
|
1100
|
+
by.add(q);
|
|
1101
|
+
if (!spans.has(n)) {
|
|
1102
|
+
spans.set(n, fr.spans);
|
|
1103
|
+
via.set(n, { q: fr.by[0], t });
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
let best = [];
|
|
1108
|
+
let most = 0;
|
|
1109
|
+
for (const n of nx) {
|
|
1110
|
+
const k = support.get(n)?.size ?? 0;
|
|
1111
|
+
if (k === 0)
|
|
1112
|
+
continue;
|
|
1113
|
+
if (k > most) {
|
|
1114
|
+
best = [n];
|
|
1115
|
+
most = k;
|
|
1116
|
+
}
|
|
1117
|
+
else if (k === most)
|
|
1118
|
+
best.push(n);
|
|
1119
|
+
}
|
|
1120
|
+
if (best.length === 0)
|
|
1121
|
+
return none;
|
|
1122
|
+
if (ctx.meter)
|
|
1123
|
+
ctx.meter.coInstanceNamings++;
|
|
1124
|
+
const first = via.get(best[0]);
|
|
1125
|
+
if (ctx.trace && first !== undefined) {
|
|
1126
|
+
ctx.trace.step("askedByCoInstance", [
|
|
1127
|
+
rItemShort(ctx, id, "node"),
|
|
1128
|
+
rItemShort(ctx, first.q, "co-instance"),
|
|
1129
|
+
rItemShort(ctx, first.t, "asked"),
|
|
1130
|
+
], best.map((n) => rItemShort(ctx, n, "named")), `${nx.length} continuations — no establishing context is witnessed; ` +
|
|
1131
|
+
`${most} co-instance(s) of the question carry the relation to ` +
|
|
1132
|
+
`${best.length === 1 ? "one" : best.length} of them`);
|
|
1133
|
+
}
|
|
1134
|
+
const evidence = new Map();
|
|
1135
|
+
for (const n of best)
|
|
1136
|
+
evidence.set(n, spans.get(n) ?? []);
|
|
1137
|
+
return { named: best, spans: evidence };
|
|
1138
|
+
}
|
|
1139
|
+
/** The relation frames the question's co-instances carry — a property of the
|
|
1140
|
+
* QUESTION, not of the node asked about, so it is read once per question
|
|
1141
|
+
* (and once per walk material) and every node only pays the exact lookups.
|
|
1142
|
+
* A question the corpus holds verbatim is its own instance and reads none. */
|
|
1143
|
+
function relationFrames(ctx, asked, allowance) {
|
|
1144
|
+
// A co-instance is the question's frame around ONE other filler, so it is
|
|
1145
|
+
// read at most to twice the question's length.
|
|
1146
|
+
const formCap = 2 * asked.bytes.length;
|
|
1147
|
+
const hit = frameMemo.get(asked);
|
|
1148
|
+
if (hit !== undefined && !ctx.trace)
|
|
1149
|
+
return hit;
|
|
1150
|
+
const whole = ctx._edgeAsked;
|
|
1151
|
+
// THE PROPOSALS ARE THE CLIMB'S. The consensus climb already scored the
|
|
1152
|
+
// stored forms the question's regions reach — measured on the 2Wiki
|
|
1153
|
+
// fixture with one-hop questions, the co-instances were among its points —
|
|
1154
|
+
// so the tier reads co-instances from those and climbs nothing of its own.
|
|
1155
|
+
// Before the climb has run there is nothing to read, and nothing is
|
|
1156
|
+
// remembered: a later ask, after the climb, reads its points.
|
|
1157
|
+
const points = whole?.points;
|
|
1158
|
+
if (points === undefined)
|
|
1159
|
+
return [];
|
|
1160
|
+
const frames = [];
|
|
1161
|
+
frameMemo.set(asked, frames);
|
|
1162
|
+
if (whole !== null && resolve(ctx, whole.bytes) !== null)
|
|
1163
|
+
return frames;
|
|
1164
|
+
const W = ctx.space.maxGroup;
|
|
1165
|
+
const cache = getStructCache(ctx);
|
|
1166
|
+
const deposited = (c) => !cachedHasParents(ctx, c, cache) && !ctx.store.hasContainers(c);
|
|
1167
|
+
const spelled = new Map();
|
|
1168
|
+
// Most corroborated first (the climb's own ranking), at most
|
|
1169
|
+
// `chainReach(W)` read — the exact tier's own floor.
|
|
1170
|
+
const proposals = points.filter((c) => cachedHasNext(ctx, c, cache))
|
|
1171
|
+
.slice(0, Math.min(allowance, chainReach(W)));
|
|
1172
|
+
for (const q of proposals) {
|
|
1173
|
+
if (!deposited(q))
|
|
1174
|
+
continue;
|
|
1175
|
+
const raw = read(ctx, q, formCap + 1);
|
|
1176
|
+
if (raw.length > formCap)
|
|
1177
|
+
continue;
|
|
1178
|
+
if (ctx.meter)
|
|
1179
|
+
ctx.meter.coInstanceReads++;
|
|
1180
|
+
const co = coInstanceFiller(ctx, raw, [asked.index], asked.bytes);
|
|
1181
|
+
if (co === null)
|
|
1182
|
+
continue;
|
|
1183
|
+
const [fs, fe] = co.span;
|
|
1184
|
+
const filler = raw.subarray(fs, fe);
|
|
1185
|
+
for (const f of ctx.store.nextFirst(q, W)) {
|
|
1186
|
+
for (const c of ctx.store.prevFirst(f, allowance)) {
|
|
1187
|
+
if (c === q || !deposited(c))
|
|
1188
|
+
continue;
|
|
1189
|
+
const cb = read(ctx, c, formCap + 1);
|
|
1190
|
+
const at = indexOf(cb, filler, 0);
|
|
1191
|
+
if (at < 0)
|
|
1192
|
+
continue;
|
|
1193
|
+
const prefix = cb.subarray(0, at);
|
|
1194
|
+
const suffix = cb.subarray(at + filler.length);
|
|
1195
|
+
if (prefix.length + suffix.length === 0)
|
|
1196
|
+
continue;
|
|
1197
|
+
const key = latin1(prefix) + "\u0000" + latin1(suffix);
|
|
1198
|
+
const known = spelled.get(key);
|
|
1199
|
+
if (known === undefined) {
|
|
1200
|
+
spelled.set(key, { by: [q], prefix, suffix, spans: co.spans });
|
|
1201
|
+
}
|
|
1202
|
+
else if (!known.by.includes(q))
|
|
1203
|
+
known.by.push(q);
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
// ONE INSTANCE AGREES WITH NOTHING. A relation is read off the corpus only
|
|
1208
|
+
// where two co-instances spell it the same way — the agreement `reference`
|
|
1209
|
+
// demands of a frame (MIN_INSTANCES), for the same reason: a single
|
|
1210
|
+
// coincidental alignment is not evidence of what the frame means. Measured
|
|
1211
|
+
// on the trained store, long dialogue turns proposed hundreds of one-off
|
|
1212
|
+
// "frames", each an exact lookup for every node asked about.
|
|
1213
|
+
for (const fr of spelled.values())
|
|
1214
|
+
if (fr.by.length >= 2)
|
|
1215
|
+
frames.push(fr);
|
|
1216
|
+
frames.sort((a, b) => b.by.length - a.by.length);
|
|
1217
|
+
return frames;
|
|
1218
|
+
}
|
|
1219
|
+
const frameMemo = new WeakMap();
|
|
893
1220
|
/** The perceived gist of a candidate node, through the session gist cache.
|
|
894
1221
|
* Re-gisting a candidate is a full river fold of its bytes — the measured
|
|
895
1222
|
* recall bottleneck (a hub context offers up to √N continuations, EACH
|
package/dist/src/mind/types.d.ts
CHANGED
|
@@ -374,10 +374,13 @@ export interface MindContext extends GraphSearchHost {
|
|
|
374
374
|
/** The question currently being answered, as the material `chooseNext`'s
|
|
375
375
|
* exact tier witnesses a continuation's establishing contexts against —
|
|
376
376
|
* its bytes (canonical when the response's canon preserves offsets) and
|
|
377
|
-
* their window index. Set and cleared with `_edgeGuide`.
|
|
377
|
+
* their window index. Set and cleared with `_edgeGuide`. `points` are the
|
|
378
|
+
* anchors the response's consensus climb scored, once it has climbed —
|
|
379
|
+
* the proposals the exact tier reads co-instances from. */
|
|
378
380
|
_edgeAsked: {
|
|
379
381
|
bytes: Uint8Array;
|
|
380
382
|
index: WindowIndex;
|
|
383
|
+
points?: readonly number[];
|
|
381
384
|
} | null;
|
|
382
385
|
_edgeChoice: Map<number, number>;
|
|
383
386
|
_prevSeen: Set<number> | null;
|
package/docs/INDEX.md
CHANGED
|
@@ -21,23 +21,23 @@ proof in `test/` (pins that fail when the law is broken).
|
|
|
21
21
|
|
|
22
22
|
## Architecture laws (15)
|
|
23
23
|
|
|
24
|
-
| Law | File | Summary
|
|
25
|
-
| --- | ------------------------------------------- |
|
|
26
|
-
| 1 | `docs/architecture/determinism.md` | No `Math.random`/`Date.now` in behaviour; seed-derived randomness; corpus-determined tie-breaks
|
|
27
|
-
| 2 | `docs/architecture/thresholds.md` | Every decision cutoff derived in `geometry.ts` over D/W/N; no tunable knobs
|
|
28
|
-
| 3 | `docs/architecture/exact-vs-approximate.md` | Vector scores rank only; identity via content-addressed lookup; six graded ladders
|
|
29
|
-
| 4 | `docs/architecture/cost-model.md` | Single ladder `MICRO`/`STEP`/`CONCEPT`/`PASS`; weight `moves + PASS·unaccounted`; `STEP`-grade compare
|
|
30
|
-
| 5 | `docs/architecture/match-project.md` | Shared `match.ts` family (`locate`/`alignGraded`/`frameSlots`/`project`); voicing gates belong to consumers
|
|
31
|
-
| 6 | `docs/architecture/mechanism-market.md` | `PipelineMechanism` (`floor`/`run`/`parse`); admissible-floor pruning, investment discipline, run-ahead bounds
|
|
32
|
-
| 7 | `docs/architecture/commonality.md` | Three: global (`reachOf`+`dominates`), weave-local (`depth[]`), window rarity
|
|
33
|
-
| 8 | `docs/architecture/bounded-reads.md` | No per-query read grows with N; `hubBound=√N` enforced at store via LIMIT/probe/prefix caps
|
|
34
|
-
| 9 | `docs/architecture/store.md` | `AbstractStore` owns dedup/indexing/batch; `store-sqlite.ts` is thin wrappers; canon index optional
|
|
35
|
-
| 10 | `docs/architecture/fold-contract.md` | `perceiveDeposit` and `perceive` agree; the read side names a branch as `intern` does; `contentLevels` is single boundary rule; no W/offset dependence
|
|
36
|
-
| 11 | `docs/architecture/memoization.md` | `Precomputed` is per-response lazy cache (promise-cached async); `beginResponse`/`endResponse` lifecycle
|
|
37
|
-
| 12 | `docs/architecture/saturation.md` | Every walk names a deciding saturation beside its cap; cap is safety net, not decision
|
|
38
|
-
| 13 | `docs/architecture/meter.md` | `meter.ts` is write-only work accounting; counts are exact, phases nest
|
|
39
|
-
| 14 | `docs/architecture/closure.md` | A derivation is closed when its structure accounts for the question's remainder; every transition asks that law, one engine walks the layers
|
|
40
|
-
| 15 | `docs/architecture/evidence.md` | A stored form is identified when the material at hand (question ∪ the node a derivation stands on) witnesses every byte of it, order-free; the question NAMES a continuation through its establishing context; a step it did not name pays from what is still owed | `test/154`
|
|
24
|
+
| Law | File | Summary | Pins |
|
|
25
|
+
| --- | ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------- |
|
|
26
|
+
| 1 | `docs/architecture/determinism.md` | No `Math.random`/`Date.now` in behaviour; seed-derived randomness; corpus-determined tie-breaks | `test/20` |
|
|
27
|
+
| 2 | `docs/architecture/thresholds.md` | Every decision cutoff derived in `geometry.ts` over D/W/N; no tunable knobs | `test/40`, `test/64` |
|
|
28
|
+
| 3 | `docs/architecture/exact-vs-approximate.md` | Vector scores rank only; identity via content-addressed lookup; six graded ladders | `test/51` |
|
|
29
|
+
| 4 | `docs/architecture/cost-model.md` | Single ladder `MICRO`/`STEP`/`CONCEPT`/`PASS`; weight `moves + PASS·unaccounted`; `STEP`-grade compare | `test/04`, `test/55` |
|
|
30
|
+
| 5 | `docs/architecture/match-project.md` | Shared `match.ts` family (`locate`/`alignGraded`/`frameSlots`/`project`); voicing gates belong to consumers | `test/24`, `test/76` |
|
|
31
|
+
| 6 | `docs/architecture/mechanism-market.md` | `PipelineMechanism` (`floor`/`run`/`parse`); admissible-floor pruning, investment discipline, run-ahead bounds | `test/01`, `test/04`, `test/153` |
|
|
32
|
+
| 7 | `docs/architecture/commonality.md` | Three: global (`reachOf`+`dominates`), weave-local (`depth[]`), window rarity | `test/17`, `test/34` |
|
|
33
|
+
| 8 | `docs/architecture/bounded-reads.md` | No per-query read grows with N; `hubBound=√N` enforced at store via LIMIT/probe/prefix caps | `test/77`, `test/90` |
|
|
34
|
+
| 9 | `docs/architecture/store.md` | `AbstractStore` owns dedup/indexing/batch; `store-sqlite.ts` is thin wrappers; canon index optional | `test/08` |
|
|
35
|
+
| 10 | `docs/architecture/fold-contract.md` | `perceiveDeposit` and `perceive` agree; the read side names a branch as `intern` does; `contentLevels` is single boundary rule; no W/offset dependence | `test/59`, `test/63`, `test/148`, `test/152` |
|
|
36
|
+
| 11 | `docs/architecture/memoization.md` | `Precomputed` is per-response lazy cache (promise-cached async); `beginResponse`/`endResponse` lifecycle | `test/42` |
|
|
37
|
+
| 12 | `docs/architecture/saturation.md` | Every walk names a deciding saturation beside its cap; cap is safety net, not decision | `test/27`, `test/16` |
|
|
38
|
+
| 13 | `docs/architecture/meter.md` | `meter.ts` is write-only work accounting; counts are exact, phases nest | `test/55` |
|
|
39
|
+
| 14 | `docs/architecture/closure.md` | A derivation is closed when its structure accounts for the question's remainder; every transition asks that law, one engine walks the layers | `test/133`–`151` |
|
|
40
|
+
| 15 | `docs/architecture/evidence.md` | A stored form is identified when the material at hand (question ∪ the node a derivation stands on) witnesses every byte of it, order-free; the question NAMES a continuation through its establishing context, or through another instance of its frame (a co-instance, never voiced as the answer); a step it did not name pays from what is still owed | `test/154`, `test/155` |
|
|
41
41
|
|
|
42
42
|
## Mechanisms (8)
|
|
43
43
|
|
package/docs/INVARIANTS.md
CHANGED
|
@@ -16,4 +16,4 @@
|
|
|
16
16
|
| 12 | Meter contracts | `src/meter.ts:Meter,PhaseCost,time` `src/mind/pipeline-mechanism.ts:Precomputed.shared` | `test/55` | `meter.md` |
|
|
17
17
|
| 13 | Saturation | `traverse.ts:edgeAncestors,types.ts:SaturationReason` `src/mind/junction.ts:junctionContainersFrom` `src/mind/resonance.ts:pivotInto` | `test/27` `test/16` | `saturation.md` |
|
|
18
18
|
| 14 | Closure | `src/mind/derivation.ts:admissible,advance,closeOver` | `test/133`–`151` | `closure.md` |
|
|
19
|
-
| 15 | Witnessed evidence | `src/mind/evidence.ts:witness,windowIndex` `src/mind/traverse.ts:chooseNext,askedEvidence,namedContinuations,scaffoldExtents`
|
|
19
|
+
| 15 | Witnessed evidence | `src/mind/evidence.ts:witness,windowIndex` `src/mind/traverse.ts:chooseNext,askedEvidence,namedContinuations,answersOtherQuestions,coInstanceFiller,scaffoldExtents` | `test/154`, `test/155` | `evidence.md` |
|