@hviana/sema 0.9.1 → 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 +19 -0
- package/dist/src/meter.js +19 -0
- package/dist/src/mind/evidence.d.ts +30 -0
- package/dist/src/mind/evidence.js +102 -0
- 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 +25 -3
- package/dist/src/mind/mechanisms/recall.js +93 -9
- package/dist/src/mind/mechanisms/reference.js +25 -0
- package/dist/src/mind/mind.d.ts +7 -0
- package/dist/src/mind/mind.js +3 -0
- package/dist/src/mind/pipeline-mechanism.js +15 -1
- package/dist/src/mind/pipeline.js +51 -8
- package/dist/src/mind/reasoning.js +65 -18
- package/dist/src/mind/resonance.d.ts +3 -2
- package/dist/src/mind/resonance.js +3 -2
- package/dist/src/mind/traverse.d.ts +94 -2
- package/dist/src/mind/traverse.js +611 -7
- package/dist/src/mind/types.d.ts +12 -0
- package/docs/INDEX.md +18 -17
- package/docs/INVARIANTS.md +1 -0
- package/docs/architecture/evidence.md +256 -0
- package/docs/architecture/exact-vs-approximate.md +10 -9
- package/jsr.json +1 -1
- package/package.json +1 -1
- package/src/meter.ts +19 -0
- package/src/mind/evidence.ts +125 -0
- package/src/mind/mechanisms/cast.ts +77 -3
- package/src/mind/mechanisms/cover.ts +42 -3
- package/src/mind/mechanisms/recall.ts +123 -11
- package/src/mind/mechanisms/reference.ts +24 -1
- package/src/mind/mind.ts +6 -0
- package/src/mind/pipeline-mechanism.ts +15 -1
- package/src/mind/pipeline.ts +64 -8
- package/src/mind/reasoning.ts +82 -17
- package/src/mind/resonance.ts +3 -2
- package/src/mind/traverse.ts +652 -7
- package/src/mind/types.ts +10 -0
- package/test/154-the-question-names-the-step.test.mjs +368 -0
- 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
package/dist/src/meter.d.ts
CHANGED
|
@@ -197,6 +197,25 @@ export declare class Meter {
|
|
|
197
197
|
/** Times the reasoner pivoted on a span its answer contains and stepped
|
|
198
198
|
* across that fact. */
|
|
199
199
|
pivotSteps: number;
|
|
200
|
+
/** `chooseNext` picks the question NAMED — a continuation one of whose own
|
|
201
|
+
* establishing contexts the question (plus the node) wholly witnesses
|
|
202
|
+
* (traverse.ts, the exact tier). */
|
|
203
|
+
askedContinuations: number;
|
|
204
|
+
/** Predecessor rows that exact tier read, against its shared √N budget. */
|
|
205
|
+
askedPredecessorReads: number;
|
|
206
|
+
/** Times the tier abstained on a read it could not trust: the continuations
|
|
207
|
+
* came back at the √N cap, or its predecessor budget ran out before every
|
|
208
|
+
* continuation was asked about — the distributional ladder decided. */
|
|
209
|
+
askedReadsSaturated: number;
|
|
210
|
+
/** Picks named by a CO-INSTANCE of the question — another instance of its
|
|
211
|
+
* frame whose continuation carries the relation over to this node by an
|
|
212
|
+
* exact substitution (traverse.ts, `byCoInstance`). */
|
|
213
|
+
coInstanceNamings: number;
|
|
214
|
+
/** Proposed co-instances that tier read and witnessed. */
|
|
215
|
+
coInstanceReads: number;
|
|
216
|
+
/** Cover sites dropped as FRAGMENTS whose several continuations the question
|
|
217
|
+
* names none of (mechanisms/cover.ts). */
|
|
218
|
+
unaskedFragments: number;
|
|
200
219
|
/** Canon probes REFUSED because the canon budget ran out — the one thing the
|
|
201
220
|
* budget does that nothing could see. The budget itself is derived
|
|
202
221
|
* (`bytes.length · chainReach(W)²`, recognition.ts), and the cheap exact route
|
package/dist/src/meter.js
CHANGED
|
@@ -207,6 +207,25 @@ export class Meter {
|
|
|
207
207
|
/** Times the reasoner pivoted on a span its answer contains and stepped
|
|
208
208
|
* across that fact. */
|
|
209
209
|
pivotSteps = 0;
|
|
210
|
+
/** `chooseNext` picks the question NAMED — a continuation one of whose own
|
|
211
|
+
* establishing contexts the question (plus the node) wholly witnesses
|
|
212
|
+
* (traverse.ts, the exact tier). */
|
|
213
|
+
askedContinuations = 0;
|
|
214
|
+
/** Predecessor rows that exact tier read, against its shared √N budget. */
|
|
215
|
+
askedPredecessorReads = 0;
|
|
216
|
+
/** Times the tier abstained on a read it could not trust: the continuations
|
|
217
|
+
* came back at the √N cap, or its predecessor budget ran out before every
|
|
218
|
+
* continuation was asked about — the distributional ladder decided. */
|
|
219
|
+
askedReadsSaturated = 0;
|
|
220
|
+
/** Picks named by a CO-INSTANCE of the question — another instance of its
|
|
221
|
+
* frame whose continuation carries the relation over to this node by an
|
|
222
|
+
* exact substitution (traverse.ts, `byCoInstance`). */
|
|
223
|
+
coInstanceNamings = 0;
|
|
224
|
+
/** Proposed co-instances that tier read and witnessed. */
|
|
225
|
+
coInstanceReads = 0;
|
|
226
|
+
/** Cover sites dropped as FRAGMENTS whose several continuations the question
|
|
227
|
+
* names none of (mechanisms/cover.ts). */
|
|
228
|
+
unaskedFragments = 0;
|
|
210
229
|
/** Canon probes REFUSED because the canon budget ran out — the one thing the
|
|
211
230
|
* budget does that nothing could see. The budget itself is derived
|
|
212
231
|
* (`bytes.length · chainReach(W)²`, recognition.ts), and the cheap exact route
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/** Where each W-window of one source first occurs. Built once per source and
|
|
2
|
+
* reused across every form asked against it. */
|
|
3
|
+
export type WindowIndex = Map<string, number>;
|
|
4
|
+
export declare function windowIndex(bytes: Uint8Array, W: number): WindowIndex;
|
|
5
|
+
/** The windows of `index` (over `bytes`) that `spoken` does not hold — what
|
|
6
|
+
* of the question no product of the derivation has restated yet. The keys
|
|
7
|
+
* keep their positions in `bytes`, so a witnessing span still names the
|
|
8
|
+
* asker's bytes. */
|
|
9
|
+
export declare function unspoken(index: WindowIndex, spoken: ReadonlyArray<WindowIndex>): WindowIndex;
|
|
10
|
+
/** How a form is witnessed by a list of sources. */
|
|
11
|
+
export interface Witnessing {
|
|
12
|
+
/** Every byte of the form lies in a window some source holds. */
|
|
13
|
+
complete: boolean;
|
|
14
|
+
/** The windows SOURCE 0 alone supplied — windows no later source holds — as
|
|
15
|
+
* merged spans of source 0. With the question as source 0, this is what the
|
|
16
|
+
* asker said about the form that the derivation did not already have. */
|
|
17
|
+
spans: Array<[number, number]>;
|
|
18
|
+
/** Bytes of source 0 inside `spans`. */
|
|
19
|
+
bytes: number;
|
|
20
|
+
/** The form's own bytes no source witnesses, as merged spans of the FORM —
|
|
21
|
+
* empty exactly when `complete`. ONE residue span is the shape of a
|
|
22
|
+
* co-instance: the same frame around a different filler (`When was Peter
|
|
23
|
+
* Jackson born?` read against `When was the director of film Jinpa
|
|
24
|
+
* born?` leaves `Peter Jackson`). */
|
|
25
|
+
residue: Array<[number, number]>;
|
|
26
|
+
}
|
|
27
|
+
/** Witness `form` against `sources` (their window indexes, same order). A
|
|
28
|
+
* window is credited to the LAST source holding it — so source 0 is credited
|
|
29
|
+
* only with what nothing else at hand supplies. */
|
|
30
|
+
export declare function witness(form: Uint8Array, indexes: ReadonlyArray<WindowIndex>, W: number): Witnessing;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// evidence.ts — what of a stored form the material at hand WITNESSES.
|
|
2
|
+
//
|
|
3
|
+
// A stored form is WITNESSED by some material when every one of its bytes lies
|
|
4
|
+
// inside a W-window that occurs literally in that material — in any order, at
|
|
5
|
+
// any place. It is the order-free reading of correspondence (`alignRuns` is
|
|
6
|
+
// its run-producing sibling, `junctionContainersFrom(…, unordered)` its
|
|
7
|
+
// container-finding one): a learnt form is evidenced by bytes that hold all of
|
|
8
|
+
// its windows, whichever way the asker happened to arrange them.
|
|
9
|
+
//
|
|
10
|
+
// The material is a LIST of sources because what a derivation has at hand is
|
|
11
|
+
// more than the question: the node it stands on is material too. A trained
|
|
12
|
+
// question `Edmond T. Gréville place of death` is in neither the asker's
|
|
13
|
+
// `Where was the place of death of the director of film Beat Girl?` nor the
|
|
14
|
+
// fact `The director of Beat Girl is Edmond T. Gréville.` the first hop reached
|
|
15
|
+
// — and both together hold every byte of it. The witness records which source
|
|
16
|
+
// held each window, so a consumer can tell the question's share (what the asker
|
|
17
|
+
// SAID about the form) from what the derivation itself brought.
|
|
18
|
+
//
|
|
19
|
+
// Exact, deterministic and linear: one window index per source, one probe per
|
|
20
|
+
// window of the form. Below one window a byte agreement is chance (the floor
|
|
21
|
+
// identityBar, attestedQ and the site test all draw), so a form shorter than W
|
|
22
|
+
// is never witnessed.
|
|
23
|
+
//
|
|
24
|
+
// Layering: bytes only — importable from traverse.ts and everything above it.
|
|
25
|
+
import { latin1 } from "../bytes.js";
|
|
26
|
+
export function windowIndex(bytes, W) {
|
|
27
|
+
const index = new Map();
|
|
28
|
+
for (let o = 0; o + W <= bytes.length; o++) {
|
|
29
|
+
const key = latin1(bytes.subarray(o, o + W));
|
|
30
|
+
if (!index.has(key))
|
|
31
|
+
index.set(key, o);
|
|
32
|
+
}
|
|
33
|
+
return index;
|
|
34
|
+
}
|
|
35
|
+
/** The windows of `index` (over `bytes`) that `spoken` does not hold — what
|
|
36
|
+
* of the question no product of the derivation has restated yet. The keys
|
|
37
|
+
* keep their positions in `bytes`, so a witnessing span still names the
|
|
38
|
+
* asker's bytes. */
|
|
39
|
+
export function unspoken(index, spoken) {
|
|
40
|
+
const out = new Map();
|
|
41
|
+
for (const [key, at] of index) {
|
|
42
|
+
if (!spoken.some((s) => s.has(key)))
|
|
43
|
+
out.set(key, at);
|
|
44
|
+
}
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
47
|
+
/** Witness `form` against `sources` (their window indexes, same order). A
|
|
48
|
+
* window is credited to the LAST source holding it — so source 0 is credited
|
|
49
|
+
* only with what nothing else at hand supplies. */
|
|
50
|
+
export function witness(form, indexes, W) {
|
|
51
|
+
if (form.length < W || indexes.length === 0) {
|
|
52
|
+
return {
|
|
53
|
+
complete: false,
|
|
54
|
+
spans: [],
|
|
55
|
+
bytes: 0,
|
|
56
|
+
residue: form.length > 0 ? [[0, form.length]] : [],
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
const covered = new Uint8Array(form.length);
|
|
60
|
+
const own = [];
|
|
61
|
+
for (let o = 0; o + W <= form.length; o++) {
|
|
62
|
+
const key = latin1(form.subarray(o, o + W));
|
|
63
|
+
let at = -1;
|
|
64
|
+
let from = -1;
|
|
65
|
+
for (let s = indexes.length - 1; s >= 0; s--) {
|
|
66
|
+
const p = indexes[s].get(key);
|
|
67
|
+
if (p !== undefined) {
|
|
68
|
+
at = p;
|
|
69
|
+
from = s;
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (from < 0)
|
|
74
|
+
continue;
|
|
75
|
+
covered.fill(1, o, o + W);
|
|
76
|
+
if (from === 0)
|
|
77
|
+
own.push([at, at + W]);
|
|
78
|
+
}
|
|
79
|
+
const residue = [];
|
|
80
|
+
for (let i = 0; i < form.length; i++) {
|
|
81
|
+
if (covered[i])
|
|
82
|
+
continue;
|
|
83
|
+
const last = residue[residue.length - 1];
|
|
84
|
+
if (last !== undefined && last[1] === i)
|
|
85
|
+
last[1] = i + 1;
|
|
86
|
+
else
|
|
87
|
+
residue.push([i, i + 1]);
|
|
88
|
+
}
|
|
89
|
+
own.sort((a, b) => a[0] - b[0]);
|
|
90
|
+
const spans = [];
|
|
91
|
+
for (const [s, e] of own) {
|
|
92
|
+
const last = spans[spans.length - 1];
|
|
93
|
+
if (last !== undefined && s <= last[1])
|
|
94
|
+
last[1] = Math.max(last[1], e);
|
|
95
|
+
else
|
|
96
|
+
spans.push([s, e]);
|
|
97
|
+
}
|
|
98
|
+
let bytes = 0;
|
|
99
|
+
for (const [s, e] of spans)
|
|
100
|
+
bytes += e - s;
|
|
101
|
+
return { complete: residue.length === 0, spans, bytes, residue };
|
|
102
|
+
}
|
|
@@ -37,7 +37,7 @@ export interface CastResult {
|
|
|
37
37
|
* painted by Leonardo da Vinci.") must be seated by that establishing
|
|
38
38
|
* sentence, NOT by its own biography fact — voicing the bio leaks exactly
|
|
39
39
|
* what a comparison must keep out, and loses the embedded "Mona Lisa"
|
|
40
|
-
* term C3
|
|
40
|
+
* term C3's further-hop candidate lives in.
|
|
41
41
|
*
|
|
42
42
|
* The distinguishing signal is content-addressed, not a count: a genuine
|
|
43
43
|
* establishing predecessor's bytes CONTAIN id's own bytes — it names or
|
|
@@ -11,11 +11,11 @@
|
|
|
11
11
|
// gate = the frame gate below + analogyStrength, projection = insert / project /
|
|
12
12
|
// juxtapose.
|
|
13
13
|
import { read } from "../primitives.js";
|
|
14
|
-
import { argmaxBy, corpusN, edgeAncestors, hubBound, sharedReachMemo, } from "../traverse.js";
|
|
14
|
+
import { answersOtherQuestions, argmaxBy, coInstanceFiller, corpusN, edgeAncestors, hubBound, hubWindows, offsetCanon, sharedReachMemo, } from "../traverse.js";
|
|
15
15
|
import { analogyStrength, follow, project, reverseContext, sharedFrameStrengthOf, } from "../match.js";
|
|
16
16
|
import { joinWithBridge } from "../resonance.js";
|
|
17
17
|
import { CONCEPT, STEP } from "../graph-search.js";
|
|
18
|
-
import { indexOf } from "../../bytes.js";
|
|
18
|
+
import { indexOf, latin1 } from "../../bytes.js";
|
|
19
19
|
import { consensusFloor, dominates } from "../../geometry.js";
|
|
20
20
|
import { restates, unexplainedSpans } from "../derivation.js";
|
|
21
21
|
import { rItem, rNode } from "../trace.js";
|
|
@@ -81,7 +81,7 @@ const MIN_WEAVE = 2;
|
|
|
81
81
|
* painted by Leonardo da Vinci.") must be seated by that establishing
|
|
82
82
|
* sentence, NOT by its own biography fact — voicing the bio leaks exactly
|
|
83
83
|
* what a comparison must keep out, and loses the embedded "Mona Lisa"
|
|
84
|
-
* term C3
|
|
84
|
+
* term C3's further-hop candidate lives in.
|
|
85
85
|
*
|
|
86
86
|
* The distinguishing signal is content-addressed, not a count: a genuine
|
|
87
87
|
* establishing predecessor's bytes CONTAIN id's own bytes — it names or
|
|
@@ -591,8 +591,16 @@ export async function counterfactualTransfer(ctx, query, pre) {
|
|
|
591
591
|
// its own fact — so the same bar applies. The displaced structure is only
|
|
592
592
|
// recognised as the slot being overridden and is never voiced, so it is
|
|
593
593
|
// deliberately not gated here.
|
|
594
|
+
// …and the substitute must lead somewhere FOR THIS QUESTION: a fragment
|
|
595
|
+
// whose continuations the question names none of answers other questions
|
|
596
|
+
// (traverse.ts, `answersOtherQuestions`). `ong)?`, the tail of every
|
|
597
|
+
// `… (… Song)?` question, was "named" by `What is the place of birth of the
|
|
598
|
+
// performer of song Heaven (Namie Amuro Song)?`, and redirection voiced
|
|
599
|
+
// its most-poured stranger's birthplace.
|
|
600
|
+
const stranger = last !== undefined &&
|
|
601
|
+
answersOtherQuestions(ctx, last.point.anchor, query.length, last.run.qe - last.run.qs);
|
|
594
602
|
if (last !== undefined && last.point !== dominant && displaced &&
|
|
595
|
-
voiceable(last.point)) {
|
|
603
|
+
voiceable(last.point) && !stranger) {
|
|
596
604
|
const g = await project(ctx, last.point.anchor, qv);
|
|
597
605
|
if (g !== null) {
|
|
598
606
|
ctx.trace?.step("projectCounterfactual", [
|
|
@@ -939,6 +947,42 @@ export async function counterfactualTransfer(ctx, query, pre) {
|
|
|
939
947
|
: [];
|
|
940
948
|
const cmpGaps = unexplainedSpans(query.length, cmpAccounted);
|
|
941
949
|
const cmpMaxGap = cmpGaps.reduce((n, [s, e]) => Math.max(n, e - s), 0);
|
|
950
|
+
// TWO THINGS NAMED. A comparison voices two structures, so the question
|
|
951
|
+
// must evidence the second one with material of its own: a W-window of the
|
|
952
|
+
// question that the analog holds — on its aligned runs, or anywhere in its
|
|
953
|
+
// own form under the response's equivalence (the witness reading,
|
|
954
|
+
// evidence.md) — and that is neither inside the dominant's runs nor corpus
|
|
955
|
+
// scaffolding (`hubWindows`, the reading of "what the question owes").
|
|
956
|
+
// `father of Frederick II?` reached `Peter III of Aragon father` through
|
|
957
|
+
// ` father`, which the dominant `Frederick II father` already holds, and
|
|
958
|
+
// ` of `, which every fact holds — one structure named, and the comparison
|
|
959
|
+
// glued the analog's bare question onto the answer (`…is Peter III of
|
|
960
|
+
// Aragon.Peter III of Aragon father`). `How is ice like steel?` names
|
|
961
|
+
// `Ice is cold` with `ice `, a window no byte-exact run aligns (the case
|
|
962
|
+
// differs) and the dominant `Steel is hard` lacks.
|
|
963
|
+
const analogOwnsEvidence = () => {
|
|
964
|
+
if (bestAnalog === null)
|
|
965
|
+
return false;
|
|
966
|
+
const W = ctx.space.maxGroup;
|
|
967
|
+
const hub = hubWindows(ctx, query);
|
|
968
|
+
const mine = runSpans(dominant);
|
|
969
|
+
const owns = (o) => !hub[o] && !mine.some(([ms, me]) => o >= ms && o + W <= me);
|
|
970
|
+
for (const [s, e] of runSpans(bestAnalog.point ?? bestAnalog.src)) {
|
|
971
|
+
for (let o = s; o + W <= e; o++)
|
|
972
|
+
if (owns(o))
|
|
973
|
+
return true;
|
|
974
|
+
}
|
|
975
|
+
const asked = ctx._edgeAsked;
|
|
976
|
+
if (asked === null)
|
|
977
|
+
return false;
|
|
978
|
+
const form = offsetCanon(ctx, read(ctx, bestAnalog.anchor, asked.bytes.length * W));
|
|
979
|
+
for (let o = 0; o + W <= form.length; o++) {
|
|
980
|
+
const at = asked.index.get(latin1(form.subarray(o, o + W)));
|
|
981
|
+
if (at !== undefined && owns(at))
|
|
982
|
+
return true;
|
|
983
|
+
}
|
|
984
|
+
return false;
|
|
985
|
+
};
|
|
942
986
|
// An analog that is not itself a directly ALIGNED point (point !== null —
|
|
943
987
|
// its own runs are query bytes, the query NAMED it) was only reached
|
|
944
988
|
// through a continuation hop or the structural-hub fallback. Voicing
|
|
@@ -1066,8 +1110,18 @@ export async function counterfactualTransfer(ctx, query, pre) {
|
|
|
1066
1110
|
// supply were never the ones that test is about.
|
|
1067
1111
|
const cmpDismisses = !bestHalo &&
|
|
1068
1112
|
dismissedKnownContent(ctx, query, cmpAccounted);
|
|
1113
|
+
// …and the dominant must be something the question is ABOUT. A co-instance
|
|
1114
|
+
// of the question (traverse.ts, `coInstanceFiller`) is its frame around
|
|
1115
|
+
// another filler, and its seat is that filler's own answer: `Where was the
|
|
1116
|
+
// performer of song God (Lennon Song) born?` compared `Where was Shakira
|
|
1117
|
+
// (Shakira Song) born?` with `John Lennon` and voiced Shakira's birthplace.
|
|
1118
|
+
const asked = ctx._edgeAsked;
|
|
1119
|
+
const dominantOtherInstance = asked !== null &&
|
|
1120
|
+
coInstanceFiller(ctx, read(ctx, dominant.anchor, 2 * query.length + 1), [asked.index], asked.bytes) !== null;
|
|
1069
1121
|
if (bestAnalog !== null &&
|
|
1070
1122
|
(bestHalo || analogNamed || rootTrusted) &&
|
|
1123
|
+
analogOwnsEvidence() &&
|
|
1124
|
+
!dominantOtherInstance &&
|
|
1071
1125
|
!cmpDismisses &&
|
|
1072
1126
|
queryScale(dominant.ctx.length) &&
|
|
1073
1127
|
roots.length <= 1 &&
|
|
@@ -1187,14 +1241,21 @@ export async function counterfactualTransfer(ctx, query, pre) {
|
|
|
1187
1241
|
? `the best analog carries no halo-tier company evidence, was never ` +
|
|
1188
1242
|
`named by the query, and no committed root's consensus vote ` +
|
|
1189
1243
|
`clears the floor, so comparison refuses to voice it`
|
|
1190
|
-
:
|
|
1191
|
-
? `
|
|
1192
|
-
`
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1244
|
+
: dominantOtherInstance
|
|
1245
|
+
? `the dominant is another instance of the question's frame — its ` +
|
|
1246
|
+
`seat is another filler's answer, not what the question asks about`
|
|
1247
|
+
: !analogOwnsEvidence()
|
|
1248
|
+
? `the question evidences the analog only with windows the dominant ` +
|
|
1249
|
+
`already holds or the corpus' scaffolding — it names one structure, ` +
|
|
1250
|
+
`not two, so there is nothing to compare`
|
|
1251
|
+
: cmpDismisses
|
|
1252
|
+
? `a frame-tier analog under an untrusted root dismisses stored ` +
|
|
1253
|
+
`query content its alignment never accounted for — comparison ` +
|
|
1254
|
+
`refuses to ignore what the store knows`
|
|
1255
|
+
: `comparison's own accounted evidence leaves a ${cmpMaxGap}-byte gap in ` +
|
|
1256
|
+
`a ${query.length}-byte query against a ${dominant.ctx.length}-byte ` +
|
|
1257
|
+
`dominant — too large to be mere framing — so it refuses rather ` +
|
|
1258
|
+
`than paper over it with an analog the query never asked about`);
|
|
1198
1259
|
}
|
|
1199
1260
|
t?.done(results.map((r) => rItem(r.bytes, "answer")), results.length > 0
|
|
1200
1261
|
? `${results.length} counterfactual schema(s) fired — the grounding decider weighs them`
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
// near-zero-cost incumbent that prunes the other mechanisms through the
|
|
10
10
|
// ordinary admissible-floor check, with no extension special-case anywhere.
|
|
11
11
|
import { read, resolve } from "../primitives.js";
|
|
12
|
-
import { guidedFirst, hubBound } from "../traverse.js";
|
|
12
|
+
import { answersOtherQuestions, guidedFirst, hubBound, scaffoldSpans, } from "../traverse.js";
|
|
13
13
|
import { conceptHop } from "../match.js";
|
|
14
14
|
import { bridge } from "../resonance.js";
|
|
15
15
|
import { liftAnswer, liftedScaffolding, segRestatesQuery } from "../types.js";
|
|
@@ -179,7 +179,7 @@ export const coverMechanism = {
|
|
|
179
179
|
const { rec, computed } = pre;
|
|
180
180
|
// Masking: computed spans are authoritative. Remove recognised sites
|
|
181
181
|
// that overlap any computed span before building the cover search.
|
|
182
|
-
|
|
182
|
+
let sites = computed.length === 0
|
|
183
183
|
? rec.sites
|
|
184
184
|
: rec.sites.filter((s) => !computed.some((u) => s.start < u.j && u.i < s.end));
|
|
185
185
|
if (computed.length > 0 && sites.length < rec.sites.length) {
|
|
@@ -191,6 +191,19 @@ export const coverMechanism = {
|
|
|
191
191
|
s.end,
|
|
192
192
|
])), "a computation always wins: recognised forms overlapping a computed span are dropped");
|
|
193
193
|
}
|
|
194
|
+
// A FRAGMENT ANSWERS OTHER QUESTIONS (traverse.ts) — and the cover used to
|
|
195
|
+
// account the fragment's bytes as explained by the stranger's answer.
|
|
196
|
+
const leading = sites.filter((s) => !answersOtherQuestions(ctx, s.payload, query.length, s.end - s.start));
|
|
197
|
+
if (leading.length < sites.length) {
|
|
198
|
+
if (ctx.meter) {
|
|
199
|
+
ctx.meter.unaskedFragments += sites.length - leading.length;
|
|
200
|
+
}
|
|
201
|
+
ctx.trace?.step("unaskedFragments", sites.filter((s) => !leading.includes(s)).map((s) => rItem(query.subarray(s.start, s.end), "fragment", s.payload, [
|
|
202
|
+
s.start,
|
|
203
|
+
s.end,
|
|
204
|
+
])), [], "a piece of other forms whose continuations the question names none of — it answers other questions");
|
|
205
|
+
sites = leading;
|
|
206
|
+
}
|
|
194
207
|
if (sites.length === 0 && computed.length === 0)
|
|
195
208
|
return [];
|
|
196
209
|
const connectors = ctx.meter
|
|
@@ -278,8 +291,17 @@ export const coverMechanism = {
|
|
|
278
291
|
// restated span contributes nothing to the composed answer, so it must
|
|
279
292
|
// not be priced as if it did (PASS-carried bytes are priced already;
|
|
280
293
|
// the diagnostic label reflects the same distinction).
|
|
294
|
+
//
|
|
295
|
+
// …and a span made of nothing but corpus-global scaffolding names nothing:
|
|
296
|
+
// every window of it is a piece of more than √N stored forms, so the form
|
|
297
|
+
// recognised there — the song `What`, in the trained store — is one of
|
|
298
|
+
// thousands it could be. Voicing that form's fact explains no byte the
|
|
299
|
+
// asker owes: measured, `What country is Jerry Bock a citizen of?` was won
|
|
300
|
+
// by `The performer of What is Melinda Marx.` glued onto the right fact.
|
|
301
|
+
const scaffold = scaffoldSpans(ctx, query);
|
|
281
302
|
const accounted = segs
|
|
282
|
-
.filter((s) => s.rec && !segRestatesQuery(s, query, query.length, W)
|
|
303
|
+
.filter((s) => s.rec && !segRestatesQuery(s, query, query.length, W) &&
|
|
304
|
+
!scaffold.some(([a, b]) => a <= s.i && s.j <= b))
|
|
283
305
|
.map((s) => [s.i, s.j]);
|
|
284
306
|
return [{
|
|
285
307
|
bytes: composed,
|
|
@@ -7,7 +7,7 @@ import { cosine } from "../../vec.js";
|
|
|
7
7
|
import { consensusFloor, dominates, identityBar, reachThreshold, significanceBar, } from "../../geometry.js";
|
|
8
8
|
import { gistOf, read, resolve } from "../primitives.js";
|
|
9
9
|
import { indexOf } from "../../bytes.js";
|
|
10
|
-
import { allWindowsAreScaffolding, corpusN, hubBound } from "../traverse.js";
|
|
10
|
+
import { allWindowsAreScaffolding, answersOtherQuestions, askedEvidence, canonHeldPoints, coInstanceFiller, corpusN, guidedFirst, hubBound, namedContinuations, } from "../traverse.js";
|
|
11
11
|
import { follow, project, reverseContext, voicesDisplacedFiller, } from "../match.js";
|
|
12
12
|
import { CONCEPT, STEP } from "../graph-search.js";
|
|
13
13
|
import { restates as lawRestates } from "../derivation.js";
|
|
@@ -55,11 +55,10 @@ export async function recallByResonance(ctx, query, pre) {
|
|
|
55
55
|
// constituent bar is the same two-quanta (2W) reading confluence binds
|
|
56
56
|
// under, nested recognitions collapse to their MAXIMAL span, and two
|
|
57
57
|
// distinct maximal arguments mean the query asks about neither alone.
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
ctx.store.hasNext(s.payload));
|
|
58
|
+
// The argument binding, given its candidate arguments (`args`) and the
|
|
59
|
+
// recognised fragments that answer other questions (`strangerIds`).
|
|
60
|
+
const W2 = 2 * ctx.space.maxGroup;
|
|
61
|
+
const bindArgument = async (args, strangerIds) => {
|
|
63
62
|
// Maximal spans by one sorted sweep (starts ascending, ties longest
|
|
64
63
|
// first): every earlier span starts at or before s, so s is contained
|
|
65
64
|
// exactly when the running max end already covers it. O(m log m) — a
|
|
@@ -86,11 +85,22 @@ export async function recallByResonance(ctx, query, pre) {
|
|
|
86
85
|
// binding to the argument's continuation would answer past content
|
|
87
86
|
// the query itself already carries forward. Derived from the same W2
|
|
88
87
|
// bar the argument itself is held to, never a separate tuned number.
|
|
88
|
+
// A fragment that answers other questions is not such a piece.
|
|
89
89
|
const hasSubstantialOutside = maximal.length === 1 &&
|
|
90
|
-
pre.rec.sites.some((s) => s.end - s.start >= W2 &&
|
|
90
|
+
pre.rec.sites.some((s) => s.end - s.start >= W2 && !strangerIds.has(s.payload) &&
|
|
91
91
|
(s.end <= maximal[0].start || s.start >= maximal[0].end));
|
|
92
92
|
if (maximal.length === 1 && !hasSubstantialOutside) {
|
|
93
93
|
const arg = maximal[0];
|
|
94
|
+
// An argument whose several continuations the question names none of
|
|
95
|
+
// outright would be followed by popularity. Another instance of the
|
|
96
|
+
// question may name one (traverse.ts, `byCoInstance`), and its
|
|
97
|
+
// proposals are the consensus climb's points — so the climb is asked
|
|
98
|
+
// for first, exactly where the choice would otherwise be blind.
|
|
99
|
+
const asked = ctx._edgeAsked;
|
|
100
|
+
if (asked !== null && asked.points === undefined &&
|
|
101
|
+
ctx.store.nextFirst(arg.payload, 2).length >= 2 &&
|
|
102
|
+
namedContinuations(ctx, arg.payload, asked) === null)
|
|
103
|
+
await pre.attention();
|
|
94
104
|
const g = await follow(ctx, arg.payload, queryGist);
|
|
95
105
|
// The same "no restated fragment" guard tier 2 applies below (§ "the
|
|
96
106
|
// anchor cleared the consensus floor..."): a followed continuation
|
|
@@ -102,9 +112,56 @@ export async function recallByResonance(ctx, query, pre) {
|
|
|
102
112
|
// conversation reads as if it were the next thing to say.
|
|
103
113
|
if (g !== null && g.length > 0 &&
|
|
104
114
|
!lawRestates(query, g, 0, { proper: true })) {
|
|
105
|
-
|
|
115
|
+
// EVIDENCE TRAVELS: when the question NAMED the continuation followed
|
|
116
|
+
// (traverse.ts, the exact tier — `Who is the father of Frederick II?`
|
|
117
|
+
// witnesses the father fact's own question `Frederick II father`), the
|
|
118
|
+
// spans that named it are explained too, not only the argument.
|
|
119
|
+
const hop = guidedFirst(ctx, arg.payload);
|
|
120
|
+
const named = hop === undefined
|
|
121
|
+
? []
|
|
122
|
+
: askedEvidence(ctx, arg.payload, hop);
|
|
123
|
+
return ground(g, "argument binding — the query's sole edge-source constituent, continuation followed", [[arg.start, arg.end], ...named], STEP);
|
|
106
124
|
}
|
|
107
125
|
}
|
|
126
|
+
return null;
|
|
127
|
+
};
|
|
128
|
+
let canonArgumentPending = false;
|
|
129
|
+
let strangers = new Set();
|
|
130
|
+
if (qId === null) {
|
|
131
|
+
const recognised = pre.rec.sites.filter((s) => s.end - s.start >= W2 &&
|
|
132
|
+
s.end - s.start < query.length &&
|
|
133
|
+
ctx.store.hasNext(s.payload));
|
|
134
|
+
// An argument must lead somewhere FOR THIS QUESTION: a fragment whose
|
|
135
|
+
// continuations the question names none of answers other questions
|
|
136
|
+
// (traverse.ts) — `director`, inside `When was the director of film Jinpa
|
|
137
|
+
// born?`, bound the most-poured of fifty-five directors. Such a fragment
|
|
138
|
+
// is no argument, and no independent piece of the query either.
|
|
139
|
+
const strangerIds = new Set();
|
|
140
|
+
for (const s of recognised) {
|
|
141
|
+
if (answersOtherQuestions(ctx, s.payload, query.length, s.end - s.start))
|
|
142
|
+
strangerIds.add(s.payload);
|
|
143
|
+
}
|
|
144
|
+
const args = recognised.filter((s) => !strangerIds.has(s.payload));
|
|
145
|
+
if (args.length === 0 && strangerIds.size > 0) {
|
|
146
|
+
if (ctx.meter)
|
|
147
|
+
ctx.meter.unaskedFragments += strangerIds.size;
|
|
148
|
+
ctx.trace?.step("unaskedFragments", recognised.filter((s) => strangerIds.has(s.payload)).map((s) => rItem(query.subarray(s.start, s.end), "fragment", s.payload, [
|
|
149
|
+
s.start,
|
|
150
|
+
s.end,
|
|
151
|
+
])), [], "the only arguments are pieces of other forms whose continuations the question names none of — they answer other questions");
|
|
152
|
+
}
|
|
153
|
+
const bound = await bindArgument(args, strangerIds);
|
|
154
|
+
if (bound !== null)
|
|
155
|
+
return bound;
|
|
156
|
+
// NO ARGUMENT BY BYTES IS NOT NO ARGUMENT. Recognition matches bytes, so
|
|
157
|
+
// `Man At Bath` (2Wiki title-cases its questions) is no site of the stored
|
|
158
|
+
// `Man at Bath`. When nothing recognised can bind, the points the
|
|
159
|
+
// consensus climb reaches that the question holds under the response's
|
|
160
|
+
// equivalence are arguments too (traverse.ts, `canonHeldPoints`) — read
|
|
161
|
+
// after the clean-resonance tier, which answers a near-identical question
|
|
162
|
+
// without any climb.
|
|
163
|
+
canonArgumentPending = ctx.canon !== null && args.length === 0;
|
|
164
|
+
strangers = strangerIds;
|
|
108
165
|
}
|
|
109
166
|
// The response's ONE top-k read (Precomputed.resonance) — the same list the
|
|
110
167
|
// frame inventory is assembled from, so a query that reaches both pays for a
|
|
@@ -178,6 +235,18 @@ export async function recallByResonance(ctx, query, pre) {
|
|
|
178
235
|
const reach = reachThreshold(ctx.space.maxGroup);
|
|
179
236
|
const fracOfQuery = (cos, otherLen) => Math.min(1, Math.max(0, cos - sig) *
|
|
180
237
|
Math.sqrt(otherLen / Math.max(1, query.length)));
|
|
238
|
+
// The argument the question holds only under the response's equivalence
|
|
239
|
+
// (above). Not gated on the whole-query resonance: a question whose only
|
|
240
|
+
// argument is a case variant (`… film Man At Bath work at?`) resonates
|
|
241
|
+
// below the significance bar as a whole.
|
|
242
|
+
if (canonArgumentPending) {
|
|
243
|
+
await pre.attention();
|
|
244
|
+
const held = canonHeldPoints(ctx, W2).filter((s) => ctx.store.hasNext(s.payload) &&
|
|
245
|
+
!answersOtherQuestions(ctx, s.payload, query.length, s.end - s.start));
|
|
246
|
+
const bound = await bindArgument(held, strangers);
|
|
247
|
+
if (bound !== null)
|
|
248
|
+
return bound;
|
|
249
|
+
}
|
|
181
250
|
// 2. Scaffolding-dominated.
|
|
182
251
|
if (top.score >= sig) {
|
|
183
252
|
// The committed points of attention ARE the shared climb's roots (same
|
|
@@ -303,7 +372,22 @@ export async function recallByResonance(ctx, query, pre) {
|
|
|
303
372
|
// is a stronger claim that needs the corpus's own carriage evidence, and
|
|
304
373
|
// that is `reference`'s job.
|
|
305
374
|
const anchorBytes = read(ctx, forest[0].anchor, query.length * ctx.space.maxGroup + 1);
|
|
306
|
-
|
|
375
|
+
// …and the same refusal read from the anchor's side: an anchor the query
|
|
376
|
+
// witnesses in every byte but one filler of its own is ANOTHER INSTANCE
|
|
377
|
+
// of the question (traverse.ts, `coInstanceFiller`). The query-side
|
|
378
|
+
// reading above needs the shared frame to dominate the QUERY, which a
|
|
379
|
+
// long slot defeats: `Where was the performer of song God (John Lennon
|
|
380
|
+
// Song) born?` elected `Where was Nicki Minaj (Nicki Minaj Song) born?`
|
|
381
|
+
// and answered Nicki Minaj's birthplace.
|
|
382
|
+
const asked = ctx._edgeAsked;
|
|
383
|
+
const co = asked === null
|
|
384
|
+
? null
|
|
385
|
+
: coInstanceFiller(ctx, anchorBytes, [asked.index], asked.bytes);
|
|
386
|
+
if (co !== null) {
|
|
387
|
+
ctx.trace?.step("coInstanceAnchor", [rItem(query, "query"), rNode(ctx, forest[0].anchor, "anchor")], [rItem(anchorBytes.subarray(co.span[0], co.span[1]), "filler")], "refused — the anchor is another instance of the question's frame, " +
|
|
388
|
+
"and its continuation speaks of its own filler");
|
|
389
|
+
}
|
|
390
|
+
else if (g !== null && voicesDisplacedFiller(ctx, query, anchorBytes, g)) {
|
|
307
391
|
ctx.trace?.step("displacedFiller", [rItem(query, "query"), rNode(ctx, forest[0].anchor, "anchor")], [rItem(g, "withheld")], "refused — the anchor's continuation speaks the anchor's own " +
|
|
308
392
|
"occupant of a position this query fills differently");
|
|
309
393
|
} // The anchor cleared the consensus floor, but the floor prices the
|
|
@@ -34,6 +34,8 @@
|
|
|
34
34
|
// population for the other is the error commonality.md names. The notion is
|
|
35
35
|
// made AVAILABLE, never imposed.
|
|
36
36
|
import { carriesFillers, distinct, follow, substituteAll } from "../match.js";
|
|
37
|
+
import { resolve } from "../primitives.js";
|
|
38
|
+
import { hubBound } from "../traverse.js";
|
|
37
39
|
import { dominates } from "../../geometry.js";
|
|
38
40
|
import { bytesEqual } from "../../bytes.js";
|
|
39
41
|
import { restates } from "../derivation.js";
|
|
@@ -172,13 +174,36 @@ export async function bindReference(ctx, query, pre) {
|
|
|
172
174
|
// discard them. Each goes through the shared projection, so an ambiguous
|
|
173
175
|
// instance is disambiguated exactly as it would be anywhere else.
|
|
174
176
|
const leadsNowhere = "an instance of the frame leads nowhere";
|
|
177
|
+
// A FACT FILED UNDER ITS FILLER IS NOT A CARRIAGE. When an instance's
|
|
178
|
+
// filler is itself a stored context leading to that instance's answer, the
|
|
179
|
+
// answer is something the corpus knows ABOUT that filler (`The place of
|
|
180
|
+
// birth of Peter Jackson is Wellington.` is a continuation of `Peter
|
|
181
|
+
// Jackson`), not a form any occupant takes — and two such facts can agree
|
|
182
|
+
// by chance (two people born in Wellington). `Run gcc hello.c` is filed
|
|
183
|
+
// under the question alone.
|
|
184
|
+
const filedUnderFiller = (inst, cont) => {
|
|
185
|
+
const c = resolve(ctx, cont);
|
|
186
|
+
if (c === null)
|
|
187
|
+
return false;
|
|
188
|
+
return inst.slots.some((s) => {
|
|
189
|
+
const f = resolve(ctx, s.filler);
|
|
190
|
+
return f !== null &&
|
|
191
|
+
ctx.store.nextFirst(f, hubBound(ctx)).includes(c);
|
|
192
|
+
});
|
|
193
|
+
};
|
|
175
194
|
const first = await follow(ctx, frame[0].id, pre.guide);
|
|
176
195
|
if (first === null || first.length === 0)
|
|
177
196
|
return fail(leadsNowhere);
|
|
197
|
+
if (filedUnderFiller(frame[0], first)) {
|
|
198
|
+
return fail("the frame's answer is a fact filed under its filler");
|
|
199
|
+
}
|
|
178
200
|
for (let i = 1; i < frame.length; i++) {
|
|
179
201
|
const cont = await follow(ctx, frame[i].id, pre.guide);
|
|
180
202
|
if (cont === null || cont.length === 0)
|
|
181
203
|
return fail(leadsNowhere);
|
|
204
|
+
if (filedUnderFiller(frame[i], cont)) {
|
|
205
|
+
return fail("the frame's answer is a fact filed under its filler");
|
|
206
|
+
}
|
|
182
207
|
if (!carriesFillers(first, fillersOf(frame[0]), cont, fillersOf(frame[i]))) {
|
|
183
208
|
ctx.trace?.step("referenceLicence", [rItem(first, "instance"), rNode(ctx, frame[i].id, "against")], [rItem(cont, "attested")], "refused — the frame's answer carries content that depends on WHICH " +
|
|
184
209
|
"filler, so the corpus cannot supply it for a new one");
|
package/dist/src/mind/mind.d.ts
CHANGED
|
@@ -47,6 +47,7 @@ export interface Conversation {
|
|
|
47
47
|
readonly id: number;
|
|
48
48
|
}
|
|
49
49
|
import type { AttentionRead, MindContext, Recognition } from "./types.js";
|
|
50
|
+
import type { WindowIndex } from "./evidence.js";
|
|
50
51
|
export type { AnchorRejectionReason, ClimbConsensusData, ConsensusAnchorTrace, ConsensusReachTrace, ConsensusRegionTrace, CrossRegionTier, JunctionVoteTrace, RegionOutcome, } from "./attention.js";
|
|
51
52
|
export type { AncestorReach, SaturationReason, SaturationStop, } from "./types.js";
|
|
52
53
|
import { type CostReport, Meter } from "../meter.js";
|
|
@@ -165,6 +166,12 @@ export declare class Mind implements MindContext {
|
|
|
165
166
|
* first-edge behaviour) and the reverse projection uses it for
|
|
166
167
|
* reverse-recall disambiguation via `chooseAmong`. */
|
|
167
168
|
_edgeGuide: Vec | null;
|
|
169
|
+
/** See {@link MindContext._edgeAsked}. */
|
|
170
|
+
_edgeAsked: {
|
|
171
|
+
bytes: Uint8Array;
|
|
172
|
+
index: WindowIndex;
|
|
173
|
+
points?: readonly number[];
|
|
174
|
+
} | null;
|
|
168
175
|
/** Per-response memo of {@link chooseNext} picks — ensures every mechanism
|
|
169
176
|
* of a single response follows the SAME continuation for each ambiguous
|
|
170
177
|
* context node. */
|
package/dist/src/mind/mind.js
CHANGED
|
@@ -104,6 +104,8 @@ export class Mind {
|
|
|
104
104
|
* first-edge behaviour) and the reverse projection uses it for
|
|
105
105
|
* reverse-recall disambiguation via `chooseAmong`. */
|
|
106
106
|
_edgeGuide = null;
|
|
107
|
+
/** See {@link MindContext._edgeAsked}. */
|
|
108
|
+
_edgeAsked = null;
|
|
107
109
|
/** Per-response memo of {@link chooseNext} picks — ensures every mechanism
|
|
108
110
|
* of a single response follows the SAME continuation for each ambiguous
|
|
109
111
|
* context node. */
|
|
@@ -334,6 +336,7 @@ export class Mind {
|
|
|
334
336
|
this.canon = null;
|
|
335
337
|
this.canonMemo = null;
|
|
336
338
|
this._edgeGuide = null;
|
|
339
|
+
this._edgeAsked = null;
|
|
337
340
|
this._edgeChoice.clear();
|
|
338
341
|
}
|
|
339
342
|
/** Shared response core — the one path from bytes to voiced answer.
|