@hviana/sema 0.2.3 → 0.2.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/dist/src/mind/attention.d.ts +14 -2
- package/dist/src/mind/attention.js +54 -8
- package/dist/src/mind/bridge.d.ts +30 -0
- package/dist/src/mind/bridge.js +569 -0
- package/dist/src/mind/match.d.ts +15 -2
- package/dist/src/mind/match.js +3 -8
- package/dist/src/mind/mechanisms/cast.d.ts +54 -0
- package/dist/src/mind/mechanisms/cast.js +268 -37
- package/dist/src/mind/mechanisms/cover.js +16 -31
- package/dist/src/mind/mechanisms/recall.js +66 -0
- package/dist/src/mind/reasoning.d.ts +11 -0
- package/dist/src/mind/reasoning.js +58 -2
- package/dist/src/mind/recognition.js +127 -7
- package/dist/src/mind/traverse.js +16 -15
- package/dist/src/mind/types.d.ts +39 -2
- package/dist/src/mind/types.js +38 -7
- package/dist/src/store.d.ts +12 -3
- package/dist/src/store.js +9 -3
- package/package.json +1 -1
- package/src/mind/attention.ts +65 -7
- package/src/mind/bridge.ts +596 -0
- package/src/mind/match.ts +19 -5
- package/src/mind/mechanisms/cast.ts +290 -38
- package/src/mind/mechanisms/cover.ts +23 -36
- package/src/mind/mechanisms/recall.ts +79 -0
- package/src/mind/reasoning.ts +71 -2
- package/src/mind/recognition.ts +132 -7
- package/src/mind/traverse.ts +16 -17
- package/src/mind/types.ts +70 -6
- package/src/store.ts +19 -5
- package/test/36-already-answered-fusion.test.mjs +128 -0
- package/test/37-cluster-dispersion-fusion.test.mjs +190 -0
- package/test/38-reason-restate-guard.test.mjs +94 -0
- package/test/39-cast-restate-guard.test.mjs +102 -0
- package/test/40-choosenext-scale-guard.test.mjs +75 -0
- package/test/41-seatofnode-direction.test.mjs +85 -0
- package/test/42-recognise-trace-idempotence.test.mjs +106 -0
- package/test/43-cast-analog-seat.test.mjs +244 -0
- package/test/44-recognise-edge-whitespace.test.mjs +63 -0
- package/test/45-liftanswer-restated-trim.test.mjs +60 -0
- package/test/46-recognise-multibyte-edge.test.mjs +85 -0
- package/test/47-cast-comparison-coverage.test.mjs +134 -0
- package/test/48-recognise-turn-connective.test.mjs +125 -0
- package/test/49-natural-units-synonym-bridge.test.mjs +175 -0
- package/test/50-cast-analog-consensus-floor.test.mjs +179 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { MindContext } from "../types.js";
|
|
2
|
+
import type { Vec } from "../../vec.js";
|
|
2
3
|
/** A CAST answer plus its elementary evidence for think's grounding decider:
|
|
3
4
|
* `accounted` — the query spans the weave's aligned runs explain; `moves` —
|
|
4
5
|
* the ladder cost of the acts the taken branch performed (STEP per
|
|
@@ -13,6 +14,59 @@ export interface CastResult {
|
|
|
13
14
|
* Task 2 note in pipeline.ts's Candidate interface). */
|
|
14
15
|
unexplained: string;
|
|
15
16
|
}
|
|
17
|
+
/** The seat that establishes a node's role in an analogical comparison:
|
|
18
|
+
* the REVERSE context (what leads to it) when a predecessor genuinely
|
|
19
|
+
* ESTABLISHES id — introduces or describes it by name — else the FORWARD
|
|
20
|
+
* continuation (what it leads to), else `fallback`.
|
|
21
|
+
*
|
|
22
|
+
* An earlier version gated this purely on `prevCount(id) > 0`: any
|
|
23
|
+
* predecessor at all was treated as proof of a genuine named ENTITY
|
|
24
|
+
* (seat it by what established it), while no predecessor meant a bare
|
|
25
|
+
* learnt CONTEXT (seat it by what it leads to, since voicing it verbatim
|
|
26
|
+
* would answer a question with a question). That test measured the wrong
|
|
27
|
+
* thing — a broad sample of this store's own question-shaped nodes showed
|
|
28
|
+
* the large majority (≈71%) have at least one predecessor, most of them a
|
|
29
|
+
* handful of generic, high-fan-out sentences that recur as an INCIDENTAL
|
|
30
|
+
* neighbour to dozens of otherwise-unrelated destinations (a SmolSent-
|
|
31
|
+
* style sentence-adjacency artifact, never naming or describing what
|
|
32
|
+
* follows). Traced live: "What is the capital of France?" — whose own
|
|
33
|
+
* forward edge unambiguously resolves to "The capital of France is
|
|
34
|
+
* Paris." — has exactly one such incidental predecessor ("Create an
|
|
35
|
+
* example of a types of questions a GPT model can answer.?"), wrongly
|
|
36
|
+
* read as disqualifying proof of "genuine entity."
|
|
37
|
+
*
|
|
38
|
+
* A plain forward-first swap (matching {@link project}'s universal
|
|
39
|
+
* priority) over-corrected: test/29's C2/C3 pin that a genuine entity
|
|
40
|
+
* analog (e.g. "Leonardo da Vinci", established by "The Mona Lisa was
|
|
41
|
+
* painted by Leonardo da Vinci.") must be seated by that establishing
|
|
42
|
+
* sentence, NOT by its own biography fact — voicing the bio leaks exactly
|
|
43
|
+
* what a comparison must keep out, and loses the embedded "Mona Lisa"
|
|
44
|
+
* term C3 relies on for a further hop.
|
|
45
|
+
*
|
|
46
|
+
* The distinguishing signal is content-addressed, not a count: a genuine
|
|
47
|
+
* establishing predecessor's bytes CONTAIN id's own bytes — it names or
|
|
48
|
+
* describes id ("...painted by Leonardo da Vinci." contains "Leonardo da
|
|
49
|
+
* Vinci"). An incidental adjacency predecessor never does — it merely
|
|
50
|
+
* preceded id in some unrelated document without ever mentioning it. No
|
|
51
|
+
* new tuned constant: containment is the same primitive `restatesQuery`
|
|
52
|
+
* and `dominates`-style checks already use throughout this codebase.
|
|
53
|
+
*
|
|
54
|
+
* `allowForward` (default true) gates the FORWARD branch specifically —
|
|
55
|
+
* see the call sites below: the DOMINANT is what the query is actually
|
|
56
|
+
* ASKING, so completing it forward is the whole point; an ANALOG is only
|
|
57
|
+
* being CITED for comparison; the query never asked about IT, so chasing
|
|
58
|
+
* its own further continuation drifts onto whatever coincidentally
|
|
59
|
+
* follows it in the corpus. Traced live: the analog "What is the capital
|
|
60
|
+
* of Japan?\nTokyo is the capital of Japan." is ALREADY a complete,
|
|
61
|
+
* self-answering unit (prevCount 0, so no establishing predecessor
|
|
62
|
+
* either) — its sole forward edge is "And what is the capital of the
|
|
63
|
+
* Moon?", an unrelated quiz question sharing nothing but corpus
|
|
64
|
+
* adjacency. With forward disallowed, an analog like this falls through
|
|
65
|
+
* to `fallback` — its own bytes, exactly the complete fact that made it a
|
|
66
|
+
* genuine analog in the first place. See
|
|
67
|
+
* test/41-seatofnode-direction.test.mjs and
|
|
68
|
+
* test/43-cast-analog-seat.test.mjs. */
|
|
69
|
+
export declare function seatOfNode(ctx: MindContext, id: number, guide: Vec | null | undefined, fallback: Uint8Array, allowForward?: boolean): Promise<Uint8Array>;
|
|
16
70
|
/** CAST's own entry gates, checked once here and reused by
|
|
17
71
|
/** The main CAST entry point. Given a query and its pre-computed pre.rec.sites,
|
|
18
72
|
* determine whether the query weaves together multiple independent learnt
|
|
@@ -11,14 +11,16 @@
|
|
|
11
11
|
// gate = the frame gate below + analogyStrength, projection = insert / project /
|
|
12
12
|
// juxtapose.
|
|
13
13
|
import { read } from "../primitives.js";
|
|
14
|
-
import { argmaxBy, hubBound } from "../traverse.js";
|
|
14
|
+
import { argmaxBy, corpusN, hubBound } from "../traverse.js";
|
|
15
15
|
import { analogyStrength, follow, project, reverseContext, } from "../match.js";
|
|
16
16
|
import { joinWithBridge } from "../resonance.js";
|
|
17
|
+
import { restatesQuery } from "../reasoning.js";
|
|
17
18
|
import { CONCEPT, STEP } from "../graph-search.js";
|
|
18
19
|
import { concat2, indexOf } from "../../bytes.js";
|
|
19
|
-
import { dominates } from "../../geometry.js";
|
|
20
|
-
import { unexplainedLabel } from "../rationale.js";
|
|
20
|
+
import { consensusFloor, dominates } from "../../geometry.js";
|
|
21
|
+
import { unexplainedLabel, unexplainedSpans, } from "../rationale.js";
|
|
21
22
|
import { rItem, rNode } from "../trace.js";
|
|
23
|
+
import { dismissedKnownContent } from "../bridge.js";
|
|
22
24
|
// ── CAST gates ────────────────────────────────────────────────────────────
|
|
23
25
|
//
|
|
24
26
|
// The frame gate has TWO components, both derived from the weave itself:
|
|
@@ -52,6 +54,81 @@ import { rItem, rNode } from "../trace.js";
|
|
|
52
54
|
* minimum: `depth > MIN_WEAVE` means at least three structures agree on a
|
|
53
55
|
* byte, so no byte is frame when only the minimum pair exists. */
|
|
54
56
|
const MIN_WEAVE = 2;
|
|
57
|
+
/** The seat that establishes a node's role in an analogical comparison:
|
|
58
|
+
* the REVERSE context (what leads to it) when a predecessor genuinely
|
|
59
|
+
* ESTABLISHES id — introduces or describes it by name — else the FORWARD
|
|
60
|
+
* continuation (what it leads to), else `fallback`.
|
|
61
|
+
*
|
|
62
|
+
* An earlier version gated this purely on `prevCount(id) > 0`: any
|
|
63
|
+
* predecessor at all was treated as proof of a genuine named ENTITY
|
|
64
|
+
* (seat it by what established it), while no predecessor meant a bare
|
|
65
|
+
* learnt CONTEXT (seat it by what it leads to, since voicing it verbatim
|
|
66
|
+
* would answer a question with a question). That test measured the wrong
|
|
67
|
+
* thing — a broad sample of this store's own question-shaped nodes showed
|
|
68
|
+
* the large majority (≈71%) have at least one predecessor, most of them a
|
|
69
|
+
* handful of generic, high-fan-out sentences that recur as an INCIDENTAL
|
|
70
|
+
* neighbour to dozens of otherwise-unrelated destinations (a SmolSent-
|
|
71
|
+
* style sentence-adjacency artifact, never naming or describing what
|
|
72
|
+
* follows). Traced live: "What is the capital of France?" — whose own
|
|
73
|
+
* forward edge unambiguously resolves to "The capital of France is
|
|
74
|
+
* Paris." — has exactly one such incidental predecessor ("Create an
|
|
75
|
+
* example of a types of questions a GPT model can answer.?"), wrongly
|
|
76
|
+
* read as disqualifying proof of "genuine entity."
|
|
77
|
+
*
|
|
78
|
+
* A plain forward-first swap (matching {@link project}'s universal
|
|
79
|
+
* priority) over-corrected: test/29's C2/C3 pin that a genuine entity
|
|
80
|
+
* analog (e.g. "Leonardo da Vinci", established by "The Mona Lisa was
|
|
81
|
+
* painted by Leonardo da Vinci.") must be seated by that establishing
|
|
82
|
+
* sentence, NOT by its own biography fact — voicing the bio leaks exactly
|
|
83
|
+
* what a comparison must keep out, and loses the embedded "Mona Lisa"
|
|
84
|
+
* term C3 relies on for a further hop.
|
|
85
|
+
*
|
|
86
|
+
* The distinguishing signal is content-addressed, not a count: a genuine
|
|
87
|
+
* establishing predecessor's bytes CONTAIN id's own bytes — it names or
|
|
88
|
+
* describes id ("...painted by Leonardo da Vinci." contains "Leonardo da
|
|
89
|
+
* Vinci"). An incidental adjacency predecessor never does — it merely
|
|
90
|
+
* preceded id in some unrelated document without ever mentioning it. No
|
|
91
|
+
* new tuned constant: containment is the same primitive `restatesQuery`
|
|
92
|
+
* and `dominates`-style checks already use throughout this codebase.
|
|
93
|
+
*
|
|
94
|
+
* `allowForward` (default true) gates the FORWARD branch specifically —
|
|
95
|
+
* see the call sites below: the DOMINANT is what the query is actually
|
|
96
|
+
* ASKING, so completing it forward is the whole point; an ANALOG is only
|
|
97
|
+
* being CITED for comparison; the query never asked about IT, so chasing
|
|
98
|
+
* its own further continuation drifts onto whatever coincidentally
|
|
99
|
+
* follows it in the corpus. Traced live: the analog "What is the capital
|
|
100
|
+
* of Japan?\nTokyo is the capital of Japan." is ALREADY a complete,
|
|
101
|
+
* self-answering unit (prevCount 0, so no establishing predecessor
|
|
102
|
+
* either) — its sole forward edge is "And what is the capital of the
|
|
103
|
+
* Moon?", an unrelated quiz question sharing nothing but corpus
|
|
104
|
+
* adjacency. With forward disallowed, an analog like this falls through
|
|
105
|
+
* to `fallback` — its own bytes, exactly the complete fact that made it a
|
|
106
|
+
* genuine analog in the first place. See
|
|
107
|
+
* test/41-seatofnode-direction.test.mjs and
|
|
108
|
+
* test/43-cast-analog-seat.test.mjs. */
|
|
109
|
+
export async function seatOfNode(ctx, id, guide, fallback, allowForward = true) {
|
|
110
|
+
const rev = ctx.store.prevFirst(id, hubBound(ctx));
|
|
111
|
+
if (rev.length > 0) {
|
|
112
|
+
const own = read(ctx, id);
|
|
113
|
+
const establishing = rev.some((p) => indexOf(read(ctx, p), own, 0) >= 0);
|
|
114
|
+
if (establishing) {
|
|
115
|
+
const back = reverseContext(ctx, id, guide, rev);
|
|
116
|
+
if (back !== null)
|
|
117
|
+
return back;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
// The "last resort, non-establishing reverse" fallback below is itself a
|
|
121
|
+
// LESS CERTAIN projection (the same tier as forward) — an analog
|
|
122
|
+
// (allowForward: false) must stop at `fallback` (its own bytes) here
|
|
123
|
+
// rather than fall back to a predecessor that already failed the
|
|
124
|
+
// establishing check just above.
|
|
125
|
+
if (!allowForward)
|
|
126
|
+
return fallback;
|
|
127
|
+
const fwd = await follow(ctx, id, guide);
|
|
128
|
+
if (fwd !== null)
|
|
129
|
+
return fwd;
|
|
130
|
+
return reverseContext(ctx, id, guide, rev) ?? fallback;
|
|
131
|
+
}
|
|
55
132
|
/** CAST's own entry gates, checked once here and reused by
|
|
56
133
|
/** The main CAST entry point. Given a query and its pre-computed pre.rec.sites,
|
|
57
134
|
* determine whether the query weaves together multiple independent learnt
|
|
@@ -222,7 +299,8 @@ export async function counterfactualTransfer(ctx, query, pre) {
|
|
|
222
299
|
const tail = proj.ctx.subarray(seat.cs);
|
|
223
300
|
let answer = await joinWithBridge(ctx, filler, tail);
|
|
224
301
|
const fwd = await follow(ctx, proj.anchor, qv);
|
|
225
|
-
if (fwd !== null && indexOf(answer, fwd, 0) < 0
|
|
302
|
+
if (fwd !== null && indexOf(answer, fwd, 0) < 0 &&
|
|
303
|
+
!restatesQuery(query, fwd)) {
|
|
226
304
|
answer = concat2(answer, fwd);
|
|
227
305
|
}
|
|
228
306
|
ctx.trace?.step("projectCounterfactual", [
|
|
@@ -278,30 +356,8 @@ export async function counterfactualTransfer(ctx, query, pre) {
|
|
|
278
356
|
// seed-dependent failure where the climb ranks an exemplar above a
|
|
279
357
|
// person node and the person node is excluded from points by run-
|
|
280
358
|
// overlap trimming.
|
|
281
|
-
// The seat that establishes a candidate's role
|
|
282
|
-
|
|
283
|
-
// candidate's own bytes when it follows nothing. DELIBERATE STRENGTHENING
|
|
284
|
-
// over the pre-refactor code: reverseContext also returns null when the
|
|
285
|
-
// picked context READS EMPTY (a dangling id degrades to zero bytes), so a
|
|
286
|
-
// corrupted-store read now falls back here instead of voicing a hollow
|
|
287
|
-
// seat into the comparison — the same "empty bytes are no grounding"
|
|
288
|
-
// invariant project() has always enforced.
|
|
289
|
-
// A node that only ever CONTINUES — an edge SOURCE with no predecessor —
|
|
290
|
-
// is a learnt CONTEXT (a stored question-shaped frame), not an entity.
|
|
291
|
-
// Voicing it verbatim answers a question with a question (the observed
|
|
292
|
-
// cast echo: two stored questions concatenated as an "answer"). The
|
|
293
|
-
// context's role is established by what it LEADS TO, so its seat is its
|
|
294
|
-
// own continuation — the fact — with the reverse projection and the raw
|
|
295
|
-
// bytes as the ordinary fallbacks for genuine entities.
|
|
296
|
-
const seatOfNode = async (id, fallback) => {
|
|
297
|
-
if (ctx.store.prevCount(id) === 0 && ctx.store.hasNext(id)) {
|
|
298
|
-
const fwd = await follow(ctx, id, qv);
|
|
299
|
-
if (fwd !== null)
|
|
300
|
-
return fwd;
|
|
301
|
-
}
|
|
302
|
-
return reverseContext(ctx, id, qv) ?? fallback;
|
|
303
|
-
};
|
|
304
|
-
const seatOf = (p) => seatOfNode(p.anchor, p.ctx);
|
|
359
|
+
// The seat that establishes a candidate's role — see {@link seatOfNode}.
|
|
360
|
+
const seatOf = (p, allowForward = true) => seatOfNode(ctx, p.anchor, qv, p.ctx, allowForward);
|
|
305
361
|
const analogs = [];
|
|
306
362
|
for (const p of points) {
|
|
307
363
|
if (p === dominant)
|
|
@@ -335,15 +391,49 @@ export async function counterfactualTransfer(ctx, query, pre) {
|
|
|
335
391
|
}
|
|
336
392
|
let bestAnalog = null;
|
|
337
393
|
let bestSim = 0;
|
|
394
|
+
let bestHalo = false;
|
|
395
|
+
// Whether the query itself NAMES a candidate. A directly aligned point
|
|
396
|
+
// is named by construction — its runs ARE query bytes. A hop-reached
|
|
397
|
+
// candidate is named when its own bytes contain the query text of an
|
|
398
|
+
// aligned run of the point whose continuation edge reached it (that
|
|
399
|
+
// alignment IS the query evidence the hop rests on — the same reading
|
|
400
|
+
// cmpAccounted already prices): "William Shakespeare", reached off
|
|
401
|
+
// "Macbeth was written by William Shakespeare.", contains the src's
|
|
402
|
+
// 12-byte aligned run " Shakespeare" — test/29 C2/C3. The run must span
|
|
403
|
+
// at least TWO perception windows (2·W, the same two-quantum floor
|
|
404
|
+
// CAST's own entry gate holds the whole query to): a single shared
|
|
405
|
+
// W-window is exactly the frame tier's own evidence quantum — the level
|
|
406
|
+
// "half the corpus" shares — and stopword scraps (" the ", "he b",
|
|
407
|
+
// 4–5 bytes) never reach two windows, while a genuinely named entity
|
|
408
|
+
// does. NOT the weave's usable()/frame filter: weave depth counts every
|
|
409
|
+
// ranked exemplar, so a query's own named entity recurring across
|
|
410
|
+
// exemplars ("Shakespeare" in Hamlet+Macbeth+…) is wrongly classified as
|
|
411
|
+
// frame — measured live, it silently disqualified C3's genuine analog.
|
|
412
|
+
const namedByQuery = (c) => {
|
|
413
|
+
if (c.point !== null)
|
|
414
|
+
return true;
|
|
415
|
+
const bytes = read(ctx, c.anchor);
|
|
416
|
+
return c.src.runs.some((r) => r.qe - r.qs >= 2 * quantum &&
|
|
417
|
+
indexOf(bytes, query.subarray(r.qs, r.qe), 0) >= 0);
|
|
418
|
+
};
|
|
419
|
+
// Whether any committed root's consensus vote clears the SAME trust bar
|
|
420
|
+
// recallByResonance applies before grounding through a climb root:
|
|
421
|
+
// consensusFloor(N) = ln(N) + 1/2. The climb's FIRST root is
|
|
422
|
+
// deliberately floor-free (attention.ts: "the dominant one always
|
|
423
|
+
// grounds") — fine for ORIENTING mechanisms, not for voicing learnt
|
|
424
|
+
// content the query never asked about. Computed once here; both the
|
|
425
|
+
// hub fallback below and the comparison gate consume it.
|
|
426
|
+
const rootTrusted = roots.some((r) => r.vote >= consensusFloor(corpusN(ctx)));
|
|
338
427
|
for (const c of analogs) {
|
|
339
|
-
const sim = await analogyStrength(ctx, dominant.anchor, c.anchor);
|
|
428
|
+
const { score: sim, halo } = await analogyStrength(ctx, dominant.anchor, c.anchor);
|
|
340
429
|
ctx.trace?.step("tryAnalog", [
|
|
341
430
|
rNode(ctx, dominant.anchor, "dominant"),
|
|
342
431
|
rNode(ctx, c.anchor, "candidate", sim),
|
|
343
|
-
], [], `analogy strength ${sim.toFixed(4)}`);
|
|
432
|
+
], [], `analogy strength ${sim.toFixed(4)}${halo ? " (halo tier)" : ""}`);
|
|
344
433
|
if (sim > bestSim) {
|
|
345
434
|
bestSim = sim;
|
|
346
435
|
bestAnalog = c;
|
|
436
|
+
bestHalo = halo;
|
|
347
437
|
}
|
|
348
438
|
}
|
|
349
439
|
// When every candidate fails the similarity gates (halo company — now
|
|
@@ -372,6 +462,18 @@ export async function counterfactualTransfer(ctx, query, pre) {
|
|
|
372
462
|
let hubMass = -1;
|
|
373
463
|
const fanClamp = hubBound(ctx) + 1;
|
|
374
464
|
for (const c of analogs) {
|
|
465
|
+
// A fallback comparison carries NO similarity evidence at all. Its
|
|
466
|
+
// honesty rests on the grounding decider discounting it against
|
|
467
|
+
// richer candidates (the design note below) — an assumption that
|
|
468
|
+
// holds only when the climb itself settled on this query with real
|
|
469
|
+
// evidence. Under a root the consensus floor does not trust, an
|
|
470
|
+
// unnamed, hop-reached hub is pure corpus adjacency: refusing it is
|
|
471
|
+
// what kept the live wrong echo silent. A hub the query itself
|
|
472
|
+
// NAMED stays eligible either way (test/29 C2/C3's "William
|
|
473
|
+
// Shakespeare"); an unnamed one under a TRUSTED root stays eligible
|
|
474
|
+
// too (test/33 1b's deliberately weak second candidate).
|
|
475
|
+
if (!rootTrusted && !namedByQuery(c))
|
|
476
|
+
continue;
|
|
375
477
|
// Evidence clamped at the hub bound: beyond √N + 1 the exact fan-out
|
|
376
478
|
// no longer discriminates (every mega-hub ties at the clamp), and
|
|
377
479
|
// counting it exactly would require the corpus-sized read.
|
|
@@ -412,17 +514,130 @@ export async function counterfactualTransfer(ctx, query, pre) {
|
|
|
412
514
|
// climb's own forest, never tuned; substitution/redirection stay
|
|
413
515
|
// unaffected — they orient around a displaced seat, not a whole-topic
|
|
414
516
|
// analogy.
|
|
517
|
+
//
|
|
518
|
+
// roots.length <= 1 is a PROXY for "the query is about one thing" — it is
|
|
519
|
+
// only as good as the climb's own root-commitment, which depends on
|
|
520
|
+
// recognise() having found something to commit a root TO. When the
|
|
521
|
+
// query's newest content genuinely isn't recognised (not boundary noise —
|
|
522
|
+
// real, uncommitted content; see the session's own investigation of the
|
|
523
|
+
// France→Spain live trace), the climb under-commits roots and this proxy
|
|
524
|
+
// is fooled: comparison looks licensed to treat the query as one topic
|
|
525
|
+
// when it is not.
|
|
526
|
+
//
|
|
527
|
+
// The direct check is the SAME accounted spans comparison is about to
|
|
528
|
+
// cite as its evidence: unexplainedSpans (rationale.ts, the same gap
|
|
529
|
+
// computation the trace's own `unexplained` diagnostic uses) names every
|
|
530
|
+
// stretch of the query NEITHER the dominant NOR the analog's evidence
|
|
531
|
+
// touches. A short comparison query ("How is ice like steel?") legitimately
|
|
532
|
+
// accounts for only its two short entity spans — the surrounding "How is
|
|
533
|
+
// ... like ...?" framing is real but SHORT, split into several small gaps,
|
|
534
|
+
// none of them the bulk of the query. The live bug's shape is different in
|
|
535
|
+
// kind, not degree: ONE contiguous, substantial gap — a whole second
|
|
536
|
+
// question the query added that comparison's two spans never touch at all.
|
|
537
|
+
//
|
|
538
|
+
// Two bars, both derived, neither tuned:
|
|
539
|
+
// • the largest gap must not DOMINATE the whole query (the same
|
|
540
|
+
// predicate CAST's own frame gate uses) — rules out a gap that is
|
|
541
|
+
// most of the query outright;
|
|
542
|
+
// • the largest gap must be SMALLER than the dominant's own established
|
|
543
|
+
// context. A gap can't be dismissed as mere connective framing once
|
|
544
|
+
// it is at least as large as the topic being compared FROM — at that
|
|
545
|
+
// scale it isn't glue between two named things, it's substantial
|
|
546
|
+
// enough to be a second topic in its own right. This is what
|
|
547
|
+
// actually separates the live bug (a 47-byte gap against a 30-byte
|
|
548
|
+
// dominant — the ignored content is bigger than the topic itself)
|
|
549
|
+
// from ordinary short comparisons (a 9-byte gap against an 11-byte
|
|
550
|
+
// dominant — the gap is smaller than what's being compared): the two
|
|
551
|
+
// cases land on the same side of "half the query" often enough
|
|
552
|
+
// (both can exceed or clear it) that the query-relative bar alone
|
|
553
|
+
// does not reliably separate them — the topic-relative scale does.
|
|
554
|
+
const cmpAccounted = bestAnalog !== null
|
|
555
|
+
? [...runSpans(dominant), ...runSpans(bestAnalog.point ?? bestAnalog.src)]
|
|
556
|
+
: [];
|
|
557
|
+
const cmpGaps = unexplainedSpans(query.length, cmpAccounted);
|
|
558
|
+
const cmpMaxGap = cmpGaps.reduce((n, [s, e]) => Math.max(n, e - s), 0);
|
|
559
|
+
// An analog that is not itself a directly ALIGNED point (point !== null —
|
|
560
|
+
// its own runs are query bytes, the query NAMED it) was only reached
|
|
561
|
+
// through a continuation hop or the structural-hub fallback. Voicing
|
|
562
|
+
// learnt content the query never named is the same act recallByResonance
|
|
563
|
+
// refuses to perform through a climb root whose consensus vote is below
|
|
564
|
+
// consensusFloor(N) = ln(N) + 1/2 (recall.ts's minVote), so comparison
|
|
565
|
+
// holds the climb to that SAME bar before citing a hop-reached analog:
|
|
566
|
+
// some committed root must clear the floor. The climb's FIRST root is
|
|
567
|
+
// deliberately floor-free (attention.ts: "the dominant one always
|
|
568
|
+
// grounds") — fine for ORIENTING mechanisms, not for transferring
|
|
569
|
+
// unnamed content through. The live bug this gates (real trained store,
|
|
570
|
+
// 325k edge sources, floor 13.2): the query's stopword scraps pooled a
|
|
571
|
+
// 1.92 vote that committed an unrelated haiku exemplar as the sole root,
|
|
572
|
+
// and comparison voiced that exemplar's continuation through a
|
|
573
|
+
// hop-reached analog while every other mechanism honestly refused. A
|
|
574
|
+
// directly aligned analog needs no floor — the query's own bytes are its
|
|
575
|
+
// evidence (test/29 C1's "Steel is hard" for "How is ice like steel?").
|
|
576
|
+
// See test/50-cast-analog-consensus-floor.
|
|
577
|
+
// A HALO-tier best analog needs neither: its similarity already cleared
|
|
578
|
+
// significanceBar-gated distributional company (analogyStrength's
|
|
579
|
+
// `halo`) — genuine evidence in its own right, the very case the halo
|
|
580
|
+
// gate exists for (test/33 1b's nickname-corroborated analog). Only a
|
|
581
|
+
// FRAME-tier or fallback analog — whose "similarity" is an unbarred
|
|
582
|
+
// coverage fraction or nothing — needs the query's naming or the climb's
|
|
583
|
+
// trust.
|
|
584
|
+
const analogNamed = bestAnalog !== null && namedByQuery(bestAnalog);
|
|
585
|
+
// NOTE — two further gates were tried here and empirically REFUTED,
|
|
586
|
+
// recorded so they are not re-tried:
|
|
587
|
+
// • dominant self-coverage (dominant's aligned runs must dominate its
|
|
588
|
+
// own ctx): legitimate dominants sit at the same coverage as junk
|
|
589
|
+
// ones ("The Mona Lisa was painted by…" 16/47 vs the live junk
|
|
590
|
+
// haiku ~10/54) — no separation.
|
|
591
|
+
// • denying the shared-frame similarity tier to hop-reached analogs:
|
|
592
|
+
// semantically right in isolation, but it merely promoted the next
|
|
593
|
+
// junk candidate — an ALIGNED scrap-matched point ("The affluence…",
|
|
594
|
+
// frame 0.157) — into bestAnalog on the live store, and the aligned
|
|
595
|
+
// configuration is byte-structurally IDENTICAL to test/29 C1's
|
|
596
|
+
// legitimate one ("Steel is hard", frame 0.364): every derived
|
|
597
|
+
// local separator measured (run length, site overlap, frame
|
|
598
|
+
// query-containment, weave-usable classification) falls on the same
|
|
599
|
+
// side for both. Only corpus-scale consensus separates them, which
|
|
600
|
+
// is exactly what `rootTrusted` prices.
|
|
601
|
+
// FRAME-tier evidence under an UNTRUSTED root is comparison's weakest
|
|
602
|
+
// licence (an unbarred coverage fraction, a climb the consensus floor
|
|
603
|
+
// does not trust). There it is additionally held to the IGNORED-KNOWN
|
|
604
|
+
// principle (dismissedKnownContent, bridge.ts): the two analogs' aligned
|
|
605
|
+
// runs must account for every STORED window of the query. This is the
|
|
606
|
+
// byte-structural separator the refuted-gates note below could not find
|
|
607
|
+
// locally: a legitimate small-corpus comparison ("How is ice like
|
|
608
|
+
// steel?") leaves only UNATTESTED spans ("How ", " like ") unexplained,
|
|
609
|
+
// while a scrap-matched junk pair leaves the query's own trained content
|
|
610
|
+
// ("…songs…times…", "…planet…sun.") dismissed as gaps. Halo-tier and
|
|
611
|
+
// trusted-root comparisons are exempt — their evidence already stands.
|
|
612
|
+
const cmpDismisses = !(bestHalo || rootTrusted) &&
|
|
613
|
+
dismissedKnownContent(ctx, query, cmpAccounted);
|
|
415
614
|
if (bestAnalog !== null &&
|
|
615
|
+
(bestHalo || analogNamed || rootTrusted) &&
|
|
616
|
+
!cmpDismisses &&
|
|
416
617
|
dominant.ctx.length <= query.length &&
|
|
417
|
-
roots.length <= 1
|
|
618
|
+
roots.length <= 1 &&
|
|
619
|
+
!dominates(cmpMaxGap, query.length) &&
|
|
620
|
+
cmpMaxGap < dominant.ctx.length) {
|
|
418
621
|
ctx.trace?.step("validateAnalogy", [
|
|
419
622
|
rNode(ctx, dominant.anchor, "analog", bestSim),
|
|
420
623
|
rNode(ctx, bestAnalog.anchor, "analog", bestSim),
|
|
421
624
|
], [], "the two structures keep distributional company beyond chance — genuine analogs");
|
|
422
625
|
const a = await seatOf(dominant);
|
|
626
|
+
// The analog is only being CITED for comparison — the query never asked
|
|
627
|
+
// about it — so its seat never chases a FORWARD continuation (see
|
|
628
|
+
// seatOfNode's `allowForward`): only reverse (if a predecessor genuinely
|
|
629
|
+
// establishes it) or its own bytes. A DIRECTLY aligned point
|
|
630
|
+
// (bestAnalog.point !== null) still goes through seatOfNode for that
|
|
631
|
+
// reverse check (a bare entity NAME like "Leonardo da Vinci" needs it —
|
|
632
|
+
// test/29's C2/C3). A nextOf DESCENDANT (point === null) was already
|
|
633
|
+
// reached by following ONE meaningful hop off another aligned point (the
|
|
634
|
+
// alignment loop above: "its nextOf is the hub... and the hub's own
|
|
635
|
+
// [...] context will be the seat") — its own bytes ARE that seat
|
|
636
|
+
// directly, with no predecessor to even check (it was found by a
|
|
637
|
+
// forward edge, not matched in the query).
|
|
423
638
|
const b = bestAnalog.point !== null
|
|
424
|
-
? await seatOf(bestAnalog.point)
|
|
425
|
-
:
|
|
639
|
+
? await seatOf(bestAnalog.point, false)
|
|
640
|
+
: read(ctx, bestAnalog.anchor);
|
|
426
641
|
const answer = await joinWithBridge(ctx, a, b);
|
|
427
642
|
record(answer, "analogical comparison — each analog voiced by the context that establishes its role", new Set([dominant.anchor, bestAnalog.anchor]),
|
|
428
643
|
// A halo-mediated act (the analogy gate) plus two seat projections.
|
|
@@ -432,10 +647,26 @@ export async function counterfactualTransfer(ctx, query, pre) {
|
|
|
432
647
|
// when it was an aligned point, else the source point whose
|
|
433
648
|
// continuation edge reached it (that alignment IS the query evidence
|
|
434
649
|
// the hop rests on).
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
650
|
+
cmpAccounted);
|
|
651
|
+
}
|
|
652
|
+
else if (bestAnalog !== null &&
|
|
653
|
+
dominant.ctx.length <= query.length &&
|
|
654
|
+
roots.length <= 1) {
|
|
655
|
+
ctx.trace?.step("validateAnalogy", [
|
|
656
|
+
rNode(ctx, dominant.anchor, "analog", bestSim),
|
|
657
|
+
rNode(ctx, bestAnalog.anchor, "analog", bestSim),
|
|
658
|
+
], [], !(bestHalo || analogNamed || rootTrusted)
|
|
659
|
+
? `the best analog carries no halo-tier company evidence, was never ` +
|
|
660
|
+
`named by the query, and no committed root's consensus vote ` +
|
|
661
|
+
`clears the floor, so comparison refuses to voice it`
|
|
662
|
+
: cmpDismisses
|
|
663
|
+
? `a frame-tier analog under an untrusted root dismisses stored ` +
|
|
664
|
+
`query content its alignment never accounted for — comparison ` +
|
|
665
|
+
`refuses to ignore what the store knows`
|
|
666
|
+
: `comparison's own accounted evidence leaves a ${cmpMaxGap}-byte gap in ` +
|
|
667
|
+
`a ${query.length}-byte query against a ${dominant.ctx.length}-byte ` +
|
|
668
|
+
`dominant — too large to be mere framing — so it refuses rather ` +
|
|
669
|
+
`than paper over it with an analog the query never asked about`);
|
|
439
670
|
}
|
|
440
671
|
t?.done(results.map((r) => rItem(r.bytes, "answer")), results.length > 0
|
|
441
672
|
? `${results.length} counterfactual schema(s) fired — the grounding decider weighs them`
|
|
@@ -8,12 +8,11 @@
|
|
|
8
8
|
// cover runs FIRST in defaultMechanisms: a computed-backed cover becomes a
|
|
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
|
-
import { bytesEqual, indexOf } from "../../bytes.js";
|
|
12
11
|
import { read, resolve } from "../primitives.js";
|
|
13
12
|
import { guidedFirst } from "../traverse.js";
|
|
14
13
|
import { conceptHop } from "../match.js";
|
|
15
14
|
import { bridge } from "../resonance.js";
|
|
16
|
-
import { liftAnswer } from "../types.js";
|
|
15
|
+
import { liftAnswer, segRestatesQuery } from "../types.js";
|
|
17
16
|
import { decodeText, unexplainedLabel } from "../rationale.js";
|
|
18
17
|
import { rItem, rNode, traceDerivation } from "../trace.js";
|
|
19
18
|
// ── Concept / connector pre-resolution ──────────────────────────────────────
|
|
@@ -166,46 +165,32 @@ export const coverMechanism = {
|
|
|
166
165
|
: "lightest derivation: the chosen spans, left to right");
|
|
167
166
|
if (segs === null)
|
|
168
167
|
return [];
|
|
168
|
+
const W = ctx.space.maxGroup;
|
|
169
169
|
// A chosen span's SUBSTITUTED bytes (an edge followed from a recognised
|
|
170
170
|
// site, not the site's own literal text read back) that equal a byte
|
|
171
171
|
// span the query ALREADY CONTAINS elsewhere restates part of the
|
|
172
|
-
// question — never an answer (
|
|
173
|
-
// apply to a whole-query projection: "a projection that is a proper
|
|
174
|
-
// byte-subspan of the query restates part of the question"). A
|
|
172
|
+
// question — never an answer (see {@link segRestatesQuery}). A
|
|
175
173
|
// recognised site that is itself an entire PRIOR TURN of a multi-turn
|
|
176
174
|
// query is exactly this shape: it carries a genuine learnt
|
|
177
175
|
// continuation, but that continuation is something the asker already
|
|
178
|
-
// said moments later in the SAME query
|
|
179
|
-
//
|
|
180
|
-
//
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
const literal = s.j - s.i === s.bytes.length &&
|
|
186
|
-
bytesEqual(s.bytes, query.subarray(s.i, s.j));
|
|
187
|
-
if (literal)
|
|
188
|
-
continue;
|
|
189
|
-
// A span shorter than one river window is exactly the "ice"/"c"
|
|
190
|
-
// case: a chain hop's short terminal coincidentally recurring as a
|
|
191
|
-
// substring of an unrelated longer word. Below the quantum, byte
|
|
192
|
-
// overlap is chance, not evidence — the same floor identityBar and
|
|
193
|
-
// reachThreshold hold every other structural-overlap claim to.
|
|
194
|
-
if (s.bytes.length >= W && s.bytes.length < query.length &&
|
|
195
|
-
indexOf(query, s.bytes, 0) >= 0) {
|
|
196
|
-
ctx.trace?.step("restatedSpan", [rItem(s.bytes, "substituted", s.node, [s.i, s.j])], [], "the chosen span's substitution already occurs elsewhere in the query — restates it, not an answer");
|
|
197
|
-
return [];
|
|
198
|
-
}
|
|
176
|
+
// said moments later in the SAME query. liftAnswer TRIMS such spans
|
|
177
|
+
// out of both the framing decision and the final concatenation — the
|
|
178
|
+
// OTHER spans a derivation chose are independent evidence and must not
|
|
179
|
+
// be discarded along with the stale one.
|
|
180
|
+
const restated = segs.filter((s) => segRestatesQuery(s, query, query.length, W));
|
|
181
|
+
if (restated.length > 0) {
|
|
182
|
+
ctx.trace?.step("restatedSpan", restated.map((s) => rItem(s.bytes, "substituted", s.node, [s.i, s.j])), [], "the chosen span's substitution already occurs elsewhere in the query — trimmed from the answer, not an answer itself");
|
|
199
183
|
}
|
|
200
|
-
const composed = liftAnswer(segs, query.length);
|
|
184
|
+
const composed = liftAnswer(segs, query.length, query, W);
|
|
201
185
|
if (composed === null)
|
|
202
186
|
return [];
|
|
203
187
|
ctx.trace?.step("liftAnswer", segs.map((s) => rItem(s.bytes, s.rec ? "chosen" : "scaffolding", s.node, [s.i, s.j])), [rItem(composed, "answer", resolve(ctx, composed) ?? undefined)], "lift the recognised region out of the asker's framing", tCover ? [tCover.index] : undefined);
|
|
204
|
-
// accounted = RECOGNISED cover spans only —
|
|
205
|
-
//
|
|
206
|
-
//
|
|
188
|
+
// accounted = RECOGNISED, non-restating cover spans only — a trimmed
|
|
189
|
+
// restated span contributes nothing to the composed answer, so it must
|
|
190
|
+
// not be priced as if it did (PASS-carried bytes are priced already;
|
|
191
|
+
// the diagnostic label reflects the same distinction).
|
|
207
192
|
const accounted = segs
|
|
208
|
-
.filter((s) => s.rec)
|
|
193
|
+
.filter((s) => s.rec && !segRestatesQuery(s, query, query.length, W))
|
|
209
194
|
.map((s) => [s.i, s.j]);
|
|
210
195
|
return [{
|
|
211
196
|
bytes: composed,
|
|
@@ -12,6 +12,7 @@ import { follow, project, reverseContext } from "../match.js";
|
|
|
12
12
|
import { CONCEPT, STEP } from "../graph-search.js";
|
|
13
13
|
import { unexplainedLabel } from "../rationale.js";
|
|
14
14
|
import { rItem, rNode } from "../trace.js";
|
|
15
|
+
import { substitutionBridge } from "../bridge.js";
|
|
15
16
|
/** Recall the answer by resonating the whole query against the content index. */
|
|
16
17
|
export async function recallByResonance(ctx, query, pre) {
|
|
17
18
|
const t = ctx.trace?.enter("recallByResonance", [
|
|
@@ -209,6 +210,71 @@ export async function recallByResonance(ctx, query, pre) {
|
|
|
209
210
|
}
|
|
210
211
|
}
|
|
211
212
|
}
|
|
213
|
+
// 3b. Corroborated-substitution bridge — refusal-path only (bridge.ts).
|
|
214
|
+
// Every gist-based tier has failed; before refusing, align the query
|
|
215
|
+
// byte-for-byte against the trained contexts its own stored windows
|
|
216
|
+
// anchor, accepting mismatches only as corpus-attested, concept-bar
|
|
217
|
+
// substitutions. A bridged context grounds exactly like any hit —
|
|
218
|
+
// projected through its learnt edges — under the same restated-fragment
|
|
219
|
+
// guard tiers 0b/2 apply. Costs nothing on any answering path.
|
|
220
|
+
{
|
|
221
|
+
// The resonance hits already ranked above are handed to the bridge as
|
|
222
|
+
// PROPOSED candidates alongside its own anchor climbs: on a corpus this
|
|
223
|
+
// size a W-byte window is far too common for the clamped climb to
|
|
224
|
+
// single out the right trained context, while the whole-query gist
|
|
225
|
+
// already ranked it nearest (observed live: "what is the capital of
|
|
226
|
+
// france" resonating straight to "What is the capital of France?" yet
|
|
227
|
+
// refusing on the reach bar). Approximate scores propose; the bridge's
|
|
228
|
+
// byte-exact alignment and attestation gates decide.
|
|
229
|
+
//
|
|
230
|
+
// The proposal breadth here is widened PAST `k` — first by requesting
|
|
231
|
+
// hubBound(ctx) candidates instead of `k` (recall's own tiers above
|
|
232
|
+
// stay at `k`; this re-resonates only on the refusal path, exactly
|
|
233
|
+
// where the bridge itself already runs), AND by asking the index to
|
|
234
|
+
// search EXHAUSTIVELY. Both matter: the IVF only ever probes
|
|
235
|
+
// ⌈√clusters⌉ of them (store.ts's efFor) REGARDLESS of k — widening k
|
|
236
|
+
// alone just returns more hits from the SAME already-probed clusters,
|
|
237
|
+
// never a hit whose vector lives in an unprobed one. Measured live:
|
|
238
|
+
// "What is the chemical symbol for water?" needs "What is the
|
|
239
|
+
// chemical formula for water?", scoring only 0.58 against the
|
|
240
|
+
// query's gist (a MIDDLE-of-string word swap perturbs the river-fold
|
|
241
|
+
// tree hash far more than a same-length TAIL swap like the "carbon"/
|
|
242
|
+
// "oxygen" neighbours that outrank it at 0.87+) — absent from the
|
|
243
|
+
// resonance list even at k=5000, present and byte-exact-verified the
|
|
244
|
+
// moment it's force-fed to the bridge directly. `exhaustive` is the
|
|
245
|
+
// natural, tuning-free ceiling (probe every cluster) for a call that
|
|
246
|
+
// is ALREADY refusal-path-only and must not miss a candidate hiding
|
|
247
|
+
// behind an unlucky structural distance.
|
|
248
|
+
const wide = k < hubBound(ctx)
|
|
249
|
+
? await ctx.store.resonate(queryGist, hubBound(ctx), true)
|
|
250
|
+
: whole;
|
|
251
|
+
const bridged = await substitutionBridge(ctx, query, wide.map((h) => h.id));
|
|
252
|
+
if (bridged !== null) {
|
|
253
|
+
const g = await project(ctx, bridged.id, queryGist);
|
|
254
|
+
// A projection contained in a substituted candidate-side span is the
|
|
255
|
+
// substitution RESTATED as if it were knowledge — the exact failure
|
|
256
|
+
// observed live: "Darwin was born in England." bridged to the
|
|
257
|
+
// Einstein fact through " England." → " Germany." and would have
|
|
258
|
+
// voiced "Germany", an answer the substitution itself manufactured.
|
|
259
|
+
// The same principle as the restated-fragment guards above, extended
|
|
260
|
+
// to the bridge's own substitutions.
|
|
261
|
+
const cBytes = ctx.store.bytes(bridged.id);
|
|
262
|
+
const manufactured = g !== null &&
|
|
263
|
+
bridged.subs.some((s) => indexOf(cBytes.subarray(s.cs, s.ce), g, 0) >= 0);
|
|
264
|
+
if (g !== null && g.length > 0 && !restates(g) && !manufactured &&
|
|
265
|
+
!(g.length < query.length && indexOf(query, g, 0) >= 0)) {
|
|
266
|
+
return ground(g, `substitution bridge — a trained context accounts for the query ` +
|
|
267
|
+
`up to ${bridged.subs.length} corroborated substitution(s)`,
|
|
268
|
+
// Accounted NOTHING — the same epistemic humility as the echo
|
|
269
|
+
// tier below: a substitution-bridged grounding is a last resort
|
|
270
|
+
// that must lose to ANY mechanism that actually explained the
|
|
271
|
+
// query (observed: pricing the aligned spans here outweighed
|
|
272
|
+
// extraction's correct answer in the grounding decider), while
|
|
273
|
+
// still beating silence when everything else refused.
|
|
274
|
+
[], CONCEPT * bridged.subs.length + STEP);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
212
278
|
// The refusal/echo decision. The echo returns a stored form's bytes AS
|
|
213
279
|
// the answer — a near-identity claim about the query — and identity-grade
|
|
214
280
|
// decisions are never made on an estimated score ("approximate scores may
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import type { MindContext } from "./types.js";
|
|
2
2
|
import type { Precomputed } from "./pipeline-mechanism.js";
|
|
3
|
+
/** Whether `bytes` is a proper byte-subspan of `query` — already present in
|
|
4
|
+
* the question, so voicing it back only restates part of what was asked,
|
|
5
|
+
* never answers it. The exact guard recallByResonance already applies to
|
|
6
|
+
* its OWN grounding candidates (tier 1's `restates`, tier 2's subspan
|
|
7
|
+
* check, tier 0b's argument-binding subspan check) — every mechanism that
|
|
8
|
+
* walks a LEARNT CONTINUATION EDGE past an already-vetted grounding
|
|
9
|
+
* (reason()'s own hops below, and CAST's `projectCounterfactual` seat
|
|
10
|
+
* substitution — see cast.ts) needs the same guard applied to what the
|
|
11
|
+
* walk turns up, since `follow()`/`chooseNext`/`pivotInto` know nothing of
|
|
12
|
+
* the query at all — only of what structurally continues what. */
|
|
13
|
+
export declare function restatesQuery(query: Uint8Array, bytes: Uint8Array): boolean;
|
|
3
14
|
/** Extend a grounded answer forward across facts (multi-hop reasoning).
|
|
4
15
|
* Pivots on the longest unconsumed learnt context each answer contains,
|
|
5
16
|
* then follows the pivot's continuation to the next fact. Repeats up
|