@hviana/sema 0.1.5 → 0.1.7

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 (170) hide show
  1. package/AGENTS.md +6 -5
  2. package/CITATION.cff +49 -0
  3. package/HOW_IT_WORKS.md +11 -12
  4. package/README.md +7 -5
  5. package/dist/example/demo.js +25 -25
  6. package/dist/example/train_base.d.ts +19 -21
  7. package/dist/example/train_base.js +1700 -1952
  8. package/dist/src/alphabet.d.ts +3 -3
  9. package/dist/src/alphabet.js +24 -27
  10. package/dist/src/alu/src/alu.d.ts +169 -194
  11. package/dist/src/alu/src/alu.js +374 -414
  12. package/dist/src/alu/src/expr.d.ts +36 -43
  13. package/dist/src/alu/src/expr.js +252 -278
  14. package/dist/src/alu/src/index.d.ts +9 -98
  15. package/dist/src/alu/src/index.js +10 -64
  16. package/dist/src/alu/src/kernel-arith.d.ts +1 -5
  17. package/dist/src/alu/src/kernel-arith.js +195 -285
  18. package/dist/src/alu/src/kernel-bits.d.ts +1 -5
  19. package/dist/src/alu/src/kernel-bits.js +81 -115
  20. package/dist/src/alu/src/kernel-logic.js +33 -63
  21. package/dist/src/alu/src/kernel-nd.js +155 -195
  22. package/dist/src/alu/src/kernel-numeric.d.ts +16 -80
  23. package/dist/src/alu/src/kernel-numeric.js +259 -331
  24. package/dist/src/alu/src/operation.d.ts +112 -132
  25. package/dist/src/alu/src/operation.js +149 -163
  26. package/dist/src/alu/src/parser.d.ts +168 -175
  27. package/dist/src/alu/src/parser.js +382 -421
  28. package/dist/src/alu/src/resonance.d.ts +16 -25
  29. package/dist/src/alu/src/resonance.js +49 -56
  30. package/dist/src/alu/src/text.d.ts +3 -7
  31. package/dist/src/alu/src/text.js +31 -37
  32. package/dist/src/alu/src/value.d.ts +14 -14
  33. package/dist/src/alu/src/value.js +150 -160
  34. package/dist/src/alu/test/alu.test.js +543 -656
  35. package/dist/src/bytes.d.ts +1 -5
  36. package/dist/src/bytes.js +33 -40
  37. package/dist/src/config.d.ts +99 -102
  38. package/dist/src/config.js +78 -83
  39. package/dist/src/derive/src/deduction.d.ts +60 -62
  40. package/dist/src/derive/src/deduction.js +103 -109
  41. package/dist/src/derive/src/index.d.ts +1 -7
  42. package/dist/src/derive/src/priority-queue.d.ts +8 -8
  43. package/dist/src/derive/src/priority-queue.js +57 -61
  44. package/dist/src/derive/src/rewrite.d.ts +15 -18
  45. package/dist/src/derive/src/rewrite.js +59 -67
  46. package/dist/src/derive/src/trie.d.ts +56 -56
  47. package/dist/src/derive/src/trie.js +175 -179
  48. package/dist/src/derive/test/derive.test.js +96 -100
  49. package/dist/src/extension.d.ts +13 -16
  50. package/dist/src/geometry.d.ts +29 -43
  51. package/dist/src/geometry.js +324 -268
  52. package/dist/src/index.d.ts +2 -17
  53. package/dist/src/index.js +2 -12
  54. package/dist/src/ingest-cache.d.ts +25 -30
  55. package/dist/src/ingest-cache.js +108 -127
  56. package/dist/src/mind/articulation.d.ts +1 -5
  57. package/dist/src/mind/articulation.js +77 -112
  58. package/dist/src/mind/attention.d.ts +40 -108
  59. package/dist/src/mind/attention.js +754 -872
  60. package/dist/src/mind/canonical.d.ts +4 -19
  61. package/dist/src/mind/canonical.js +27 -31
  62. package/dist/src/mind/graph-search.d.ts +201 -225
  63. package/dist/src/mind/graph-search.js +742 -821
  64. package/dist/src/mind/index.d.ts +2 -10
  65. package/dist/src/mind/junction.d.ts +31 -58
  66. package/dist/src/mind/junction.js +172 -237
  67. package/dist/src/mind/learning.d.ts +16 -52
  68. package/dist/src/mind/learning.js +143 -165
  69. package/dist/src/mind/match.d.ts +20 -69
  70. package/dist/src/mind/match.js +259 -318
  71. package/dist/src/mind/mechanisms/alu.js +16 -16
  72. package/dist/src/mind/mechanisms/cast.d.ts +9 -13
  73. package/dist/src/mind/mechanisms/cast.js +363 -456
  74. package/dist/src/mind/mechanisms/confluence.d.ts +8 -12
  75. package/dist/src/mind/mechanisms/confluence.js +152 -183
  76. package/dist/src/mind/mechanisms/cover.d.ts +2 -8
  77. package/dist/src/mind/mechanisms/cover.js +148 -210
  78. package/dist/src/mind/mechanisms/extraction.d.ts +8 -34
  79. package/dist/src/mind/mechanisms/extraction.js +234 -288
  80. package/dist/src/mind/mechanisms/recall.d.ts +6 -10
  81. package/dist/src/mind/mechanisms/recall.js +141 -185
  82. package/dist/src/mind/mind.d.ts +194 -155
  83. package/dist/src/mind/mind.js +392 -289
  84. package/dist/src/mind/pipeline-mechanism.d.ts +112 -124
  85. package/dist/src/mind/pipeline-mechanism.js +161 -172
  86. package/dist/src/mind/pipeline.d.ts +4 -14
  87. package/dist/src/mind/pipeline.js +125 -189
  88. package/dist/src/mind/primitives.d.ts +20 -33
  89. package/dist/src/mind/primitives.js +124 -120
  90. package/dist/src/mind/rationale.d.ts +86 -98
  91. package/dist/src/mind/rationale.js +113 -121
  92. package/dist/src/mind/reasoning.d.ts +2 -13
  93. package/dist/src/mind/reasoning.js +129 -166
  94. package/dist/src/mind/recognition.d.ts +1 -4
  95. package/dist/src/mind/recognition.js +198 -210
  96. package/dist/src/mind/resonance.d.ts +5 -22
  97. package/dist/src/mind/resonance.js +0 -0
  98. package/dist/src/mind/trace.d.ts +6 -25
  99. package/dist/src/mind/trace.js +50 -58
  100. package/dist/src/mind/traverse.d.ts +29 -58
  101. package/dist/src/mind/traverse.js +344 -356
  102. package/dist/src/mind/types.d.ts +122 -127
  103. package/dist/src/mind/types.js +60 -69
  104. package/dist/src/rabitq-ivf/src/database.d.ts +113 -0
  105. package/dist/src/rabitq-ivf/src/database.js +201 -0
  106. package/dist/src/rabitq-ivf/src/index.d.ts +7 -0
  107. package/dist/src/{rabitq-hnsw → rabitq-ivf}/src/index.js +1 -3
  108. package/dist/src/rabitq-ivf/src/ivf.d.ts +200 -0
  109. package/dist/src/rabitq-ivf/src/ivf.js +1165 -0
  110. package/dist/src/rabitq-ivf/src/prng.d.ts +19 -0
  111. package/dist/src/rabitq-ivf/src/prng.js +36 -0
  112. package/dist/src/rabitq-ivf/src/rabitq.d.ts +95 -0
  113. package/dist/src/rabitq-ivf/src/rabitq.js +283 -0
  114. package/dist/src/sema.d.ts +9 -13
  115. package/dist/src/sema.js +26 -40
  116. package/dist/src/store-sqlite.d.ts +171 -166
  117. package/dist/src/store-sqlite.js +768 -662
  118. package/dist/src/store.d.ts +597 -630
  119. package/dist/src/store.js +1434 -1581
  120. package/dist/src/vec.d.ts +5 -9
  121. package/dist/src/vec.js +61 -73
  122. package/example/train_base.ts +33 -15
  123. package/index.html +65 -0
  124. package/package.json +1 -1
  125. package/src/alu/README.md +1 -1
  126. package/src/alu/src/index.ts +1 -1
  127. package/src/config.ts +19 -27
  128. package/src/geometry.ts +93 -1
  129. package/src/index.ts +6 -11
  130. package/src/mind/attention.ts +11 -6
  131. package/src/mind/mechanisms/recall.ts +29 -13
  132. package/src/mind/mind.ts +250 -19
  133. package/src/mind/primitives.ts +43 -6
  134. package/src/mind/recognition.ts +26 -8
  135. package/src/mind/traverse.ts +47 -0
  136. package/src/mind/types.ts +20 -21
  137. package/src/rabitq-ivf/README.md +56 -0
  138. package/src/rabitq-ivf/src/database.ts +276 -0
  139. package/src/{rabitq-hnsw → rabitq-ivf}/src/index.ts +2 -5
  140. package/src/rabitq-ivf/src/ivf.ts +1330 -0
  141. package/src/{rabitq-hnsw → rabitq-ivf}/src/prng.ts +1 -1
  142. package/src/store-sqlite.ts +204 -9
  143. package/src/store.ts +27 -34
  144. package/test/08-storage.test.mjs +3 -3
  145. package/test/13-conversation.test.mjs +190 -20
  146. package/test/14-scaling.test.mjs +2 -2
  147. package/test/35-ivf.test.mjs +263 -0
  148. package/test/36-bloom.test.mjs +123 -0
  149. package/dist/src/rabitq-hnsw/src/database.d.ts +0 -202
  150. package/dist/src/rabitq-hnsw/src/database.js +0 -405
  151. package/dist/src/rabitq-hnsw/src/heap.d.ts +0 -22
  152. package/dist/src/rabitq-hnsw/src/heap.js +0 -94
  153. package/dist/src/rabitq-hnsw/src/hnsw.d.ts +0 -125
  154. package/dist/src/rabitq-hnsw/src/hnsw.js +0 -500
  155. package/dist/src/rabitq-hnsw/src/index.d.ts +0 -15
  156. package/dist/src/rabitq-hnsw/src/prng.d.ts +0 -19
  157. package/dist/src/rabitq-hnsw/src/prng.js +0 -38
  158. package/dist/src/rabitq-hnsw/src/rabitq.d.ts +0 -95
  159. package/dist/src/rabitq-hnsw/src/rabitq.js +0 -299
  160. package/dist/src/rabitq-hnsw/src/store.d.ts +0 -162
  161. package/dist/src/rabitq-hnsw/src/store.js +0 -916
  162. package/dist/src/rabitq-hnsw/test/hnsw.test.d.ts +0 -1
  163. package/dist/src/rabitq-hnsw/test/hnsw.test.js +0 -1197
  164. package/src/rabitq-hnsw/README.md +0 -303
  165. package/src/rabitq-hnsw/src/database.ts +0 -492
  166. package/src/rabitq-hnsw/src/heap.ts +0 -90
  167. package/src/rabitq-hnsw/src/hnsw.ts +0 -514
  168. package/src/rabitq-hnsw/src/store.ts +0 -994
  169. package/src/rabitq-hnsw/test/hnsw.test.ts +0 -1213
  170. /package/src/{rabitq-hnsw → rabitq-ivf}/src/rabitq.ts +0 -0
