@hviana/sema 0.2.6 → 0.2.8
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/example/demo.d.ts +1 -0
- package/dist/example/demo.js +39 -0
- package/dist/example/train_base.d.ts +87 -0
- package/dist/example/train_base.js +2252 -0
- package/dist/src/alphabet.d.ts +7 -0
- package/dist/src/alphabet.js +33 -0
- package/dist/src/alu/src/alu.d.ts +185 -0
- package/dist/src/alu/src/alu.js +440 -0
- package/dist/src/alu/src/expr.d.ts +61 -0
- package/dist/src/alu/src/expr.js +318 -0
- package/dist/src/alu/src/index.d.ts +11 -0
- package/dist/src/alu/src/index.js +19 -0
- package/dist/src/alu/src/kernel-arith.d.ts +16 -0
- package/dist/src/alu/src/kernel-arith.js +264 -0
- package/dist/src/alu/src/kernel-bits.d.ts +19 -0
- package/dist/src/alu/src/kernel-bits.js +152 -0
- package/dist/src/alu/src/kernel-logic.d.ts +4 -0
- package/dist/src/alu/src/kernel-logic.js +60 -0
- package/dist/src/alu/src/kernel-nd.d.ts +3 -0
- package/dist/src/alu/src/kernel-nd.js +208 -0
- package/dist/src/alu/src/kernel-numeric.d.ts +54 -0
- package/dist/src/alu/src/kernel-numeric.js +366 -0
- package/dist/src/alu/src/operation.d.ts +168 -0
- package/dist/src/alu/src/operation.js +189 -0
- package/dist/src/alu/src/parser.d.ts +221 -0
- package/dist/src/alu/src/parser.js +577 -0
- package/dist/src/alu/src/resonance.d.ts +55 -0
- package/dist/src/alu/src/resonance.js +126 -0
- package/dist/src/alu/src/text.d.ts +31 -0
- package/dist/src/alu/src/text.js +73 -0
- package/dist/src/alu/src/value.d.ts +109 -0
- package/dist/src/alu/src/value.js +300 -0
- package/dist/src/alu/test/alu.test.d.ts +1 -0
- package/dist/src/alu/test/alu.test.js +764 -0
- package/dist/src/bytes.d.ts +14 -0
- package/dist/src/bytes.js +59 -0
- package/dist/src/canon.d.ts +26 -0
- package/dist/src/canon.js +57 -0
- package/dist/src/config.d.ts +111 -0
- package/dist/src/config.js +91 -0
- package/dist/src/derive/src/deduction.d.ts +125 -0
- package/dist/src/derive/src/deduction.js +155 -0
- package/dist/src/derive/src/index.d.ts +7 -0
- package/dist/src/derive/src/index.js +11 -0
- package/dist/src/derive/src/priority-queue.d.ts +20 -0
- package/dist/src/derive/src/priority-queue.js +73 -0
- package/dist/src/derive/src/rewrite.d.ts +56 -0
- package/dist/src/derive/src/rewrite.js +100 -0
- package/dist/src/derive/src/trie.d.ts +90 -0
- package/dist/src/derive/src/trie.js +217 -0
- package/dist/src/derive/test/derive.test.d.ts +1 -0
- package/dist/src/derive/test/derive.test.js +122 -0
- package/dist/src/extension.d.ts +37 -0
- package/dist/src/extension.js +7 -0
- package/dist/src/geometry.d.ts +202 -0
- package/dist/src/geometry.js +575 -0
- package/dist/src/index.d.ts +16 -0
- package/dist/src/index.js +18 -0
- package/dist/src/ingest-cache.d.ts +41 -0
- package/dist/src/ingest-cache.js +161 -0
- package/dist/src/mind/articulation.d.ts +6 -0
- package/dist/src/mind/articulation.js +99 -0
- package/dist/src/mind/attention.d.ts +405 -0
- package/dist/src/mind/attention.js +1829 -0
- package/dist/src/mind/bridge.d.ts +30 -0
- package/dist/src/mind/bridge.js +569 -0
- package/dist/src/mind/canonical.d.ts +29 -0
- package/dist/src/mind/canonical.js +88 -0
- package/dist/src/mind/graph-search.d.ts +285 -0
- package/dist/src/mind/graph-search.js +956 -0
- package/dist/src/mind/index.d.ts +7 -0
- package/dist/src/mind/index.js +5 -0
- package/dist/src/mind/junction.d.ts +124 -0
- package/dist/src/mind/junction.js +317 -0
- package/dist/src/mind/learning.d.ts +47 -0
- package/dist/src/mind/learning.js +248 -0
- package/dist/src/mind/match.d.ts +126 -0
- package/dist/src/mind/match.js +441 -0
- package/dist/src/mind/mechanisms/alu.d.ts +4 -0
- package/dist/src/mind/mechanisms/alu.js +36 -0
- package/dist/src/mind/mechanisms/cast.d.ts +89 -0
- package/dist/src/mind/mechanisms/cast.js +716 -0
- package/dist/src/mind/mechanisms/confluence.d.ts +24 -0
- package/dist/src/mind/mechanisms/confluence.js +225 -0
- package/dist/src/mind/mechanisms/cover.d.ts +6 -0
- package/dist/src/mind/mechanisms/cover.js +203 -0
- package/dist/src/mind/mechanisms/extraction.d.ts +67 -0
- package/dist/src/mind/mechanisms/extraction.js +387 -0
- package/dist/src/mind/mechanisms/recall.d.ts +13 -0
- package/dist/src/mind/mechanisms/recall.js +325 -0
- package/dist/src/mind/mind.d.ts +276 -0
- package/dist/src/mind/mind.js +572 -0
- package/dist/src/mind/pipeline-mechanism.d.ts +142 -0
- package/dist/src/mind/pipeline-mechanism.js +213 -0
- package/dist/src/mind/pipeline.d.ts +20 -0
- package/dist/src/mind/pipeline.js +217 -0
- package/dist/src/mind/primitives.d.ts +70 -0
- package/dist/src/mind/primitives.js +287 -0
- package/dist/src/mind/rationale.d.ts +139 -0
- package/dist/src/mind/rationale.js +163 -0
- package/dist/src/mind/reasoning.d.ts +34 -0
- package/dist/src/mind/reasoning.js +240 -0
- package/dist/src/mind/recognition.d.ts +20 -0
- package/dist/src/mind/recognition.js +390 -0
- package/dist/src/mind/resonance.d.ts +23 -0
- package/dist/src/mind/resonance.js +0 -0
- package/dist/src/mind/trace.d.ts +15 -0
- package/dist/src/mind/trace.js +73 -0
- package/dist/src/mind/traverse.d.ts +113 -0
- package/dist/src/mind/traverse.js +568 -0
- package/dist/src/mind/types.d.ts +289 -0
- package/dist/src/mind/types.js +130 -0
- package/dist/src/rabitq-ivf/src/database.d.ts +113 -0
- package/dist/src/rabitq-ivf/src/database.js +201 -0
- package/dist/src/rabitq-ivf/src/index.d.ts +7 -0
- package/dist/src/rabitq-ivf/src/index.js +4 -0
- package/dist/src/rabitq-ivf/src/ivf.d.ts +200 -0
- package/dist/src/rabitq-ivf/src/ivf.js +1165 -0
- package/dist/src/rabitq-ivf/src/prng.d.ts +19 -0
- package/dist/src/rabitq-ivf/src/prng.js +36 -0
- package/dist/src/rabitq-ivf/src/rabitq.d.ts +95 -0
- package/dist/src/rabitq-ivf/src/rabitq.js +283 -0
- package/dist/src/sema.d.ts +31 -0
- package/dist/src/sema.js +63 -0
- package/dist/src/store-sqlite.d.ts +184 -0
- package/dist/src/store-sqlite.js +942 -0
- package/dist/src/store.d.ts +663 -0
- package/dist/src/store.js +1618 -0
- package/dist/src/vec.d.ts +31 -0
- package/dist/src/vec.js +109 -0
- package/package.json +1 -1
- package/src/mind/attention.ts +178 -63
- package/test/51-structural-resonance-ladder.test.mjs +6 -3
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export type Vec = Float32Array;
|
|
2
|
+
/** Deterministic PRNG (32-bit mixer). */
|
|
3
|
+
export declare function rng(seed: number): () => number;
|
|
4
|
+
export declare const zeros: (D: number) => Vec;
|
|
5
|
+
export declare const copy: (v: Vec) => Vec;
|
|
6
|
+
/** Random point on the unit sphere. */
|
|
7
|
+
export declare function randomUnit(D: number, rand: () => number): Vec;
|
|
8
|
+
/** target += src * scale (in place). */
|
|
9
|
+
export declare function addInto(target: Vec, src: Vec, scale?: number): Vec;
|
|
10
|
+
export declare function dot(a: Vec, b: Vec): number;
|
|
11
|
+
/** In-place normalization. */
|
|
12
|
+
export declare function normalize(v: Vec): Vec;
|
|
13
|
+
/** Resonance: 1 = same, 0 = unrelated. */
|
|
14
|
+
export declare function cosine(a: Vec, b: Vec): number;
|
|
15
|
+
/** Set vector epsilon thresholds. Called once by Mind at construction. */
|
|
16
|
+
export declare function setVecConfig(cfg: {
|
|
17
|
+
normalizeEpsilon?: number;
|
|
18
|
+
cosineEpsilon?: number;
|
|
19
|
+
}): void;
|
|
20
|
+
export interface Permutation {
|
|
21
|
+
fwd: Uint32Array;
|
|
22
|
+
inv: Uint32Array;
|
|
23
|
+
}
|
|
24
|
+
/** The keyring: one independent permutation per seat.
|
|
25
|
+
* Independent keys do not commute, so an address in a tree is the
|
|
26
|
+
* path itself — "seat 2 inside seat 1" ≠ "seat 1 inside seat 2". */
|
|
27
|
+
export declare function makeKeyring(D: number, seats: number, rand: () => number): Permutation[];
|
|
28
|
+
/** Apply permutation: out[i] = v[table[i]]. */
|
|
29
|
+
export declare function permute(v: Vec, table: Uint32Array): Vec;
|
|
30
|
+
/** Permute into existing buffer — zero allocation. */
|
|
31
|
+
export declare function permuteInto(out: Vec, v: Vec, table: Uint32Array): Vec;
|
package/dist/src/vec.js
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
// vec.ts — vector primitives.
|
|
2
|
+
// Superposition (add), normalization (stay on the sphere),
|
|
3
|
+
// resonance (cosine), and seat binding (a keyring of fixed permutations).
|
|
4
|
+
// No weights. No gradients.
|
|
5
|
+
/** Deterministic PRNG (32-bit mixer). */
|
|
6
|
+
export function rng(seed) {
|
|
7
|
+
let s = seed >>> 0;
|
|
8
|
+
return () => {
|
|
9
|
+
s = (s + 0x6d2b79f5) >>> 0;
|
|
10
|
+
let t = s;
|
|
11
|
+
t = Math.imul(t ^ (t >>> 15), t | 1);
|
|
12
|
+
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
|
|
13
|
+
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
/** Standard normal sample (Box–Muller). */
|
|
17
|
+
function gaussian(rand) {
|
|
18
|
+
let u = 0, v = 0;
|
|
19
|
+
while (u === 0)
|
|
20
|
+
u = rand();
|
|
21
|
+
while (v === 0)
|
|
22
|
+
v = rand();
|
|
23
|
+
return Math.sqrt(-2 * Math.log(u)) * Math.cos(2 * Math.PI * v);
|
|
24
|
+
}
|
|
25
|
+
export const zeros = (D) => new Float32Array(D);
|
|
26
|
+
export const copy = (v) => new Float32Array(v);
|
|
27
|
+
/** Random point on the unit sphere. */
|
|
28
|
+
export function randomUnit(D, rand) {
|
|
29
|
+
const v = zeros(D);
|
|
30
|
+
for (let i = 0; i < D; i++)
|
|
31
|
+
v[i] = gaussian(rand);
|
|
32
|
+
return normalize(v);
|
|
33
|
+
}
|
|
34
|
+
/** target += src * scale (in place). */
|
|
35
|
+
export function addInto(target, src, scale = 1) {
|
|
36
|
+
for (let i = 0; i < target.length; i++)
|
|
37
|
+
target[i] += src[i] * scale;
|
|
38
|
+
return target;
|
|
39
|
+
}
|
|
40
|
+
export function dot(a, b) {
|
|
41
|
+
let s = 0;
|
|
42
|
+
for (let i = 0; i < a.length; i++)
|
|
43
|
+
s += a[i] * b[i];
|
|
44
|
+
return s;
|
|
45
|
+
}
|
|
46
|
+
const norm = (v) => Math.sqrt(dot(v, v));
|
|
47
|
+
// Epsilon thresholds (settable once via setVecConfig).
|
|
48
|
+
let _normalizeEpsilon = 1e-12;
|
|
49
|
+
let _cosineEpsilon = 1e-12;
|
|
50
|
+
/** In-place normalization. */
|
|
51
|
+
export function normalize(v) {
|
|
52
|
+
const n = norm(v);
|
|
53
|
+
if (n > _normalizeEpsilon) {
|
|
54
|
+
for (let i = 0; i < v.length; i++)
|
|
55
|
+
v[i] /= n;
|
|
56
|
+
}
|
|
57
|
+
return v;
|
|
58
|
+
}
|
|
59
|
+
/** Resonance: 1 = same, 0 = unrelated. */
|
|
60
|
+
export function cosine(a, b) {
|
|
61
|
+
const na = norm(a), nb = norm(b);
|
|
62
|
+
return na > _cosineEpsilon && nb > _cosineEpsilon ? dot(a, b) / (na * nb) : 0;
|
|
63
|
+
}
|
|
64
|
+
/** Set vector epsilon thresholds. Called once by Mind at construction. */
|
|
65
|
+
export function setVecConfig(cfg) {
|
|
66
|
+
if (cfg.normalizeEpsilon !== undefined) {
|
|
67
|
+
_normalizeEpsilon = cfg.normalizeEpsilon;
|
|
68
|
+
}
|
|
69
|
+
if (cfg.cosineEpsilon !== undefined)
|
|
70
|
+
_cosineEpsilon = cfg.cosineEpsilon;
|
|
71
|
+
}
|
|
72
|
+
/** One fixed random permutation (Fisher–Yates). */
|
|
73
|
+
function makePermutation(D, rand) {
|
|
74
|
+
const fwd = new Uint32Array(D);
|
|
75
|
+
for (let i = 0; i < D; i++)
|
|
76
|
+
fwd[i] = i;
|
|
77
|
+
for (let i = D - 1; i > 0; i--) {
|
|
78
|
+
const j = Math.floor(rand() * (i + 1));
|
|
79
|
+
const t = fwd[i];
|
|
80
|
+
fwd[i] = fwd[j];
|
|
81
|
+
fwd[j] = t;
|
|
82
|
+
}
|
|
83
|
+
const inv = new Uint32Array(D);
|
|
84
|
+
for (let i = 0; i < D; i++)
|
|
85
|
+
inv[fwd[i]] = i;
|
|
86
|
+
return { fwd, inv };
|
|
87
|
+
}
|
|
88
|
+
/** The keyring: one independent permutation per seat.
|
|
89
|
+
* Independent keys do not commute, so an address in a tree is the
|
|
90
|
+
* path itself — "seat 2 inside seat 1" ≠ "seat 1 inside seat 2". */
|
|
91
|
+
export function makeKeyring(D, seats, rand) {
|
|
92
|
+
const ring = [];
|
|
93
|
+
for (let s = 0; s < seats; s++)
|
|
94
|
+
ring.push(makePermutation(D, rand));
|
|
95
|
+
return ring;
|
|
96
|
+
}
|
|
97
|
+
/** Apply permutation: out[i] = v[table[i]]. */
|
|
98
|
+
export function permute(v, table) {
|
|
99
|
+
const out = new Float32Array(v.length);
|
|
100
|
+
for (let i = 0; i < v.length; i++)
|
|
101
|
+
out[i] = v[table[i]];
|
|
102
|
+
return out;
|
|
103
|
+
}
|
|
104
|
+
/** Permute into existing buffer — zero allocation. */
|
|
105
|
+
export function permuteInto(out, v, table) {
|
|
106
|
+
for (let i = 0; i < v.length; i++)
|
|
107
|
+
out[i] = v[table[i]];
|
|
108
|
+
return out;
|
|
109
|
+
}
|
package/package.json
CHANGED
package/src/mind/attention.ts
CHANGED
|
@@ -1549,86 +1549,137 @@ const VARIANT_KIND_ORDER: Record<StructuralVariant["kind"], number> = {
|
|
|
1549
1549
|
"double-synonym": 2,
|
|
1550
1550
|
};
|
|
1551
1551
|
|
|
1552
|
-
/** A
|
|
1553
|
-
*
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1552
|
+
/** A lightweight, cost-free descriptor of one candidate structural variant —
|
|
1553
|
+
* enough to rank it, but with no bytes read and no vector materialized. */
|
|
1554
|
+
interface StructuralVariantSpec {
|
|
1555
|
+
kind: "left-synonym" | "right-synonym" | "double-synonym";
|
|
1556
|
+
semanticConfidence: number;
|
|
1557
|
+
leftSiblingId?: number;
|
|
1558
|
+
rightSiblingId?: number;
|
|
1559
1559
|
}
|
|
1560
1560
|
|
|
1561
|
-
/**
|
|
1562
|
-
*
|
|
1563
|
-
*
|
|
1564
|
-
function
|
|
1561
|
+
/** Same deterministic ordering the old implementation applied to already-
|
|
1562
|
+
* materialized variants (§8): semantic confidence desc, then kind
|
|
1563
|
+
* (left-synonym, right-synonym, double-synonym), then sibling ids asc. */
|
|
1564
|
+
function compareStructuralVariantSpecs(
|
|
1565
|
+
a: StructuralVariantSpec,
|
|
1566
|
+
b: StructuralVariantSpec,
|
|
1567
|
+
): number {
|
|
1568
|
+
return b.semanticConfidence - a.semanticConfidence ||
|
|
1569
|
+
VARIANT_KIND_ORDER[a.kind] - VARIANT_KIND_ORDER[b.kind] ||
|
|
1570
|
+
(a.leftSiblingId ?? -1) - (b.leftSiblingId ?? -1) ||
|
|
1571
|
+
(a.rightSiblingId ?? -1) - (b.rightSiblingId ?? -1);
|
|
1572
|
+
}
|
|
1573
|
+
|
|
1574
|
+
/** Every single- and double-synonym combination, as cost-free descriptors —
|
|
1575
|
+
* no `read`, `gistOf`, `perceive` or `StructuralPart` allocation. Both
|
|
1576
|
+
* sibling lists are already bounded by `haloQueryK`, so the O(haloQueryK²)
|
|
1577
|
+
* cross-product here is cheap; only the SELECTED specs go on to pay for
|
|
1578
|
+
* sibling reconstruction. */
|
|
1579
|
+
function buildStructuralVariantSpecs(
|
|
1580
|
+
sides: JunctionSynonymSides,
|
|
1581
|
+
): StructuralVariantSpec[] {
|
|
1582
|
+
const specs: StructuralVariantSpec[] = [];
|
|
1583
|
+
|
|
1584
|
+
for (const left of sides.leftSiblings) {
|
|
1585
|
+
specs.push({
|
|
1586
|
+
kind: "left-synonym",
|
|
1587
|
+
semanticConfidence: left.score,
|
|
1588
|
+
leftSiblingId: left.id,
|
|
1589
|
+
});
|
|
1590
|
+
}
|
|
1591
|
+
|
|
1592
|
+
for (const right of sides.rightSiblings) {
|
|
1593
|
+
specs.push({
|
|
1594
|
+
kind: "right-synonym",
|
|
1595
|
+
semanticConfidence: right.score,
|
|
1596
|
+
rightSiblingId: right.id,
|
|
1597
|
+
});
|
|
1598
|
+
}
|
|
1599
|
+
|
|
1600
|
+
for (const left of sides.leftSiblings) {
|
|
1601
|
+
for (const right of sides.rightSiblings) {
|
|
1602
|
+
specs.push({
|
|
1603
|
+
kind: "double-synonym",
|
|
1604
|
+
semanticConfidence: Math.min(left.score, right.score),
|
|
1605
|
+
leftSiblingId: left.id,
|
|
1606
|
+
rightSiblingId: right.id,
|
|
1607
|
+
});
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1610
|
+
|
|
1611
|
+
specs.sort(compareStructuralVariantSpecs);
|
|
1612
|
+
|
|
1613
|
+
return specs;
|
|
1614
|
+
}
|
|
1615
|
+
|
|
1616
|
+
/** A halo sibling's structural gist, bounded to `maxBytes` of stored content
|
|
1617
|
+
* and reused across the whole climb. `positiveMemo` (shared across every
|
|
1618
|
+
* probe in the climb, passed in by the caller) remembers only successfully
|
|
1619
|
+
* reconstructed complete gists — a sibling rejected here for being too
|
|
1620
|
+
* large for THIS pair's phrase-scale bound may still be admissible for a
|
|
1621
|
+
* larger-spanning pair later, so a rejection is never memoized globally.
|
|
1622
|
+
* `localMemo` is scoped to one `buildStructuralVariants` call, where every
|
|
1623
|
+
* variant shares the same bound, so a `null` there is safe to reuse. */
|
|
1624
|
+
function loadBoundedSiblingGist(
|
|
1565
1625
|
ctx: MindContext,
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1626
|
+
id: number,
|
|
1627
|
+
maxBytes: number,
|
|
1628
|
+
positiveMemo: Map<number, Vec>,
|
|
1629
|
+
localMemo: Map<number, Vec | null>,
|
|
1630
|
+
): Vec | null {
|
|
1631
|
+
if (localMemo.has(id)) {
|
|
1632
|
+
return localMemo.get(id) ?? null;
|
|
1633
|
+
}
|
|
1634
|
+
|
|
1635
|
+
const cached = positiveMemo.get(id);
|
|
1636
|
+
if (cached !== undefined) {
|
|
1637
|
+
localMemo.set(id, cached);
|
|
1638
|
+
return cached;
|
|
1639
|
+
}
|
|
1640
|
+
|
|
1641
|
+
const length = ctx.store.contentLen(id, maxBytes + 1);
|
|
1642
|
+
if (length <= 0 || length > maxBytes) {
|
|
1643
|
+
localMemo.set(id, null);
|
|
1644
|
+
return null;
|
|
1645
|
+
}
|
|
1646
|
+
|
|
1647
|
+
const bytes = read(ctx, id, maxBytes + 1);
|
|
1648
|
+
if (bytes.length === 0 || bytes.length > maxBytes) {
|
|
1649
|
+
localMemo.set(id, null);
|
|
1650
|
+
return null;
|
|
1651
|
+
}
|
|
1652
|
+
|
|
1653
|
+
const gist = gistOf(ctx, bytes);
|
|
1654
|
+
positiveMemo.set(id, gist);
|
|
1655
|
+
localMemo.set(id, gist);
|
|
1656
|
+
return gist;
|
|
1573
1657
|
}
|
|
1574
1658
|
|
|
1575
1659
|
/** Build, bound and order every mandatory structural variant (§7-8): the
|
|
1576
1660
|
* exact/exact composition is always kept; up to `ctx.cfg.haloQueryK`
|
|
1577
1661
|
* synonym variants (single- and double-synonym combined, one shared
|
|
1578
|
-
* budget) are appended, ordered by confidence, then kind, then sibling id.
|
|
1662
|
+
* budget) are appended, ordered by confidence, then kind, then sibling id.
|
|
1663
|
+
* Variant selection is entirely lightweight (see {@link
|
|
1664
|
+
* buildStructuralVariantSpecs}); a sibling's bytes are read and perceived
|
|
1665
|
+
* only for specs actually retained, and at most once per sibling id per
|
|
1666
|
+
* climb via `siblingGistMemo`. */
|
|
1579
1667
|
export function buildStructuralVariants(
|
|
1580
1668
|
ctx: MindContext,
|
|
1581
1669
|
ra: Region,
|
|
1582
1670
|
rb: Region,
|
|
1583
1671
|
sides: JunctionSynonymSides,
|
|
1672
|
+
siblingGistMemo: Map<number, Vec>,
|
|
1584
1673
|
): {
|
|
1585
1674
|
variants: StructuralVariant[];
|
|
1586
1675
|
exactLeft: StructuralPart;
|
|
1587
1676
|
exactRight: StructuralPart;
|
|
1588
1677
|
} {
|
|
1589
|
-
const
|
|
1590
|
-
const
|
|
1591
|
-
|
|
1592
|
-
const synonymVariants: StructuralVariant[] = [];
|
|
1593
|
-
for (const ls of sides.leftSiblings) {
|
|
1594
|
-
synonymVariants.push({
|
|
1595
|
-
left: siblingPart(ctx, ls, ra),
|
|
1596
|
-
right: exactRight,
|
|
1597
|
-
kind: "left-synonym",
|
|
1598
|
-
semanticConfidence: ls.score,
|
|
1599
|
-
leftSiblingId: ls.id,
|
|
1600
|
-
});
|
|
1601
|
-
}
|
|
1602
|
-
for (const rs of sides.rightSiblings) {
|
|
1603
|
-
synonymVariants.push({
|
|
1604
|
-
left: exactLeft,
|
|
1605
|
-
right: siblingPart(ctx, rs, rb),
|
|
1606
|
-
kind: "right-synonym",
|
|
1607
|
-
semanticConfidence: rs.score,
|
|
1608
|
-
rightSiblingId: rs.id,
|
|
1609
|
-
});
|
|
1610
|
-
}
|
|
1611
|
-
for (const ls of sides.leftSiblings) {
|
|
1612
|
-
for (const rs of sides.rightSiblings) {
|
|
1613
|
-
synonymVariants.push({
|
|
1614
|
-
left: siblingPart(ctx, ls, ra),
|
|
1615
|
-
right: siblingPart(ctx, rs, rb),
|
|
1616
|
-
kind: "double-synonym",
|
|
1617
|
-
semanticConfidence: Math.min(ls.score, rs.score),
|
|
1618
|
-
leftSiblingId: ls.id,
|
|
1619
|
-
rightSiblingId: rs.id,
|
|
1620
|
-
});
|
|
1621
|
-
}
|
|
1622
|
-
}
|
|
1678
|
+
const leftLen = ra.end - ra.start;
|
|
1679
|
+
const rightLen = rb.end - rb.start;
|
|
1623
1680
|
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
synonymVariants.sort((a, b) =>
|
|
1627
|
-
b.semanticConfidence - a.semanticConfidence ||
|
|
1628
|
-
VARIANT_KIND_ORDER[a.kind] - VARIANT_KIND_ORDER[b.kind] ||
|
|
1629
|
-
(a.leftSiblingId ?? -1) - (b.leftSiblingId ?? -1) ||
|
|
1630
|
-
(a.rightSiblingId ?? -1) - (b.rightSiblingId ?? -1)
|
|
1631
|
-
);
|
|
1681
|
+
const exactLeft: StructuralPart = { v: ra.v, len: leftLen };
|
|
1682
|
+
const exactRight: StructuralPart = { v: rb.v, len: rightLen };
|
|
1632
1683
|
|
|
1633
1684
|
const variants: StructuralVariant[] = [
|
|
1634
1685
|
{
|
|
@@ -1637,8 +1688,60 @@ export function buildStructuralVariants(
|
|
|
1637
1688
|
kind: "exact-exact",
|
|
1638
1689
|
semanticConfidence: 1,
|
|
1639
1690
|
},
|
|
1640
|
-
...synonymVariants.slice(0, ctx.cfg.haloQueryK),
|
|
1641
1691
|
];
|
|
1692
|
+
|
|
1693
|
+
// Same phrase-scale bound the cross-region junction ladder uses
|
|
1694
|
+
// (`maxInterior`): a sibling whose complete stored content exceeds it is
|
|
1695
|
+
// not materialized as a structural-resonance endpoint, keeping sibling
|
|
1696
|
+
// reconstruction phrase-scale even for a large deposit or conversation
|
|
1697
|
+
// root that merely appeared in a halo result.
|
|
1698
|
+
const maxSiblingBytes = (leftLen + rightLen) * ctx.space.maxGroup;
|
|
1699
|
+
|
|
1700
|
+
const specs = buildStructuralVariantSpecs(sides);
|
|
1701
|
+
const localGistMemo = new Map<number, Vec | null>();
|
|
1702
|
+
let retainedSynonyms = 0;
|
|
1703
|
+
|
|
1704
|
+
for (const spec of specs) {
|
|
1705
|
+
if (retainedSynonyms >= ctx.cfg.haloQueryK) break;
|
|
1706
|
+
|
|
1707
|
+
let left = exactLeft;
|
|
1708
|
+
let right = exactRight;
|
|
1709
|
+
|
|
1710
|
+
if (spec.leftSiblingId !== undefined) {
|
|
1711
|
+
const gist = loadBoundedSiblingGist(
|
|
1712
|
+
ctx,
|
|
1713
|
+
spec.leftSiblingId,
|
|
1714
|
+
maxSiblingBytes,
|
|
1715
|
+
siblingGistMemo,
|
|
1716
|
+
localGistMemo,
|
|
1717
|
+
);
|
|
1718
|
+
if (gist === null) continue;
|
|
1719
|
+
left = { v: gist, len: leftLen };
|
|
1720
|
+
}
|
|
1721
|
+
|
|
1722
|
+
if (spec.rightSiblingId !== undefined) {
|
|
1723
|
+
const gist = loadBoundedSiblingGist(
|
|
1724
|
+
ctx,
|
|
1725
|
+
spec.rightSiblingId,
|
|
1726
|
+
maxSiblingBytes,
|
|
1727
|
+
siblingGistMemo,
|
|
1728
|
+
localGistMemo,
|
|
1729
|
+
);
|
|
1730
|
+
if (gist === null) continue;
|
|
1731
|
+
right = { v: gist, len: rightLen };
|
|
1732
|
+
}
|
|
1733
|
+
|
|
1734
|
+
variants.push({
|
|
1735
|
+
left,
|
|
1736
|
+
right,
|
|
1737
|
+
kind: spec.kind,
|
|
1738
|
+
semanticConfidence: spec.semanticConfidence,
|
|
1739
|
+
leftSiblingId: spec.leftSiblingId,
|
|
1740
|
+
rightSiblingId: spec.rightSiblingId,
|
|
1741
|
+
});
|
|
1742
|
+
retainedSynonyms++;
|
|
1743
|
+
}
|
|
1744
|
+
|
|
1642
1745
|
return { variants, exactLeft, exactRight };
|
|
1643
1746
|
}
|
|
1644
1747
|
|
|
@@ -1675,6 +1778,7 @@ export async function structuralResonance(
|
|
|
1675
1778
|
ra: Region,
|
|
1676
1779
|
rb: Region,
|
|
1677
1780
|
sides: JunctionSynonymSides,
|
|
1781
|
+
siblingGistMemo: Map<number, Vec>,
|
|
1678
1782
|
k: number,
|
|
1679
1783
|
N: number,
|
|
1680
1784
|
reachMemo: Map<number, AncestorReach>,
|
|
@@ -1692,7 +1796,13 @@ export async function structuralResonance(
|
|
|
1692
1796
|
| { proposal: StructuralResonanceProposal; reach: AncestorReach; idf: number }
|
|
1693
1797
|
| null
|
|
1694
1798
|
> {
|
|
1695
|
-
const { variants } = buildStructuralVariants(
|
|
1799
|
+
const { variants } = buildStructuralVariants(
|
|
1800
|
+
ctx,
|
|
1801
|
+
ra,
|
|
1802
|
+
rb,
|
|
1803
|
+
sides,
|
|
1804
|
+
siblingGistMemo,
|
|
1805
|
+
);
|
|
1696
1806
|
if (trace) trace.variantBudget = ctx.cfg.haloQueryK;
|
|
1697
1807
|
|
|
1698
1808
|
const middleBytes = query.subarray(ra.end, rb.start);
|
|
@@ -1864,6 +1974,10 @@ async function crossRegionVotes(
|
|
|
1864
1974
|
//
|
|
1865
1975
|
// Only MAXIMAL spans compose: a span contained in another candidate is a
|
|
1866
1976
|
// fragment of that candidate's evidence, never independent of it.
|
|
1977
|
+
// Shared across every cross-region probe in this climb: a sibling
|
|
1978
|
+
// successfully reconstructed while probing one pair must not be read and
|
|
1979
|
+
// perceived again while probing another pair in the same climb.
|
|
1980
|
+
const siblingGistMemo = new Map<number, Vec>();
|
|
1867
1981
|
const votedSpans = new Set<string>();
|
|
1868
1982
|
for (const rv of rvs.votes) votedSpans.add(`${rv.start},${rv.end}`);
|
|
1869
1983
|
const seen = new Set<string>();
|
|
@@ -2155,6 +2269,7 @@ async function crossRegionVotes(
|
|
|
2155
2269
|
ra,
|
|
2156
2270
|
rb,
|
|
2157
2271
|
sides,
|
|
2272
|
+
siblingGistMemo,
|
|
2158
2273
|
k,
|
|
2159
2274
|
N,
|
|
2160
2275
|
reachMemo,
|
|
@@ -381,6 +381,7 @@ test("7/8/9. buildStructuralVariants always includes exact-exact, left-synonym,
|
|
|
381
381
|
ra,
|
|
382
382
|
rb,
|
|
383
383
|
sides,
|
|
384
|
+
new Map(),
|
|
384
385
|
);
|
|
385
386
|
assert.equal(variants[0].kind, "exact-exact");
|
|
386
387
|
assert.equal(variants[0].semanticConfidence, 1);
|
|
@@ -410,7 +411,7 @@ test("11. synonym variants are bounded to haloQueryK, in addition to the always-
|
|
|
410
411
|
enc("crimson"),
|
|
411
412
|
enc("square"),
|
|
412
413
|
);
|
|
413
|
-
const { variants } = buildStructuralVariants(m, ra, rb, sides);
|
|
414
|
+
const { variants } = buildStructuralVariants(m, ra, rb, sides, new Map());
|
|
414
415
|
assert.ok(variants.length <= 1 + m.cfg.haloQueryK);
|
|
415
416
|
await m.store.close();
|
|
416
417
|
});
|
|
@@ -428,7 +429,7 @@ test("12. a sibling's structural part keeps the ORIGINAL query-region slot lengt
|
|
|
428
429
|
enc("crimson"),
|
|
429
430
|
enc("square"),
|
|
430
431
|
);
|
|
431
|
-
const { variants } = buildStructuralVariants(m, ra, rb, sides);
|
|
432
|
+
const { variants } = buildStructuralVariants(m, ra, rb, sides, new Map());
|
|
432
433
|
for (const v of variants) {
|
|
433
434
|
assert.equal(
|
|
434
435
|
v.left.len,
|
|
@@ -483,6 +484,7 @@ test("13/18. structuralResonance composes the real middle query bytes and applie
|
|
|
483
484
|
ra,
|
|
484
485
|
rb,
|
|
485
486
|
sides,
|
|
487
|
+
new Map(),
|
|
486
488
|
12,
|
|
487
489
|
N,
|
|
488
490
|
new Map(),
|
|
@@ -520,7 +522,7 @@ test("15. two variants proposing the SAME candidate keep only the higher-effecti
|
|
|
520
522
|
enc("crimson"),
|
|
521
523
|
enc("square"),
|
|
522
524
|
);
|
|
523
|
-
const { variants } = buildStructuralVariants(m, ra, rb, sides);
|
|
525
|
+
const { variants } = buildStructuralVariants(m, ra, rb, sides, new Map());
|
|
524
526
|
// Directly exercise the merge logic's contract: build two synthetic
|
|
525
527
|
// proposals for the SAME id with different effectiveScore and confirm the
|
|
526
528
|
// higher one is what a caller keeps (mirrors betterProposal's tie-break,
|
|
@@ -533,6 +535,7 @@ test("15. two variants proposing the SAME candidate keep only the higher-effecti
|
|
|
533
535
|
ra,
|
|
534
536
|
rb,
|
|
535
537
|
sides,
|
|
538
|
+
new Map(),
|
|
536
539
|
12,
|
|
537
540
|
N,
|
|
538
541
|
new Map(),
|