@hviana/sema 0.5.2 → 0.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/AGENTS.md +115 -53
  2. package/HOW_IT_WORKS.md +291 -184
  3. package/jsr.json +6 -0
  4. package/package.json +1 -1
  5. package/src/mind/bridge.ts +10 -104
  6. package/src/mind/match.ts +497 -7
  7. package/src/mind/{prefix-completion.ts → mechanisms/prefix-completion.ts} +66 -92
  8. package/src/mind/mechanisms/recall.ts +38 -129
  9. package/src/mind/mechanisms/reference.ts +343 -0
  10. package/src/mind/mind.ts +12 -8
  11. package/src/mind/pipeline-mechanism.ts +120 -3
  12. package/src/mind/pipeline.ts +16 -2
  13. package/src/mind/traverse.ts +92 -1
  14. package/src/store.ts +13 -4
  15. package/test/33-multi-candidate.test.mjs +21 -11
  16. package/test/70-prefix-completion.test.mjs +1 -1
  17. package/test/72-prefix-candidate-supply.test.mjs +7 -9
  18. package/test/74-prefix-trap-not-sprung-early.test.mjs +1 -1
  19. package/test/76-reference-binding.test.mjs +543 -0
  20. package/dist/example/demo.d.ts +0 -1
  21. package/dist/example/demo.js +0 -39
  22. package/dist/example/train_base.d.ts +0 -93
  23. package/dist/example/train_base.js +0 -2269
  24. package/dist/src/alphabet.d.ts +0 -7
  25. package/dist/src/alphabet.js +0 -33
  26. package/dist/src/alu/src/alu.d.ts +0 -185
  27. package/dist/src/alu/src/alu.js +0 -440
  28. package/dist/src/alu/src/expr.d.ts +0 -61
  29. package/dist/src/alu/src/expr.js +0 -318
  30. package/dist/src/alu/src/index.d.ts +0 -11
  31. package/dist/src/alu/src/index.js +0 -19
  32. package/dist/src/alu/src/kernel-arith.d.ts +0 -16
  33. package/dist/src/alu/src/kernel-arith.js +0 -264
  34. package/dist/src/alu/src/kernel-bits.d.ts +0 -19
  35. package/dist/src/alu/src/kernel-bits.js +0 -152
  36. package/dist/src/alu/src/kernel-logic.d.ts +0 -4
  37. package/dist/src/alu/src/kernel-logic.js +0 -60
  38. package/dist/src/alu/src/kernel-nd.d.ts +0 -3
  39. package/dist/src/alu/src/kernel-nd.js +0 -208
  40. package/dist/src/alu/src/kernel-numeric.d.ts +0 -54
  41. package/dist/src/alu/src/kernel-numeric.js +0 -366
  42. package/dist/src/alu/src/operation.d.ts +0 -168
  43. package/dist/src/alu/src/operation.js +0 -189
  44. package/dist/src/alu/src/parser.d.ts +0 -221
  45. package/dist/src/alu/src/parser.js +0 -577
  46. package/dist/src/alu/src/resonance.d.ts +0 -55
  47. package/dist/src/alu/src/resonance.js +0 -126
  48. package/dist/src/alu/src/text.d.ts +0 -31
  49. package/dist/src/alu/src/text.js +0 -73
  50. package/dist/src/alu/src/value.d.ts +0 -109
  51. package/dist/src/alu/src/value.js +0 -300
  52. package/dist/src/alu/test/alu.test.d.ts +0 -1
  53. package/dist/src/alu/test/alu.test.js +0 -764
  54. package/dist/src/bytes.d.ts +0 -14
  55. package/dist/src/bytes.js +0 -59
  56. package/dist/src/canon.d.ts +0 -45
  57. package/dist/src/canon.js +0 -85
  58. package/dist/src/config.d.ts +0 -111
  59. package/dist/src/config.js +0 -91
  60. package/dist/src/derive/src/deduction.d.ts +0 -136
  61. package/dist/src/derive/src/deduction.js +0 -159
  62. package/dist/src/derive/src/index.d.ts +0 -8
  63. package/dist/src/derive/src/index.js +0 -11
  64. package/dist/src/derive/src/priority-queue.d.ts +0 -20
  65. package/dist/src/derive/src/priority-queue.js +0 -73
  66. package/dist/src/derive/src/rewrite.d.ts +0 -56
  67. package/dist/src/derive/src/rewrite.js +0 -100
  68. package/dist/src/derive/src/trie.d.ts +0 -90
  69. package/dist/src/derive/src/trie.js +0 -217
  70. package/dist/src/derive/test/derive.test.d.ts +0 -1
  71. package/dist/src/derive/test/derive.test.js +0 -122
  72. package/dist/src/extension.d.ts +0 -37
  73. package/dist/src/extension.js +0 -7
  74. package/dist/src/geometry.d.ts +0 -233
  75. package/dist/src/geometry.js +0 -1089
  76. package/dist/src/index.d.ts +0 -17
  77. package/dist/src/index.js +0 -19
  78. package/dist/src/ingest-cache.d.ts +0 -41
  79. package/dist/src/ingest-cache.js +0 -165
  80. package/dist/src/meter.d.ts +0 -176
  81. package/dist/src/meter.js +0 -274
  82. package/dist/src/mind/articulation.d.ts +0 -6
  83. package/dist/src/mind/articulation.js +0 -99
  84. package/dist/src/mind/attention.d.ts +0 -430
  85. package/dist/src/mind/attention.js +0 -2418
  86. package/dist/src/mind/bridge.d.ts +0 -39
  87. package/dist/src/mind/bridge.js +0 -998
  88. package/dist/src/mind/canonical.d.ts +0 -34
  89. package/dist/src/mind/canonical.js +0 -93
  90. package/dist/src/mind/frame-filler.d.ts +0 -15
  91. package/dist/src/mind/frame-filler.js +0 -535
  92. package/dist/src/mind/graph-search.d.ts +0 -294
  93. package/dist/src/mind/graph-search.js +0 -996
  94. package/dist/src/mind/index.d.ts +0 -9
  95. package/dist/src/mind/index.js +0 -5
  96. package/dist/src/mind/junction.d.ts +0 -137
  97. package/dist/src/mind/junction.js +0 -358
  98. package/dist/src/mind/learning.d.ts +0 -75
  99. package/dist/src/mind/learning.js +0 -265
  100. package/dist/src/mind/match.d.ts +0 -192
  101. package/dist/src/mind/match.js +0 -666
  102. package/dist/src/mind/mechanisms/alu.d.ts +0 -4
  103. package/dist/src/mind/mechanisms/alu.js +0 -36
  104. package/dist/src/mind/mechanisms/cast.d.ts +0 -89
  105. package/dist/src/mind/mechanisms/cast.js +0 -1186
  106. package/dist/src/mind/mechanisms/confluence.d.ts +0 -24
  107. package/dist/src/mind/mechanisms/confluence.js +0 -271
  108. package/dist/src/mind/mechanisms/cover.d.ts +0 -6
  109. package/dist/src/mind/mechanisms/cover.js +0 -232
  110. package/dist/src/mind/mechanisms/extraction.d.ts +0 -33
  111. package/dist/src/mind/mechanisms/extraction.js +0 -327
  112. package/dist/src/mind/mechanisms/recall.d.ts +0 -16
  113. package/dist/src/mind/mechanisms/recall.js +0 -558
  114. package/dist/src/mind/mind.d.ts +0 -386
  115. package/dist/src/mind/mind.js +0 -754
  116. package/dist/src/mind/pipeline-mechanism.d.ts +0 -183
  117. package/dist/src/mind/pipeline-mechanism.js +0 -521
  118. package/dist/src/mind/pipeline.d.ts +0 -49
  119. package/dist/src/mind/pipeline.js +0 -331
  120. package/dist/src/mind/prefix-completion.d.ts +0 -59
  121. package/dist/src/mind/prefix-completion.js +0 -270
  122. package/dist/src/mind/primitives.d.ts +0 -85
  123. package/dist/src/mind/primitives.js +0 -333
  124. package/dist/src/mind/rationale.d.ts +0 -139
  125. package/dist/src/mind/rationale.js +0 -163
  126. package/dist/src/mind/reasoning.d.ts +0 -42
  127. package/dist/src/mind/reasoning.js +0 -305
  128. package/dist/src/mind/recognition.d.ts +0 -20
  129. package/dist/src/mind/recognition.js +0 -696
  130. package/dist/src/mind/resonance.d.ts +0 -35
  131. package/dist/src/mind/resonance.js +0 -365
  132. package/dist/src/mind/trace.d.ts +0 -15
  133. package/dist/src/mind/trace.js +0 -73
  134. package/dist/src/mind/traverse.d.ts +0 -158
  135. package/dist/src/mind/traverse.js +0 -716
  136. package/dist/src/mind/types.d.ts +0 -418
  137. package/dist/src/mind/types.js +0 -179
  138. package/dist/src/rabitq-ivf/src/database.d.ts +0 -113
  139. package/dist/src/rabitq-ivf/src/database.js +0 -201
  140. package/dist/src/rabitq-ivf/src/index.d.ts +0 -7
  141. package/dist/src/rabitq-ivf/src/index.js +0 -4
  142. package/dist/src/rabitq-ivf/src/ivf.d.ts +0 -200
  143. package/dist/src/rabitq-ivf/src/ivf.js +0 -1165
  144. package/dist/src/rabitq-ivf/src/prng.d.ts +0 -19
  145. package/dist/src/rabitq-ivf/src/prng.js +0 -36
  146. package/dist/src/rabitq-ivf/src/rabitq.d.ts +0 -95
  147. package/dist/src/rabitq-ivf/src/rabitq.js +0 -313
  148. package/dist/src/sema.d.ts +0 -41
  149. package/dist/src/sema.js +0 -77
  150. package/dist/src/store-sqlite.d.ts +0 -184
  151. package/dist/src/store-sqlite.js +0 -942
  152. package/dist/src/store.d.ts +0 -762
  153. package/dist/src/store.js +0 -1823
  154. package/dist/src/vec.d.ts +0 -31
  155. package/dist/src/vec.js +0 -109
  156. package/src/mind/frame-filler.ts +0 -604
  157. package/test/69-frame-filler.test.mjs +0 -115