@@ -4,12 +4,7 @@
4
4
  // index and grounds the nearest learned form. Four tiers, orderly degrading
5
5
  // from exact self-match to honest echo.
6
6
  import { cosine } from "../../vec.js";
7
- import {
8
- consensusFloor,
9
- identityBar,
10
- reachThreshold,
11
- significanceBar,
12
- } from "../../geometry.js";
7
+ import { consensusFloor, identityBar, reachThreshold, significanceBar, } from "../../geometry.js";
13
8
  import { gistOf, read, resolve } from "../primitives.js";
14
9
  import { corpusN, hubBound } from "../traverse.js";
15
10
  import { project, reverseContext } from "../match.js";
@@ -18,193 +13,154 @@ import { unexplainedLabel } from "../rationale.js";
18
13
  import { rItem, rNode } from "../trace.js";
19
14
  /** Recall the answer by resonating the whole query against the content index. */
20
15
  export async function recallByResonance(ctx, query, pre) {
21
- const t = ctx.trace?.enter("recallByResonance", [
22
- rItem(query, "query"),
23
- ]);
24
- const whole_ = [[0, query.length]];
25
- const nothing = [];
26
- const ground = (bytes, note, accounted, moves, echoed = false) => {
27
- t?.done(
28
- bytes === null
29
- ? []
30
- : [rItem(bytes, "answer", resolve(ctx, bytes) ?? undefined)],
31
- note,
32
- );
33
- return bytes === null ? null : {
34
- bytes,
35
- echoed,
36
- accounted,
37
- moves,
38
- unexplained: unexplainedLabel(query, accounted),
16
+ const t = ctx.trace?.enter("recallByResonance", [
17
+ rItem(query, "query"),
18
+ ]);
19
+ const whole_ = [[0, query.length]];
20
+ const nothing = [];
21
+ const ground = (bytes, note, accounted, moves, echoed = false) => {
22
+ t?.done(bytes === null
23
+ ? []
24
+ : [rItem(bytes, "answer", resolve(ctx, bytes) ?? undefined)], note);
25
+ return bytes === null ? null : {
26
+ bytes,
27
+ echoed,
28
+ accounted,
29
+ moves,
30
+ unexplained: unexplainedLabel(query, accounted),
31
+ };
39
32
  };
40
- };
41
- const k = pre.k;
42
- const queryGist = pre.guide;
43
- // 0. Exact self-match — content-addressed, deterministic.
44
- const qId = pre.queryResolved;
45
- if (qId !== null) {
46
- const rev = ctx.store.prevFirst(qId, hubBound(ctx));
47
- const g = reverseContext(ctx, qId, queryGist, rev);
48
- if (g !== null) {
49
- return ground(
50
- g,
51
- rev.length === 1
52
- ? "exact self-match — reverse recall to the sole predecessor"
53
- : "exact self-match — reverse recall to the best-resonating predecessor",
54
- nothing,
55
- STEP,
56
- );
57
- }
58
- }
59
- const whole = await ctx.store.resonate(queryGist, k);
60
- if (whole.length === 0) {
61
- return ground(null, "empty store — nothing to resonate with", [], 0);
62
- }
63
- const top = whole[0];
64
- ctx.trace?.step(
65
- "resonate",
66
- [rItem(query, "query-gist")],
67
- whole.map((h) => rNode(ctx, h.id, "hit", h.score)),
68
- `resonate the whole-query gist → ${whole.length} nearest learnt form(s)`,
69
- );
70
- // 1. Clean resonance — the scale-aware identity claim. The ANGLE
71
- // (top.score) carries the shared fraction; the query's MAGNITUDE (√len,
72
- // the linear fold's own norm) converts the tolerated foreign fraction
73
- // into bytes — at most one river window (see {@link identityBar}). A
74
- // fixed cosine bar let long queries claim "near-identical" while whole
75
- // windows — an answer word — differed.
76
- if (top.score >= identityBar(ctx.store.D, ctx.space.maxGroup, query.length)) {
77
- for (const h of whole) {
78
- if (h.id === qId || h.score >= 1.0) {
79
- const rev = ctx.store.prevFirst(h.id, hubBound(ctx));
80
- const g = reverseContext(ctx, h.id, queryGist, rev);
33
+ const k = pre.k;
34
+ const queryGist = pre.guide;
35
+ // 0. Exact self-match — content-addressed, deterministic.
36
+ const qId = pre.queryResolved;
37
+ if (qId !== null) {
38
+ const rev = ctx.store.prevFirst(qId, hubBound(ctx));
39
+ const g = reverseContext(ctx, qId, queryGist, rev);
81
40
  if (g !== null) {
82
- return ground(
83
- g,
84
- rev.length === 1
85
- ? "perfect self-match — reverse recall to the sole predecessor"
86
- : "perfect self-match — reverse recall to the best-resonating predecessor",
87
- nothing,
88
- STEP,
89
- );
41
+ return ground(g, rev.length === 1
42
+ ? "exact self-match — reverse recall to the sole predecessor"
43
+ : "exact self-match — reverse recall to the best-resonating predecessor", nothing, STEP);
90
44
  }
91
- const own = read(ctx, h.id);
92
- if (own.length > 0) {
93
- return ground(
94
- own,
95
- "perfect self-match — the query IS this node",
96
- nothing,
97
- STEP,
98
- );
45
+ }
46
+ const whole = await ctx.store.resonate(queryGist, k);
47
+ if (whole.length === 0) {
48
+ return ground(null, "empty store — nothing to resonate with", [], 0);
49
+ }
50
+ const top = whole[0];
51
+ ctx.trace?.step("resonate", [rItem(query, "query-gist")], whole.map((h) => rNode(ctx, h.id, "hit", h.score)), `resonate the whole-query gist → ${whole.length} nearest learnt form(s)`);
52
+ // 1. Clean resonance — the scale-aware identity claim. The ANGLE
53
+ // (top.score) carries the shared fraction; the query's MAGNITUDE (√len,
54
+ // the linear fold's own norm) converts the tolerated foreign fraction
55
+ // into bytes — at most one river window (see {@link identityBar}). A
56
+ // fixed cosine bar let long queries claim "near-identical" while whole
57
+ // windows — an answer word — differed.
58
+ if (top.score >= identityBar(ctx.store.D, ctx.space.maxGroup, query.length)) {
59
+ for (const h of whole) {
60
+ if (h.id === qId || h.score >= 1.0) {
61
+ const rev = ctx.store.prevFirst(h.id, hubBound(ctx));
62
+ const g = reverseContext(ctx, h.id, queryGist, rev);
63
+ if (g !== null) {
64
+ return ground(g, rev.length === 1
65
+ ? "perfect self-match — reverse recall to the sole predecessor"
66
+ : "perfect self-match — reverse recall to the best-resonating predecessor", nothing, STEP);
67
+ }
68
+ const own = read(ctx, h.id);
69
+ if (own.length > 0) {
70
+ return ground(own, "perfect self-match — the query IS this node", nothing, STEP);
71
+ }
72
+ }
73
+ const g = await project(ctx, h.id, queryGist);
74
+ if (g) {
75
+ return ground(g, "clean whole-query resonance — ground the nearest hit", whole_, STEP);
76
+ }
99
77
  }
100
- }
101
- const g = await project(ctx, h.id, queryGist);
102
- if (g) {
103
- return ground(
104
- g,
105
- "clean whole-query resonance — ground the nearest hit",
106
- whole_,
107
- STEP,
108
- );
109
- }
110
78
  }
111
- }
112
- // 2. Scaffolding-dominated.
113
- if (top.score >= significanceBar(ctx.store.D)) {
114
- const N = corpusN(ctx);
115
- const minVote = consensusFloor(N);
116
- // The committed points of attention ARE the shared climb's roots (same
117
- // query, same k, same DF mode) read them from Precomputed instead of
118
- // re-climbing, so even a traced response pays for the climb once.
119
- const forest = (await pre.attention()).roots;
120
- if (forest.length > 0 && forest[0].vote >= minVote) {
121
- const g = await project(ctx, forest[0].anchor, queryGist);
122
- if (g) {
123
- return ground(
124
- g,
125
- "scaffolding-dominated query — ground the consensus-climb anchor",
126
- [[forest[0].start, forest[0].end]],
127
- CONCEPT,
128
- );
129
- }
79
+ // 2. Scaffolding-dominated.
80
+ if (top.score >= significanceBar(ctx.store.D)) {
81
+ const N = corpusN(ctx);
82
+ const minVote = consensusFloor(N);
83
+ // The committed points of attention ARE the shared climb's roots (same
84
+ // query, same k, same DF mode) read them from Precomputed instead of
85
+ // re-climbing, so even a traced response pays for the climb once.
86
+ const forest = (await pre.attention()).roots;
87
+ if (forest.length > 0 && forest[0].vote >= minVote) {
88
+ const g = await project(ctx, forest[0].anchor, queryGist);
89
+ if (g) {
90
+ return ground(g, "scaffolding-dominated query — ground the consensus-climb anchor", [[forest[0].start, forest[0].end]], CONCEPT);
91
+ }
92
+ }
130
93
  }
131
- }
132
- // 3. Last resort gated on the FRACTION OF THE QUERY the grounding
133
- // explains, not the raw cosine. Root gists are unit vectors, but their
134
- // magnitudes are recoverable from the byte lengths (‖·‖ = √len under the
135
- // linear fold): cos = shared/√(lenQ·lenG), so shared/lenQ = cos·√(lenG/lenQ).
136
- // The raw cosine punished honest containment a query fully inside a
137
- // longer grounded answer scored √(lenQ/lenG) and was refused and let a
138
- // long answer sharing only scaffolding pass; the query-relative fraction
139
- // measures exactly what the reach bar means: how much of THE QUERY the
140
- // store accounts for.
141
- const fracOfQuery = (cos, otherLen) =>
142
- Math.min(1, cos * Math.sqrt(otherLen / Math.max(1, query.length)));
143
- for (const h of whole) {
144
- const g = await project(ctx, h.id, queryGist);
145
- if (g) {
146
- if (
147
- fracOfQuery(cosine(queryGist, gistOf(ctx, g)), g.length) >=
148
- reachThreshold(ctx.space.maxGroup)
149
- ) {
150
- return ground(
151
- g,
152
- "last resort: the nearest grounded whole-query hit",
153
- [],
154
- STEP,
155
- );
156
- }
94
+ // 3. Last resort — gated on the FRACTION OF THE QUERY the grounding
95
+ // explains, not the raw cosine. Root gists are unit vectors, but their
96
+ // magnitudes are recoverable from the byte lengths (‖·‖ = √len under the
97
+ // linear fold): cos = shared/√(lenQ·lenG), so shared/lenQ = cos·√(lenG/lenQ).
98
+ // The raw cosine punished honest containment a query fully inside a
99
+ // longer grounded answer scored √(lenQ/lenG) and was refused and let a
100
+ // long answer sharing only scaffolding pass; the query-relative fraction
101
+ // measures exactly what the reach bar means: how much of THE QUERY the
102
+ // store accounts for.
103
+ // Chance similarity survives the length conversion AMPLIFIED: the same
104
+ // √(lenG/lenQ) factor that converts an honest shared fraction into a
105
+ // query-relative one multiplies the estimator/chance floor too, so a long
106
+ // stored form (√(lenG/lenQ) 10 at 100×) lifted a noise-level cosine past
107
+ // the reach bar and grounded pure gibberish (observed). Only the
108
+ // ABOVE-CHANCE part of the similarity is evidence of shared content —
109
+ // subtract the significance bar (3/√D, §8.3) before converting. Derived
110
+ // from the existing bars; never tuned.
111
+ const sig = significanceBar(ctx.store.D);
112
+ const fracOfQuery = (cos, otherLen) => Math.min(1, Math.max(0, cos - sig) *
113
+ Math.sqrt(otherLen / Math.max(1, query.length)));
114
+ for (const h of whole) {
115
+ const g = await project(ctx, h.id, queryGist);
116
+ if (g) {
117
+ if (fracOfQuery(cosine(queryGist, gistOf(ctx, g)), g.length) >=
118
+ reachThreshold(ctx.space.maxGroup)) {
119
+ return ground(g, "last resort: the nearest grounded whole-query hit", [], STEP);
120
+ }
121
+ }
157
122
  }
158
- }
159
- // The refusal/echo decision, in the same query-relative units the top
160
- // hit's magnitude read from the store (contentLen: √bytes IS the linear
161
- // fold's gist norm), never from re-reading its bytes.
162
- // The magnitude read SATURATES at the decision point: frac reaches the
163
- // reach bar exactly when lenH = lenQ·(reach/score)², so the walk never
164
- // needs to see past that a huge conversation root costs a capped read,
165
- // and a clamped return decides "pass" identically (frac reach).
166
- const reach = reachThreshold(ctx.space.maxGroup);
167
- const lenCap =
168
- Math.ceil(query.length * (reach / Math.max(top.score, 1e-6)) ** 2) + 1;
169
- if (fracOfQuery(top.score, ctx.store.contentLen(top.id, lenCap)) < reach) {
170
- return ground(
171
- null,
172
- "below reach threshold nothing in the store relates to this query",
173
- [],
174
- 0,
175
- );
176
- }
177
- // Honest echo.
178
- return ground(
179
- read(ctx, top.id),
180
- "last resort: the nearest resonant form's own bytes (echo, not grounded)",
181
- [],
182
- 0,
183
- true,
184
- );
123
+ // The refusal/echo decision. The echo returns a stored form's bytes AS
124
+ // the answer a near-identity claim about the query — and identity-grade
125
+ // decisions are never made on an estimated score ("approximate scores may
126
+ // rank and propose; they may never decide", §6.2): the RaBitQ estimate
127
+ // overshooting the reach bar echoed a WRONG-entity neighbour ("capital of
128
+ // Zamunda?" echoed the Armenia fact, observed). The bytes are read
129
+ // anyway to be echoed, so the decision uses their EXACT fold: one river
130
+ // fold of the top hit, measured in the same query-relative,
131
+ // chance-corrected units as the tier above.
132
+ const reach = reachThreshold(ctx.space.maxGroup);
133
+ const topBytes = read(ctx, top.id);
134
+ const exact = topBytes.length > 0
135
+ ? cosine(queryGist, gistOf(ctx, topBytes))
136
+ : 0;
137
+ if (fracOfQuery(exact, topBytes.length) < reach) {
138
+ return ground(null, "below reach threshold — nothing in the store relates to this query", [], 0);
139
+ }
140
+ // Honest echo.
141
+ return ground(topBytes, "last resort: the nearest resonant form's own bytes (echo, not grounded)", [], 0, true);
185
142
  }
186
143
  // ── Pipeline mechanism ──────────────────────────────────────────────────────
187
144
  export const recallMechanism = {
188
- name: "recall",
189
- provenance: "recall",
190
- // Recall's floor is free to state (one STEP-grade projection) and its run
191
- // gates its own tiers — no expensive investment happens inside floor, so
192
- // there is nothing to guard with worthRunning here: the pipeline's own
193
- // check prunes run() against the incumbent.
194
- async floor(_ctx, _query, _pre, _worthRunning) {
195
- return STEP;
196
- },
197
- async run(ctx, query, pre) {
198
- const r = await recallByResonance(ctx, query, pre);
199
- if (!r) {
200
- return [];
201
- }
202
- return [{
203
- bytes: r.bytes,
204
- accounted: r.accounted,
205
- moves: r.moves,
206
- unexplained: r.unexplained,
207
- provenance: r.echoed ? "recall-echo" : "recall",
208
- }];
209
- },
145
+ name: "recall",
146
+ provenance: "recall",
147
+ // Recall's floor is free to state (one STEP-grade projection) and its run
148
+ // gates its own tiers — no expensive investment happens inside floor, so
149
+ // there is nothing to guard with worthRunning here: the pipeline's own
150
+ // check prunes run() against the incumbent.
151
+ async floor(_ctx, _query, _pre, _worthRunning) {
152
+ return STEP;
153
+ },
154
+ async run(ctx, query, pre) {
155
+ const r = await recallByResonance(ctx, query, pre);
156
+ if (!r)
157
+ return [];
158
+ return [{
159
+ bytes: r.bytes,
160
+ accounted: r.accounted,
161
+ moves: r.moves,
162
+ unexplained: r.unexplained,
163
+ provenance: r.echoed ? "recall-echo" : "recall",
164
+ }];
165
+ },
210
166
  };