@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
@@ -17,225 +17,163 @@ import { decodeText, unexplainedLabel } from "../rationale.js";
17
17
  import { rItem, rNode, traceDerivation } from "../trace.js";
18
18
  // ── Concept / connector pre-resolution ──────────────────────────────────────
19
19
  export async function resolveConcepts(ctx, sites) {
20
- const target = new Map();
21
- const visited = new Set();
22
- for (const { payload: n } of sites) {
23
- if (visited.has(n)) {
24
- continue;
20
+ const target = new Map();
21
+ const visited = new Set();
22
+ for (const { payload: n } of sites) {
23
+ if (visited.has(n))
24
+ continue;
25
+ visited.add(n);
26
+ if (ctx.store.hasNext(n))
27
+ continue;
28
+ const hop = await conceptHop(ctx, n);
29
+ if (hop !== null)
30
+ target.set(n, hop);
25
31
  }
26
- visited.add(n);
27
- if (ctx.store.hasNext(n)) {
28
- continue;
32
+ if (target.size > 0) {
33
+ ctx.trace?.step("resolveConcepts", [...target.keys()].map((n) => rNode(ctx, n, "edgeless-form")), [...target.values()].map((h) => rNode(ctx, h, "concept-sibling")), "borrow a synonym's continuation edge for each edge-less form (a concept/halo hop)");
29
34
  }
30
- const hop = await conceptHop(ctx, n);
31
- if (hop !== null) {
32
- target.set(n, hop);
33
- }
34
- }
35
- if (target.size > 0) {
36
- ctx.trace?.step(
37
- "resolveConcepts",
38
- [...target.keys()].map((n) => rNode(ctx, n, "edgeless-form")),
39
- [...target.values()].map((h) => rNode(ctx, h, "concept-sibling")),
40
- "borrow a synonym's continuation edge for each edge-less form (a concept/halo hop)",
41
- );
42
- }
43
- return target;
35
+ return target;
44
36
  }
45
37
  export async function resolveConnectors(ctx, sites) {
46
- const links = new Map();
47
- const ordered = [...sites].sort((a, b) => a.start - b.start);
48
- const answerOf = (n) => guidedFirst(ctx, n) ?? n;
49
- const bridgePair = async (l, r) => {
50
- if (l === r || links.has(l + "," + r)) {
51
- return;
52
- }
53
- const link = await bridge(ctx, read(ctx, l), read(ctx, r));
54
- if (link !== null) {
55
- links.set(l + "," + r, link);
38
+ const links = new Map();
39
+ const ordered = [...sites].sort((a, b) => a.start - b.start);
40
+ const answerOf = (n) => guidedFirst(ctx, n) ?? n;
41
+ const bridgePair = async (l, r) => {
42
+ if (l === r || links.has(l + "," + r))
43
+ return;
44
+ const link = await bridge(ctx, read(ctx, l), read(ctx, r));
45
+ if (link !== null)
46
+ links.set(l + "," + r, link);
47
+ };
48
+ for (let i = 0; i + 1 < ordered.length; i++) {
49
+ if (ordered[i].end !== ordered[i + 1].start)
50
+ continue;
51
+ const lefts = [ordered[i].payload, answerOf(ordered[i].payload)];
52
+ const rights = [ordered[i + 1].payload, answerOf(ordered[i + 1].payload)];
53
+ for (const l of new Set(lefts)) {
54
+ for (const r of new Set(rights)) {
55
+ await bridgePair(l, r);
56
+ await bridgePair(r, l);
57
+ }
58
+ }
56
59
  }
57
- };
58
- for (let i = 0; i + 1 < ordered.length; i++) {
59
- if (ordered[i].end !== ordered[i + 1].start) {
60
- continue;
60
+ const orderedNodes = [];
61
+ const seenN = new Set();
62
+ for (const s of ordered) {
63
+ const node = guidedFirst(ctx, s.payload) ?? s.payload;
64
+ if (seenN.has(node))
65
+ continue;
66
+ seenN.add(node);
67
+ orderedNodes.push({ node, bytes: read(ctx, node) });
61
68
  }
62
- const lefts = [ordered[i].payload, answerOf(ordered[i].payload)];
63
- const rights = [ordered[i + 1].payload, answerOf(ordered[i + 1].payload)];
64
- for (const l of new Set(lefts)) {
65
- for (const r of new Set(rights)) {
66
- await bridgePair(l, r);
67
- await bridgePair(r, l);
68
- }
69
+ if (orderedNodes.length >= 3) {
70
+ const first = orderedNodes[0];
71
+ const W = ctx.space.maxGroup;
72
+ let middleBytes = 0; // Σ bytes of the answers BETWEEN first and m-th
73
+ for (let m = 1; m < orderedNodes.length; m++) {
74
+ const key = first.node + "," + orderedNodes[m].node;
75
+ if (links.has(key)) {
76
+ middleBytes += orderedNodes[m].bytes.length;
77
+ continue;
78
+ }
79
+ // The N-ary interior legitimately holds every intermediate answer
80
+ // plus one W-quantum of glue per joint — pass that allowance so the
81
+ // bridge's phrase-scale cap admits the whole learnt run.
82
+ const allowance = middleBytes + (m + 1) * W;
83
+ const interior = await bridge(ctx, first.bytes, orderedNodes[m].bytes, allowance);
84
+ if (interior !== null)
85
+ links.set(key, interior);
86
+ middleBytes += orderedNodes[m].bytes.length;
87
+ }
69
88
  }
70
- }
71
- const orderedNodes = [];
72
- const seenN = new Set();
73
- for (const s of ordered) {
74
- const node = guidedFirst(ctx, s.payload) ?? s.payload;
75
- if (seenN.has(node)) {
76
- continue;
89
+ if (links.size > 0) {
90
+ ctx.trace?.step("resolveConnectors", ordered.map((s) => rItem(read(ctx, s.payload), "answer", s.payload)), [...links.entries()].map(([pair, bytes]) => ({
91
+ text: `${pair}: "${decodeText(bytes)}"`,
92
+ role: "connector",
93
+ })), "the bytes the graph splices between adjacent answers (asked of the gist space)");
77
94
  }
78
- seenN.add(node);
79
- orderedNodes.push({ node, bytes: read(ctx, node) });
80
- }
81
- if (orderedNodes.length >= 3) {
82
- const first = orderedNodes[0];
83
- const W = ctx.space.maxGroup;
84
- let middleBytes = 0; // Σ bytes of the answers BETWEEN first and m-th
85
- for (let m = 1; m < orderedNodes.length; m++) {
86
- const key = first.node + "," + orderedNodes[m].node;
87
- if (links.has(key)) {
88
- middleBytes += orderedNodes[m].bytes.length;
89
- continue;
90
- }
91
- // The N-ary interior legitimately holds every intermediate answer
92
- // plus one W-quantum of glue per joint — pass that allowance so the
93
- // bridge's phrase-scale cap admits the whole learnt run.
94
- const allowance = middleBytes + (m + 1) * W;
95
- const interior = await bridge(
96
- ctx,
97
- first.bytes,
98
- orderedNodes[m].bytes,
99
- allowance,
100
- );
101
- if (interior !== null) {
102
- links.set(key, interior);
103
- }
104
- middleBytes += orderedNodes[m].bytes.length;
105
- }
106
- }
107
- if (links.size > 0) {
108
- ctx.trace?.step(
109
- "resolveConnectors",
110
- ordered.map((s) => rItem(read(ctx, s.payload), "answer", s.payload)),
111
- [...links.entries()].map(([pair, bytes]) => ({
112
- text: `${pair}: "${decodeText(bytes)}"`,
113
- role: "connector",
114
- })),
115
- "the bytes the graph splices between adjacent answers (asked of the gist space)",
116
- );
117
- }
118
- return links;
95
+ return links;
119
96
  }
120
97
  // ── Pipeline mechanism ──────────────────────────────────────────────────────
121
98
  export const coverMechanism = {
122
- name: "cover",
123
- provenance: "cover",
124
- async floor(_ctx, _query, _pre, _worthRunning) {
125
- return 0;
126
- },
127
- async run(ctx, query, pre) {
128
- const { rec, computed } = pre;
129
- // Masking: computed spans are authoritative. Remove recognised sites
130
- // that overlap any computed span before building the cover search.
131
- const sites = computed.length === 0
132
- ? rec.sites
133
- : rec.sites.filter((s) =>
134
- !computed.some((u) => s.start < u.j && u.i < s.end)
135
- );
136
- if (computed.length > 0 && sites.length < rec.sites.length) {
137
- ctx.trace?.step(
138
- "maskByComputation",
139
- rec.sites.map((s) =>
140
- rItem(query.subarray(s.start, s.end), "form", s.payload, [
141
- s.start,
142
- s.end,
143
- ])
144
- ),
145
- sites.map((s) =>
146
- rItem(query.subarray(s.start, s.end), "form", s.payload, [
147
- s.start,
148
- s.end,
149
- ])
150
- ),
151
- "a computation always wins: recognised forms overlapping a computed span are dropped",
152
- );
153
- }
154
- if (sites.length === 0 && computed.length === 0) {
155
- return [];
156
- }
157
- const connectors = await resolveConnectors(ctx, sites);
158
- let splits = rec.splits;
159
- if (computed.length > 0) {
160
- splits = new Set(rec.splits);
161
- for (const u of computed) {
162
- splits.add(u.i);
163
- splits.add(u.j);
164
- }
165
- }
166
- const concepts = await resolveConcepts(ctx, sites);
167
- const coverDeps = [
168
- ctx.trace?.lastIndex("recognise"),
169
- ctx.trace?.lastIndex("computeExtensions"),
170
- ctx.trace?.lastIndex("resolveConcepts"),
171
- ctx.trace?.lastIndex("resolveConnectors"),
172
- ].filter((x) => x !== undefined);
173
- // Convert ComputedSpan[] to ComputedResult[] for the graph search.
174
- const computedResults = computed.map((u) => ({
175
- i: u.i,
176
- j: u.j,
177
- bytes: u.bytes,
178
- node: resolve(ctx, u.bytes) ?? undefined,
179
- }));
180
- const tCover = ctx.trace?.enter("cover", [
181
- ...sites.map((s) =>
182
- rItem(query.subarray(s.start, s.end), "form", s.payload, [
183
- s.start,
184
- s.end,
185
- ])
186
- ),
187
- ...computedResults.map((u) => rItem(u.bytes, "computed")),
188
- ], coverDeps.length ? coverDeps : undefined);
189
- const solved = ctx.search.cover(
190
- query.length,
191
- sites,
192
- concepts,
193
- rec.leaves,
194
- splits,
195
- undefined,
196
- connectors,
197
- computedResults,
198
- ctx.trace ? (steps) => traceDerivation(ctx, steps) : undefined,
199
- );
200
- const segs = solved && solved.segs;
201
- tCover?.done(
202
- segs === null
203
- ? []
204
- : segs.map((s) =>
205
- rItem(s.bytes, s.rec ? "chosen" : "bridge", s.node, [s.i, s.j])
206
- ),
207
- segs === null
208
- ? "no cover of the query composed"
209
- : "lightest derivation: the chosen spans, left to right",
210
- );
211
- if (segs === null) {
212
- return [];
213
- }
214
- const composed = liftAnswer(segs, query.length);
215
- if (composed === null) {
216
- return [];
217
- }
218
- ctx.trace?.step(
219
- "liftAnswer",
220
- segs.map((s) =>
221
- rItem(s.bytes, s.rec ? "chosen" : "scaffolding", s.node, [s.i, s.j])
222
- ),
223
- [rItem(composed, "answer", resolve(ctx, composed) ?? undefined)],
224
- "lift the recognised region out of the asker's framing",
225
- tCover ? [tCover.index] : undefined,
226
- );
227
- // accounted = RECOGNISED cover spans only — PASS-carried bytes
228
- // are priced in cost already; the diagnostic label reflects the
229
- // same distinction.
230
- const accounted = segs
231
- .filter((s) => s.rec)
232
- .map((s) => [s.i, s.j]);
233
- return [{
234
- bytes: composed,
235
- accounted,
236
- moves: 0,
237
- weight: solved.cost, // A*LD derivation's g-value IS the weight
238
- unexplained: unexplainedLabel(query, accounted),
239
- }];
240
- },
99
+ name: "cover",
100
+ provenance: "cover",
101
+ async floor(_ctx, _query, _pre, _worthRunning) {
102
+ return 0;
103
+ },
104
+ async run(ctx, query, pre) {
105
+ const { rec, computed } = pre;
106
+ // Masking: computed spans are authoritative. Remove recognised sites
107
+ // that overlap any computed span before building the cover search.
108
+ const sites = computed.length === 0
109
+ ? rec.sites
110
+ : rec.sites.filter((s) => !computed.some((u) => s.start < u.j && u.i < s.end));
111
+ if (computed.length > 0 && sites.length < rec.sites.length) {
112
+ ctx.trace?.step("maskByComputation", rec.sites.map((s) => rItem(query.subarray(s.start, s.end), "form", s.payload, [
113
+ s.start,
114
+ s.end,
115
+ ])), sites.map((s) => rItem(query.subarray(s.start, s.end), "form", s.payload, [
116
+ s.start,
117
+ s.end,
118
+ ])), "a computation always wins: recognised forms overlapping a computed span are dropped");
119
+ }
120
+ if (sites.length === 0 && computed.length === 0)
121
+ return [];
122
+ const connectors = await resolveConnectors(ctx, sites);
123
+ let splits = rec.splits;
124
+ if (computed.length > 0) {
125
+ splits = new Set(rec.splits);
126
+ for (const u of computed) {
127
+ splits.add(u.i);
128
+ splits.add(u.j);
129
+ }
130
+ }
131
+ const concepts = await resolveConcepts(ctx, sites);
132
+ const coverDeps = [
133
+ ctx.trace?.lastIndex("recognise"),
134
+ ctx.trace?.lastIndex("computeExtensions"),
135
+ ctx.trace?.lastIndex("resolveConcepts"),
136
+ ctx.trace?.lastIndex("resolveConnectors"),
137
+ ].filter((x) => x !== undefined);
138
+ // Convert ComputedSpan[] to ComputedResult[] for the graph search.
139
+ const computedResults = computed.map((u) => ({
140
+ i: u.i,
141
+ j: u.j,
142
+ bytes: u.bytes,
143
+ node: resolve(ctx, u.bytes) ?? undefined,
144
+ }));
145
+ const tCover = ctx.trace?.enter("cover", [
146
+ ...sites.map((s) => rItem(query.subarray(s.start, s.end), "form", s.payload, [
147
+ s.start,
148
+ s.end,
149
+ ])),
150
+ ...computedResults.map((u) => rItem(u.bytes, "computed")),
151
+ ], coverDeps.length ? coverDeps : undefined);
152
+ const solved = ctx.search.cover(query.length, sites, concepts, rec.leaves, splits, undefined, connectors, computedResults, ctx.trace ? (steps) => traceDerivation(ctx, steps) : undefined);
153
+ const segs = solved && solved.segs;
154
+ tCover?.done(segs === null
155
+ ? []
156
+ : segs.map((s) => rItem(s.bytes, s.rec ? "chosen" : "bridge", s.node, [s.i, s.j])), segs === null
157
+ ? "no cover of the query composed"
158
+ : "lightest derivation: the chosen spans, left to right");
159
+ if (segs === null)
160
+ return [];
161
+ const composed = liftAnswer(segs, query.length);
162
+ if (composed === null)
163
+ return [];
164
+ ctx.trace?.step("liftAnswer", segs.map((s) => rItem(s.bytes, s.rec ? "chosen" : "scaffolding", s.node, [s.i, s.j])), [rItem(composed, "answer", resolve(ctx, composed) ?? undefined)], "lift the recognised region out of the asker's framing", tCover ? [tCover.index] : undefined);
165
+ // accounted = RECOGNISED cover spans only — PASS-carried bytes
166
+ // are priced in cost already; the diagnostic label reflects the
167
+ // same distinction.
168
+ const accounted = segs
169
+ .filter((s) => s.rec)
170
+ .map((s) => [s.i, s.j]);
171
+ return [{
172
+ bytes: composed,
173
+ accounted,
174
+ moves: 0,
175
+ weight: solved.cost, // A*LD derivation's g-value IS the weight
176
+ unexplained: unexplainedLabel(query, accounted),
177
+ }];
178
+ },
241
179
  };
@@ -17,47 +17,29 @@ import type { PipelineMechanism, Precomputed } from "../pipeline-mechanism.js";
17
17
  * explained for one mechanism and not the other, and the asymmetry, not
18
18
  * the answers' merits, decided the grounding.) Null when no skill
19
19
  * applies. */
20
- export declare function extractBySkill(
21
- ctx: MindContext,
22
- query: Uint8Array,
23
- pre: Precomputed,
24
- ): Promise<
25
- {
20
+ export declare function extractBySkill(ctx: MindContext, query: Uint8Array, pre: Precomputed): Promise<{
26
21
  bytes: Uint8Array;
27
22
  accounted: Array<[number, number]>;
28
23
  unexplained: string;
29
- } | null
30
- >;
24
+ } | null>;
31
25
  /** Decompose an answer into substrings of its surrounding context, in order —
32
26
  * the STRONG span-shape reading (see the section note above). Returns null
33
27
  * when no greedy longest-run decomposition exists. Adjacent runs that
34
28
  * connect contiguously are merged. */
35
- export declare function answerRunsInContext(
36
- _ctx: MindContext,
37
- context: Uint8Array,
38
- answer: Uint8Array,
39
- ):
40
- | Array<{
29
+ export declare function answerRunsInContext(_ctx: MindContext, context: Uint8Array, answer: Uint8Array): Array<{
41
30
  start: number;
42
31
  end: number;
43
32
  ansLen: number;
44
- }>
45
- | null;
33
+ }> | null;
46
34
  /** Check whether an anchor is a span-shaped skill exemplar: it represents a
47
35
  * fact whose context and answer together form a span-in-context pattern.
48
36
  * If the anchor has a nextOf continuation, that is the answer and the anchor
49
37
  * itself is the context. Otherwise the anchor's prevOf parents provide
50
38
  * candidate contexts, and the longest one whose span is span-shaped wins. */
51
- export declare function skillExemplar(
52
- ctx: MindContext,
53
- anchor: number,
54
- guide?: Vec | null,
55
- ): Promise<
56
- {
39
+ export declare function skillExemplar(ctx: MindContext, anchor: number, guide?: Vec | null): Promise<{
57
40
  contextBytes: Uint8Array;
58
41
  answerBytes: Uint8Array;
59
- } | null
60
- >;
42
+ } | null>;
61
43
  /** Whether the answer is a SPARSE subsequence of the context (bytes in
62
44
  * order, arbitrary gaps) — the OPEN span-shape reading (see the section
63
45
  * note above). This is what lets extraction validate a MULTI-PIECE
@@ -72,11 +54,7 @@ export declare function skillExemplar(
72
54
  * with the same truth value. The old pre-check re-perceived the context
73
55
  * (a full river fold) per CANDIDATE in skillExemplar's √N-capped loop —
74
56
  * pure cost, no discrimination. */
75
- export declare function isSpanShaped(
76
- _ctx: MindContext,
77
- context: Uint8Array,
78
- answer: Uint8Array,
79
- ): boolean;
57
+ export declare function isSpanShaped(_ctx: MindContext, context: Uint8Array, answer: Uint8Array): boolean;
80
58
  /** STRICT containment: the answer's resolved node appears in the context's
81
59
  * folded tree, or the answer occurs as one CONTIGUOUS byte run of the
82
60
  * context. This is real evidence the answer was drawn from the context.
@@ -85,9 +63,5 @@ export declare function isSpanShaped(
85
63
  * queries ("cold" is a gap-tolerant subsequence of most sentences holding
86
64
  * c…o…l…d in order), and gating fusion on it silently starved multi-topic
87
65
  * queries of their further points of attention. */
88
- export declare function containsSpan(
89
- ctx: MindContext,
90
- context: Uint8Array,
91
- answer: Uint8Array,
92
- ): boolean;
66
+ export declare function containsSpan(ctx: MindContext, context: Uint8Array, answer: Uint8Array): boolean;
93
67
  export declare const extractionMechanism: PipelineMechanism;