@@ -1,35 +0,0 @@
1
- import type { MindContext } from "./types.js";
2
- /** The connector that belongs BETWEEN two adjacent results — the graded
3
- * junction ladder described in the module note above. Returns null when
4
- * the graph holds no evidence that the two ever ran together. */
5
- export declare function bridge(ctx: MindContext, left: Uint8Array, right: Uint8Array, interiorAllowance?: number): Promise<Uint8Array | null>;
6
- /** Join two spans with the learnt connector between them, when one exists —
7
- * the composition step every out-of-search assembly (multi-topic fusion,
8
- * CAST's substitution and comparison) shares. A miss joins the pieces BARE
9
- * and is never silent: it emits the same `bridgeMiss` trace step everywhere,
10
- * so a degraded join is visible in the rationale regardless of which
11
- * mechanism paid it. (The in-search connector splice in graph-search.ts is
12
- * the same concept inside the deduction, where the join is a costed rule.) */
13
- export declare function joinWithBridge(ctx: MindContext, left: Uint8Array, right: Uint8Array): Promise<Uint8Array>;
14
- /** The pivot a produced answer bridges through: the longest UNCONSUMED learnt
15
- * CONTEXT (a node bearing a continuation edge) whose bytes `answer` literally
16
- * contains. Candidates are gathered by resonating the answer's sub-regions
17
- * (breadth-first, leaves skipped, probes capped by branch count), then
18
- * confirmed by exact byte containment — a near-resonance alone never hops.
19
- *
20
- * `voiced` carries the BYTES of the anchors the grounding mechanism declared
21
- * it spoke for, and no candidate CONTAINED IN one of them may be pivoted
22
- * through. Node identity alone is too coarse a reading of "already spoken
23
- * for": the same content is interned at several scales, so a strict fragment
24
- * of a voiced anchor is a different id carrying no evidence the anchor did
25
- * not already carry. Measured on test/29 C2 — CAST voiced "William
26
- * Shakespeare" (id 676) and the pivot hopped through "speare" (id 606, not
27
- * in `consumed`) straight into that analog's own biography, which is exactly
28
- * what the comparison had refused to voice. The rule is CONTAINMENT, not
29
- * overlap, so C3's genuine further hop — "Mona Lisa", a term inside the seat
30
- * sentence but part of NEITHER analog — still fires. */
31
- export declare function pivotInto(ctx: MindContext, answer: Uint8Array, consumed: ReadonlySet<number>, voiced?: readonly Uint8Array[]): Promise<number | null>;
32
- export declare function meaningOf(ctx: MindContext, bytes: Uint8Array, anchors: ReadonlyArray<{
33
- name: string;
34
- form: Uint8Array;
35
- }>): Promise<string | null>;
@@ -1,365 +0,0 @@
1
- // resonance.ts — Pattern A: Resonance Search (Section 3 of the mind).
2
- //
3
- // Address → Resonate → filter by Traverse/Read predicates → transform.
4
- // Used by bridge, recallByResonance, pivotInto, meaningOf.
5
- // (The graded locate() matcher formerly here lives in match.ts.)
6
- import { rItem } from "./trace.js";
7
- import { cosine } from "../vec.js";
8
- import { mergeThreshold } from "../geometry.js";
9
- import { concat2, concatBytes, indexOf } from "../bytes.js";
10
- import { gistOf, read, resolve, walkTree } from "./primitives.js";
11
- import { perceive } from "./primitives.js";
12
- import { argmaxBy, argmaxCosine, candidateGist, hubBound } from "./traverse.js";
13
- import { cachedRead, junctionContainers, junctionSynonyms, walkCache, } from "./junction.js";
14
- import { recognise } from "./recognition.js";
15
- // ── The bridge — the junction between two adjacent results ──────────────────
16
- //
17
- // A GRADED evidence ladder, exact before approximate (the same discipline as
18
- // locate/alignGraded):
19
- //
20
- // 1. JUNCTION CONTAINERS by content-addressed identity. Hash-consing means
21
- // "which learnt wholes ran L and R together?" is a DAG ascent, not a
22
- // similarity guess: any deposit containing L's bytes shares L's node (or
23
- // L's canonical-window ids — position-independent identities), so
24
- // climbing parents + containment links from L and R reaches every
25
- // container exactly. The legacy resonance seed (gist of the bare
26
- // concatenation — an object never learnt) could rank the true container
27
- // out of its top-k; the ascent cannot.
28
- //
29
- // 2. EDGE JUNCTIONS. A continuation edge IS junction information: when a
30
- // learnt continuation of L contains R, the prefix before R is the learnt
31
- // glue ("what comes after L on the way to R"); symmetrically, a learnt
32
- // context of R that contains L yields its suffix after L. The legacy
33
- // bridge ignored edges entirely.
34
- //
35
- // 3. RESONANCE (the legacy path), kept as the last resort: containment
36
- // links absent or saturated, the ANN may still surface a container.
37
- //
38
- // Selection among several junctions: the response guide (ctx._edgeGuide — the
39
- // same disambiguator every projection uses) picks by gist resonance through
40
- // the session gist cache; ties prefer the SHORTEST interior (a junction
41
- // should not insert unnecessary glue), then the lowest node id
42
- // (deterministic, a property of the corpus, not the seed). An EMPTY interior
43
- // found by evidence is a confirmed adjacency — returned as such, never
44
- // confused with a miss (null).
45
- /** Rank junction candidates and return the best interior (see the module
46
- * note above for the order), or null when there are none. */
47
- function pickJunction(ctx, cands) {
48
- if (cands.length === 0)
49
- return null;
50
- if (cands.length === 1)
51
- return cands[0];
52
- const guide = ctx._edgeGuide;
53
- const scored = cands.map((c) => {
54
- const g = guide !== null ? candidateGist(ctx, c.id) : null;
55
- return { ...c, score: g !== null && guide !== null ? cosine(guide, g) : 0 };
56
- });
57
- scored.sort((a, b) => b.score - a.score ||
58
- a.interior.length - b.interior.length ||
59
- a.id - b.id);
60
- return scored[0];
61
- }
62
- /** Tier 2: junctions learnt as EDGES. A continuation of left that contains
63
- * right carries the glue as its prefix; a context of right that contains
64
- * left carries it as its suffix. Fan-outs read through the store's LIMITed
65
- * edge reads at the hub bound, like every edge walk. */
66
- function junctionEdges(ctx, left, right, maxContainer) {
67
- const bound = hubBound(ctx);
68
- const out = [];
69
- const lId = resolve(ctx, left);
70
- if (lId !== null) {
71
- // A FULL √N page of continuations means the side is an edge hub: its
72
- // fan-out is non-discriminative for a junction (the same common-content
73
- // abstention as tier 1's containment gate), and reading √N capped
74
- // continuations per pair is exactly the cost a miss must not pay.
75
- // Below the page the list IS the full fan — read exactly.
76
- const nexts = ctx.store.nextFirst(lId, bound);
77
- if (nexts.length < bound) {
78
- const cache = walkCache(ctx);
79
- for (const n of nexts) {
80
- // Prefix-capped read (same phrase-scale discipline as tier 1): a
81
- // continuation longer than any admissible container cannot carry a
82
- // junction-sized glue — skipped without reconstructing it.
83
- const b = cachedRead(ctx, cache, n, maxContainer);
84
- if (b.length > maxContainer)
85
- continue;
86
- const ri = indexOf(b, right, 0);
87
- if (ri >= 0)
88
- out.push({ id: n, interior: b.subarray(0, ri) });
89
- }
90
- }
91
- }
92
- const rId = resolve(ctx, right);
93
- if (rId !== null) {
94
- const prevs = ctx.store.prevFirst(rId, bound);
95
- if (prevs.length < bound) {
96
- const cache = walkCache(ctx);
97
- for (const p of prevs) {
98
- const b = cachedRead(ctx, cache, p, maxContainer);
99
- if (b.length > maxContainer)
100
- continue;
101
- const li = indexOf(b, left, 0);
102
- if (li >= 0) {
103
- out.push({ id: p, interior: b.subarray(li + left.length) });
104
- }
105
- }
106
- }
107
- }
108
- return out;
109
- }
110
- /** A byte string as a string, ONE code unit per byte — injective, so it is
111
- * safe to build a cache key from. Chunked to keep the spread within the
112
- * engine's argument limit on long contexts. */
113
- function latin1(b) {
114
- let s = "";
115
- for (let i = 0; i < b.length; i += 4096) {
116
- s += String.fromCharCode(...b.subarray(i, i + 4096));
117
- }
118
- return s;
119
- }
120
- /** Per-response memo of bridge results, keyed by the response's lifecycle
121
- * object (ctx.climbMemo — created fresh by respond() and nulled after, so
122
- * entries can never outlive the read-only window they are valid in). The
123
- * cover's connector pre-resolution asks for the same byte pair through up
124
- * to eight (site, answer) combinations, and fusion/CAST re-ask pairs the
125
- * cover already resolved — each unique (left, right, allowance) is walked
126
- * once per response. Outside a response (climbMemo null) nothing is
127
- * memoised, preserving standalone behaviour. */
128
- const bridgeMemo = new WeakMap();
129
- /** The connector that belongs BETWEEN two adjacent results — the graded
130
- * junction ladder described in the module note above. Returns null when
131
- * the graph holds no evidence that the two ever ran together. */
132
- export async function bridge(ctx, left, right, interiorAllowance) {
133
- if (left.length === 0 || right.length === 0)
134
- return null;
135
- let memo;
136
- let memoKey;
137
- if (ctx.climbMemo !== null) {
138
- memo = bridgeMemo.get(ctx.climbMemo);
139
- if (memo === undefined)
140
- bridgeMemo.set(ctx.climbMemo, memo = new Map());
141
- // KEYED ON BYTES, NOT ON TEXT. This key used to be built with
142
- // `decodeText`, which decodes lossily AND strips NUL — so it is not
143
- // injective on raw bytes, and a cache key that is not injective returns
144
- // one input's answer for another's. `bridge` takes arbitrary byte
145
- // strings, and this system pads with NUL, so the collision is reachable:
146
- // [65,0,66] and [65,66,0] have the same length and both decode to "AB",
147
- // giving them the same key and the same cached bridge.
148
- //
149
- // `latin1` maps each byte to exactly one code unit and is therefore
150
- // injective; both lengths are included so the two sides cannot be
151
- // confused by a shared boundary, which is what the separator was for.
152
- memoKey = `${interiorAllowance ?? -1}:${left.length}:${right.length}:` +
153
- latin1(left) + latin1(right);
154
- const hit = memo.get(memoKey);
155
- if (hit !== undefined)
156
- return hit;
157
- }
158
- const result = await bridgeUncached(ctx, left, right, interiorAllowance);
159
- if (memo !== undefined && memoKey !== undefined)
160
- memo.set(memoKey, result);
161
- return result;
162
- }
163
- async function bridgeUncached(ctx, left, right, interiorAllowance) {
164
- const joined = concat2(left, right);
165
- // The PHRASE-SCALE contract: a junction container is a learnt whole the
166
- // pair nearly exhausts. By default the glue between the two sides may be
167
- // up to W (the perceptual quantum) times the content it joins; a caller
168
- // that KNOWS its interior legitimately carries more (the n-ary connector,
169
- // whose interior holds the intermediate answers themselves) passes its own
170
- // allowance. This is what lets the identity walks read every candidate
171
- // with a hard byte cap instead of reconstructing corpus-sized deposits.
172
- const maxInterior = interiorAllowance ??
173
- (left.length + right.length) * ctx.space.maxGroup;
174
- const maxContainer = joined.length + maxInterior;
175
- // Tier 1 — junction containers, by content-addressed identity.
176
- const container = pickJunction(ctx, junctionContainers(ctx, left, right, maxContainer));
177
- if (container !== null) {
178
- ctx.trace?.step("bridge", [rItem(left, "left"), rItem(right, "right")], [rItem(container.interior, "connector", container.id)], "junction container — a learnt whole runs the two together (content-addressed ascent)");
179
- return container.interior;
180
- }
181
- // Tier 2 — junctions learnt as edges.
182
- const edge = pickJunction(ctx, junctionEdges(ctx, left, right, maxContainer));
183
- if (edge !== null) {
184
- ctx.trace?.step("bridge", [rItem(left, "left"), rItem(right, "right")], [rItem(edge.interior, "connector", edge.id)], "edge junction — a learnt continuation/context carries the glue between the two");
185
- return edge.interior;
186
- }
187
- // Tier 2.5 — synonym junctions: the content-addressed container search
188
- // applied to halo siblings of left/right. Container evidence is exact
189
- // (same DAG ascent as tier 1, with window-id-enhanced seeds); the
190
- // relaxation is only in which form occupies one side.
191
- const synonym = pickJunction(ctx, await junctionSynonyms(ctx, left, right, maxInterior));
192
- if (synonym !== null) {
193
- ctx.trace?.step("bridge", [rItem(left, "left"), rItem(right, "right")], [rItem(synonym.interior, "connector", synonym.id)], "synonym junction — a halo sibling of one answer runs together with the other in a learnt whole");
194
- return synonym.interior;
195
- }
196
- // Tier 3 — the legacy resonance path (approximate, last resort).
197
- const hits = await ctx.store.resonate(gistOf(ctx, joined), ctx.cfg.recallQueryK * 2);
198
- // `hits` arrive nearest-first, so the first containment-passing hit is also
199
- // the best-scoring container — no further evidence comparison is needed.
200
- for (const h of hits) {
201
- // Same phrase-scale cap as the identity tiers: a hit longer than any
202
- // admissible container is skipped without reconstructing it.
203
- const f = read(ctx, h.id, maxContainer + 1);
204
- if (f.length > maxContainer)
205
- continue;
206
- if (f.length <= joined.length)
207
- continue; // no room for a connector
208
- const li = indexOf(f, left, 0);
209
- if (li < 0)
210
- continue;
211
- const ri = indexOf(f, right, li + left.length);
212
- if (ri < 0)
213
- continue;
214
- ctx.trace?.step("bridge", [rItem(left, "left"), rItem(right, "right")], [rItem(f.subarray(li + left.length, ri), "connector", h.id)], "resonant container — found by whole-gist resonance (approximate fallback)");
215
- return f.subarray(li + left.length, ri);
216
- }
217
- return null;
218
- }
219
- /** Join two spans with the learnt connector between them, when one exists —
220
- * the composition step every out-of-search assembly (multi-topic fusion,
221
- * CAST's substitution and comparison) shares. A miss joins the pieces BARE
222
- * and is never silent: it emits the same `bridgeMiss` trace step everywhere,
223
- * so a degraded join is visible in the rationale regardless of which
224
- * mechanism paid it. (The in-search connector splice in graph-search.ts is
225
- * the same concept inside the deduction, where the join is a costed rule.) */
226
- export async function joinWithBridge(ctx, left, right) {
227
- const link = await bridge(ctx, left, right);
228
- if (link === null) {
229
- ctx.trace?.step("bridgeMiss", [rItem(left, "left"), rItem(right, "right")], [], "no learnt connector resonated between these pieces — concatenated bare");
230
- return concat2(left, right);
231
- }
232
- return concatBytes([left, link, right]);
233
- }
234
- /** The pivot a produced answer bridges through: the longest UNCONSUMED learnt
235
- * CONTEXT (a node bearing a continuation edge) whose bytes `answer` literally
236
- * contains. Candidates are gathered by resonating the answer's sub-regions
237
- * (breadth-first, leaves skipped, probes capped by branch count), then
238
- * confirmed by exact byte containment — a near-resonance alone never hops.
239
- *
240
- * `voiced` carries the BYTES of the anchors the grounding mechanism declared
241
- * it spoke for, and no candidate CONTAINED IN one of them may be pivoted
242
- * through. Node identity alone is too coarse a reading of "already spoken
243
- * for": the same content is interned at several scales, so a strict fragment
244
- * of a voiced anchor is a different id carrying no evidence the anchor did
245
- * not already carry. Measured on test/29 C2 — CAST voiced "William
246
- * Shakespeare" (id 676) and the pivot hopped through "speare" (id 606, not
247
- * in `consumed`) straight into that analog's own biography, which is exactly
248
- * what the comparison had refused to voice. The rule is CONTAINMENT, not
249
- * overlap, so C3's genuine further hop — "Mona Lisa", a term inside the seat
250
- * sentence but part of NEITHER analog — still fires. */
251
- export async function pivotInto(ctx, answer, consumed, voiced = []) {
252
- const k = ctx.cfg.recallQueryK;
253
- // ONE perception of the answer, shared by the probe budget and the walk —
254
- // this used to fold the same bytes twice, back to back, on every hop.
255
- const tree = perceive(ctx, answer);
256
- // Probe budget: one per branch node, CAPPED at k. The sweep is a
257
- // resonance-shortlist question ("which learnt contexts does this answer
258
- // contain?"), so it carries the same k budget every resonance read does —
259
- // an answer's branch count grows with its length, and probing every
260
- // branch of a long answer made the pivot sweep the dominant ANN cost of
261
- // multi-hop reasoning at corpus scale (profiled: ~150 ANN queries per
262
- // response on conversation-length answers). Breadth-first order means
263
- // the k probes spent are the LARGEST regions — the ones that name learnt
264
- // contexts; and recognition below still contributes every exact,
265
- // content-addressed containment candidate regardless of the probe budget,
266
- // so short answers (branchCount ≤ k) keep the identical exhaustive sweep.
267
- let branchCount = 0;
268
- walkTree(tree, 0, (n) => {
269
- if (n.kids !== null)
270
- branchCount++;
271
- });
272
- const probeCap = Math.min(branchCount, k);
273
- const scored = new Map();
274
- const queue = [tree];
275
- let probes = 0;
276
- while (queue.length > 0 && probes < probeCap) {
277
- const n = queue.shift();
278
- if (n.kids === null)
279
- continue; // a leaf never names a learnt context
280
- probes++;
281
- for (const hit of await ctx.store.resonate(n.v, k)) {
282
- if (!consumed.has(hit.id) && ctx.store.hasNext(hit.id)) {
283
- const prev = scored.get(hit.id) ?? 0;
284
- if (hit.score > prev)
285
- scored.set(hit.id, hit.score);
286
- }
287
- }
288
- for (const c of n.kids)
289
- queue.push(c); // breadth-first: larger regions first
290
- }
291
- const rec = recognise(ctx, answer);
292
- for (const s of rec.sites) {
293
- if (!consumed.has(s.payload) && ctx.store.hasNext(s.payload)) {
294
- scored.set(s.payload, Math.max(scored.get(s.payload) ?? 0, 1));
295
- }
296
- }
297
- // Byte containment, longest wins — the answer literally contains the
298
- // pivot's bytes, and the biggest well-evidenced span is the real pivot.
299
- const found = argmaxBy(scored.keys(), (id) => {
300
- // A PIVOT MUST BE A THING THE CORPUS DEPOSITED, NOT A PIECE OF ONE.
301
- // "Longest wins" ranks candidates but never asks whether the winner is
302
- // an entity at all, and by the time a chain reaches here `consumeAll`
303
- // has taken the answer's real contexts — so on a corpus of
304
- // near-identical records the field is left to whatever interned
305
- // fragments remain. Measured on a 200-line templated log corpus, query
306
- // "what happened to request_id=1042 and request_id=1077?": CAST
307
- // produced the correct comparison and one `pivotStep` replaced it
308
- // wholesale, pivoting through `s=70` — a four-byte tail of
309
- // `latency_ms=70` — onto an unrelated record (`handled 1130`).
310
- //
311
- // The separator is NOT length. Measured against the multi-hop tests'
312
- // own pivots: `Paris` (5 bytes), `Jupiter` (7), `lithium` (7), `Mona
313
- // Lisa` (9) against junk `s=70` (4) — a two-quantum floor, which
314
- // confluence.ts applies to a meet for the same "one window is not an
315
- // entity" reason, discards three of the four legitimate pivots.
316
- // Entities are simply short.
317
- //
318
- // What separates them is STRUCTURAL, and the store already holds it:
319
- //
320
- // s=70 parents 2 containers 1 prevCount 0 halo no
321
- // Paris parents 0 containers 0 prevCount 1 halo yes
322
- // Jupiter parents 0 containers 0 prevCount 1 halo yes
323
- // lithium parents 0 containers 0 prevCount 1 halo yes
324
- // Mona Lisa parents 0 containers 0 prevCount 1 halo yes
325
- //
326
- // A deposited whole — a context or an answer — is interned in its own
327
- // right and has neither structural parents nor containment links. A
328
- // fragment is addressable ONLY because window interning made its span
329
- // addressable inside something bigger, and that containment is exactly
330
- // what `parents`/`containers` record. Reasoning steps THROUGH a fact;
331
- // a span that was never a fact on its own is not one to step through.
332
- // No constant enters — it is a structural predicate, not a threshold.
333
- if (ctx.store.hasParents(id) || ctx.store.hasContainers(id)) {
334
- return -Infinity;
335
- }
336
- const bytes = read(ctx, id);
337
- if (indexOf(answer, bytes, 0) < 0)
338
- return -Infinity;
339
- for (const v of voiced)
340
- if (indexOf(v, bytes, 0) >= 0)
341
- return -Infinity;
342
- return bytes.length;
343
- }, 0, true);
344
- return found?.item ?? null;
345
- }
346
- /** Which of the given labelled forms a span MEANS — generic resonance over
347
- * perceived gists. Each anchor form's gist is memoised; the span's gist
348
- * is matched against them. Returns null when nothing resonates closely
349
- * enough — the caller declines rather than guessing. */
350
- const anchorGists = new WeakMap();
351
- export async function meaningOf(ctx, bytes, anchors) {
352
- if (bytes.length === 0 || anchors.length === 0)
353
- return null;
354
- let gists = anchorGists.get(anchors);
355
- if (!gists) {
356
- gists = anchors.map((a) => ({
357
- name: a.name,
358
- v: gistOf(ctx, a.form),
359
- }));
360
- anchorGists.set(anchors, gists);
361
- }
362
- const qv = gistOf(ctx, bytes);
363
- const found = argmaxCosine(qv, gists, (g) => g.v, mergeThreshold(ctx.store.D));
364
- return found?.item.name ?? null;
365
- }
@@ -1,15 +0,0 @@
1
- import type { MindContext } from "./types.js";
2
- import type { DerivationStep } from "./graph-search.js";
3
- import type { RationaleItem } from "./rationale.js";
4
- export declare function rItem(bytes: Uint8Array, role?: string, node?: number, span?: [number, number]): RationaleItem;
5
- export declare function rNode(ctx: MindContext, id: number, role?: string, score?: number): RationaleItem;
6
- export declare function rDeriv(ctx: MindContext, it: DerivationStep["conclusion"], role?: string): RationaleItem;
7
- /** The standard FALL-THROUGH closer every self-gating mechanism ends with:
8
- * close the open scope with no outputs and the reason, and return null so
9
- * the caller can `return fail("…")` in one expression. `t` is the scope an
10
- * enclosing `ctx.trace?.enter(...)` returned (undefined when not tracing). */
11
- export declare function traceFail(t: {
12
- done(outputs: RationaleItem[], note?: string): void;
13
- } | undefined): (note: string) => null;
14
- export declare const MOVE_NOTE: Record<string, string>;
15
- export declare function traceDerivation(ctx: MindContext, steps: ReadonlyArray<DerivationStep>): void;
@@ -1,73 +0,0 @@
1
- // trace.ts — trace instrumentation + persistence (Section 9 of the mind).
2
- //
3
- // rItem, rNode, rDeriv — build RationaleItems from bytes/nodes/derivations
4
- // traceDerivation — trace a full derivation proof tree
5
- // MOVE_NOTE — human-readable names for each derivation move
6
- import { read } from "./primitives.js";
7
- import { decodeText } from "./rationale.js";
8
- export function rItem(bytes, role, node, span) {
9
- return {
10
- text: decodeText(bytes),
11
- role,
12
- node: node ?? undefined,
13
- span,
14
- };
15
- }
16
- export function rNode(ctx, id, role, score) {
17
- return {
18
- text: decodeText(read(ctx, id)),
19
- node: id,
20
- role,
21
- score,
22
- };
23
- }
24
- export function rDeriv(ctx, it, role) {
25
- const text = it.bytes
26
- ? decodeText(it.bytes)
27
- : it.node !== undefined
28
- ? decodeText(read(ctx, it.node))
29
- : it.kind === "cover"
30
- ? `cover@${it.span[0]}`
31
- : `[${it.span[0]},${it.span[1]})`;
32
- return { text, role: role ?? it.kind, node: it.node, span: it.span };
33
- }
34
- /** The standard FALL-THROUGH closer every self-gating mechanism ends with:
35
- * close the open scope with no outputs and the reason, and return null so
36
- * the caller can `return fail("…")` in one expression. `t` is the scope an
37
- * enclosing `ctx.trace?.enter(...)` returned (undefined when not tracing). */
38
- export function traceFail(t) {
39
- return (note) => {
40
- t?.done([], note);
41
- return null;
42
- };
43
- }
44
- export const MOVE_NOTE = {
45
- "follow-edge": "follow a learned continuation edge — 'what follows what'",
46
- "concept-hop": "jump a concept (halo) link — a synonym's edge",
47
- "voice": "emit the asker's own wording for this form (articulation)",
48
- "ground": "a chain reached its terminal answer",
49
- "splice-connector": "splice a learnt connector between two rewrites",
50
- "split": "cut a span at a sub-leaf form boundary so a form can be reached",
51
- "fuse": "fuse adjacent fragments toward a deeper learned form",
52
- "recompose": "recompose fused parts into a learned whole that leads on",
53
- "bridge": "advance the cover frontier across this span",
54
- "pool-vote": "pool independent regions' evidence for a shared anchor (sum, not shortest path)",
55
- "axiom": "a seed: a perceived leaf, recognised form, or computed result",
56
- "step": "a derivation step",
57
- };
58
- export function traceDerivation(ctx, steps) {
59
- const t = ctx.trace;
60
- if (!t)
61
- return;
62
- const indexOfOrder = new Map();
63
- for (const s of steps) {
64
- const note = MOVE_NOTE[s.move] ?? s.move;
65
- const deps = s.producers
66
- .map((o) => indexOfOrder.get(o))
67
- .filter((x) => x !== undefined);
68
- const premises = s.premises.map((p) => rDeriv(ctx, p));
69
- const conclusion = [rDeriv(ctx, s.conclusion)];
70
- const index = t.step(s.move, premises, conclusion, s.cost > 0 ? `${note} (cost ${s.cost})` : note, deps.length > 0 ? deps : undefined);
71
- indexOfOrder.set(s.order, index);
72
- }
73
- }
@@ -1,158 +0,0 @@
1
- import { Vec } from "../vec.js";
2
- import type { AncestorReach, MindContext } from "./types.js";
3
- /** The reach memo this ask should use — see the note above.
4
- *
5
- * A TRACED response always gets a fresh, empty one. `AncestorReach`'s
6
- * `visited`/`maxDepth`/`saturation` fields are populated only when a trace
7
- * is attached, so an entry deposited by an untraced earlier turn would
8
- * silently black out the reach detail of a later traced one; and the trace's
9
- * reach payload is serialised by ITERATING this map, which must therefore
10
- * hold what THIS climb consulted, not the whole conversation's history.
11
- * Consistent with AGENTS §2.11: a traced response is a different machine —
12
- * never benchmark with a trace attached. */
13
- export declare function sharedReachMemo(ctx: MindContext): Map<number, AncestorReach>;
14
- /** Invalidate every session-lifetime structural read after a write. */
15
- export declare function invalidateStructuralCaches(ctx: MindContext): void;
16
- /** Climb the structural DAG from a node to its edge-bearing ancestor contexts.
17
- * Ascent stops at hub nodes (parents > √N) — their reach is non-discriminative.
18
- * When the start node has no structural parents, climbs from containment parents
19
- * (sub-span flat branches inheriting their chunks' context).
20
- *
21
- * `memo`, when given, caches whole climbs by start id for the duration of ONE
22
- * query (the store is read-only while a query is in flight, so a climb is a
23
- * pure function of the id). The consensus pipeline climbs the SAME anchors
24
- * repeatedly — regions sharing a chunk, and canonicalChunkId probing each
25
- * chunk's prefixes — so without the memo every repeat re-pays the full
26
- * fan-out reads. */
27
- export declare function edgeAncestors(ctx: MindContext, id: number, contextCount: number, memo?: Map<number, AncestorReach>): AncestorReach;
28
- /** Convenience: forward edges of a node. */
29
- export declare function nextOf(ctx: MindContext, id: number): number[];
30
- /** Convenience: reverse edges of a node. */
31
- export declare function prevOf(ctx: MindContext, id: number): number[];
32
- /** The uniform-expectation floor on a byte atom's corpus commonality: N
33
- * learnt contexts, each at least one perception chunk of up to W of the 256
34
- * possible byte values, contain a given atom in ≥ N·W/256 contexts on
35
- * average. An atom's TRUE containment is unmeasurable (atoms carry no
36
- * kid/contain links by construction), so this floor is the honest stand-in:
37
- * derived entirely from the corpus scale N, the perception window W, and
38
- * the alphabet size — never tuned. */
39
- export declare function atomReach(ctx: MindContext, contextCount: number): number;
40
- /** Whether a byte atom is a hub at this corpus scale — its commonality floor
41
- * {@link atomReach} exceeds the hub bound √N. Below it (small stores) an
42
- * atom votes and is recognised exactly as any stored form; above it the
43
- * alphabet is scaffolding everywhere and abstains. */
44
- export declare function atomIsHub(ctx: MindContext, contextCount: number): boolean;
45
- /** Whether a node LEADS SOMEWHERE — it bears a continuation edge or a halo.
46
- * The admission predicate recognition filters sites with (HOW_IT_WORKS
47
- * §15.3): a form that leads nowhere contributes nothing to any derivation.
48
- * Runs once per candidate span on the recognition hot path — `hasNext` is
49
- * cached per response (the same flat-branch ids are probed across prefix
50
- * variants by canonicalChunkId). `hasHalo` is not cached: it's a single
51
- * indexed point probe per candidate, and the candidates that reach this
52
- * check have already been filtered by hasNext above in edgeAncestors. */
53
- export declare function leadsSomewhere(ctx: MindContext, id: number): boolean;
54
- /** The structural IDF read of ONE node: how many distinct learnt contexts
55
- * its containment/edge climb reaches, or Infinity when it reaches none or
56
- * saturates (no usable identity evidence). The number every
57
- * discriminative-vs-scaffolding decision derives from — paired with the
58
- * half-dominance convention (geometry.dominates(reach, N)): content
59
- * reaching a corpus MINORITY of contexts discriminates (an entity, a
60
- * filler); content reaching a majority is frame scaffolding. */
61
- export declare function reachOf(ctx: MindContext, id: number, contextCount: number, memo?: Map<number, AncestorReach>): number;
62
- /** The corpus scale N — the count of DISTINCT learnt contexts, floored at 2
63
- * so its derived readings (ln N in the consensus floor, √N in the hub bound)
64
- * stay meaningful on a near-empty store. The one definition every consumer
65
- * of "how big is this corpus?" reads. */
66
- export declare function corpusN(ctx: MindContext): number;
67
- /** The hub bound √N itself (≥ 2 always, since N is floored at 2) — for
68
- * consumers that pass it to the store's LIMITed reads instead of capping a
69
- * materialised list. {@link hubCap} is the list-side reading of the same
70
- * convention. */
71
- export declare function hubBound(ctx: MindContext): number;
72
- /** Cap a candidate list at the hub bound √N (insertion order) — the ONE
73
- * fan-out convention every walk and disambiguation uses (see HOW_IT_WORKS
74
- * §8.6). A node connected to more than √N others is a hub whose individual
75
- * connections carry ~no discriminative information; materialising or scoring
76
- * them all would make single decisions scale with the corpus. */
77
- export declare function hubCap<T>(ctx: MindContext, ids: readonly T[]): readonly T[];
78
- /** Whether `descendant` lies within `ancestor`'s subtree — a structural DAG
79
- * relation read off the hash-consed `kids` lists, by a bounded explicit-stack
80
- * descent. Used by articulation to keep a voice from revoicing a fragment
81
- * OF that voice. */
82
- export declare function contains(ctx: MindContext, ancestor: number, descendant: number): boolean;
83
- /** The best-scoring item by cosine against `query`, among items scoring at
84
- * or above `threshold` — the shared arg-max every Pattern-A "which of these
85
- * resonates best" decision reduces to. `strict` picks the tie-break a
86
- * caller needs: `true` keeps the first-seen leader on a tie (`>`), the
87
- * default lets a later equal score take it (`>=`). */
88
- export declare function argmaxBy<T>(items: Iterable<T>, scoreOf: (item: T) => number, threshold: number, strict?: boolean): {
89
- item: T;
90
- score: number;
91
- } | null;
92
- export declare function argmaxCosine<T>(query: Vec, items: Iterable<T>, vecOf: (item: T) => Vec | null | undefined, threshold: number, strict?: boolean): {
93
- item: T;
94
- score: number;
95
- } | null;
96
- /** The guided-or-first continuation of a node, as answer-shaped bytes source:
97
- * chooseNext under the response guide, falling back to the FIRST-inserted
98
- * edge — the one no-guide convention chooseNext, project() and the search's
99
- * formRules all share. undefined when the node has no continuation. */
100
- export declare function guidedFirst(ctx: MindContext, id: number): number | undefined;
101
- export declare function guidedNext(ctx: MindContext, node: number): number | undefined;
102
- /** Disambiguate among a node's learnt continuations by distributional
103
- * support. NOTE the `guide` contract: its VALUE is deliberately unused —
104
- * only its PRESENCE gates disambiguation (a null guide means no query is in
105
- * flight, so structural walkers keep plain first-edge behaviour). The
106
- * gist-cosine of short answer candidates against a query guide is dominated
107
- * by accidental byte-pattern correlations, not semantic relatedness, so the
108
- * evidence consulted is structural: each candidate's reverse-edge support
109
- * count (see below). Contrast {@link chooseAmong}, the REVERSE-direction
110
- * disambiguator, whose candidates are whole learnt contexts — long enough
111
- * that their perceived gists ARE semantically meaningful — and which
112
- * therefore scores by guide cosine. The two directions consult different
113
- * halves of the evidence on purpose. */
114
- export declare function chooseNext(ctx: MindContext, id: number, guide?: Vec | null): number | undefined;
115
- /** The perceived gist of a candidate node, through the session gist cache.
116
- * Re-gisting a candidate is a full river fold of its bytes — the measured
117
- * recall bottleneck (a hub context offers up to √N continuations, EACH
118
- * re-perceived per pick). A node's bytes are immutable and perception is
119
- * pure, so the cached gist is valid for the store's lifetime. Exported for
120
- * every "score node ids against a guide" decision (chooseAmong here, the
121
- * bridge's junction pick) so they share ONE cache and one convention. */
122
- export declare function candidateGist(ctx: MindContext, c: number): Vec | null;
123
- export declare function chooseAmong(ctx: MindContext, candidates: readonly number[], guide: Vec): {
124
- id: number;
125
- score: number;
126
- };
127
- /** True when NO window of `query` discriminates anything — every stored
128
- * W-window it spells is contained by more places than the hub bound allows,
129
- * i.e. the whole query is corpus-global scaffolding.
130
- *
131
- * WHAT IT IS FOR. Several mechanisms ground a query through the literal
132
- * spans it did NOT explain, and those spans are the whole of their evidence.
133
- * When every one of them is a hub, the query says nothing the corpus can be
134
- * held to, and grounding it means picking one of thousands of continuations
135
- * it gives no evidence for — a fabrication whatever the answer happens to be.
136
- * Answering with silence there is the honest degradation contract (§2.13).
137
- *
138
- * MEASURED SEPARATION (trained store, hubBound 571) — this is categorical,
139
- * not marginal, and it is why the predicate lives here rather than being
140
- * spelled twice:
141
- * "What is the capital of" ALL saturated ("What":572) → fabricated
142
- * "What is the capital " ALL saturated ("What":572) → fabricated
143
- * "what is the capital of france" min "f fr":248 → correct
144
- * "What is the capitol of France?" min "f Fr":114 → correct
145
- * "WHAT IS THE CAPITAL OF FRANCE?" min "HE C":1 → correct
146
- * "What is the capital of France?" min "t i":4 → correct
147
- * "Who wrote Romeo and Juliet?" min "iet?":26 → correct
148
- * "What is the capital of Zamunda?" min "Zamu":3 → silent anyway
149
- * Note the last: the honest-silence probes are already refused on other
150
- * evidence and sit on the SAME side as the correct ones, so this predicate
151
- * is not what makes them silent and cannot be credited for them.
152
- *
153
- * NO NEW THRESHOLD (§2.2): `hubBound` is the √N reading of "hub" used
154
- * everywhere, and the containment read is clamped to it exactly as every
155
- * other fan-out read is (§2.8). A query with no stored window at all is NOT
156
- * scaffolding-only — it has no evidence either way, and its callers already
157
- * refuse it on their own terms. */
158
- export declare function allWindowsAreScaffolding(ctx: MindContext, query: Uint8Array): boolean;