@hviana/sema 0.1.5 → 0.1.6

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 (160) 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 +1687 -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 +17 -42
  51. package/dist/src/geometry.js +235 -266
  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 +749 -871
  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 +126 -185
  82. package/dist/src/mind/mind.d.ts +129 -154
  83. package/dist/src/mind/mind.js +258 -288
  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 +8 -32
  89. package/dist/src/mind/primitives.js +99 -117
  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 +183 -208
  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 +16 -58
  101. package/dist/src/mind/traverse.js +304 -357
  102. package/dist/src/mind/types.d.ts +120 -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 +169 -166
  117. package/dist/src/store-sqlite.js +762 -662
  118. package/dist/src/store.d.ts +586 -630
  119. package/dist/src/store.js +1423 -1581
  120. package/dist/src/vec.d.ts +5 -9
  121. package/dist/src/vec.js +61 -73
  122. package/example/train_base.ts +13 -10
  123. package/package.json +1 -1
  124. package/src/alu/README.md +1 -1
  125. package/src/alu/src/index.ts +1 -1
  126. package/src/config.ts +19 -27
  127. package/src/index.ts +6 -11
  128. package/src/rabitq-ivf/README.md +56 -0
  129. package/src/rabitq-ivf/src/database.ts +276 -0
  130. package/src/{rabitq-hnsw → rabitq-ivf}/src/index.ts +2 -5
  131. package/src/rabitq-ivf/src/ivf.ts +1330 -0
  132. package/src/{rabitq-hnsw → rabitq-ivf}/src/prng.ts +1 -1
  133. package/src/store-sqlite.ts +196 -9
  134. package/src/store.ts +8 -32
  135. package/test/08-storage.test.mjs +3 -3
  136. package/test/14-scaling.test.mjs +2 -2
  137. package/test/35-ivf.test.mjs +263 -0
  138. package/test/36-bloom.test.mjs +123 -0
  139. package/dist/src/rabitq-hnsw/src/database.d.ts +0 -202
  140. package/dist/src/rabitq-hnsw/src/database.js +0 -405
  141. package/dist/src/rabitq-hnsw/src/heap.d.ts +0 -22
  142. package/dist/src/rabitq-hnsw/src/heap.js +0 -94
  143. package/dist/src/rabitq-hnsw/src/hnsw.d.ts +0 -125
  144. package/dist/src/rabitq-hnsw/src/hnsw.js +0 -500
  145. package/dist/src/rabitq-hnsw/src/index.d.ts +0 -15
  146. package/dist/src/rabitq-hnsw/src/prng.d.ts +0 -19
  147. package/dist/src/rabitq-hnsw/src/prng.js +0 -38
  148. package/dist/src/rabitq-hnsw/src/rabitq.d.ts +0 -95
  149. package/dist/src/rabitq-hnsw/src/rabitq.js +0 -299
  150. package/dist/src/rabitq-hnsw/src/store.d.ts +0 -162
  151. package/dist/src/rabitq-hnsw/src/store.js +0 -916
  152. package/dist/src/rabitq-hnsw/test/hnsw.test.d.ts +0 -1
  153. package/dist/src/rabitq-hnsw/test/hnsw.test.js +0 -1197
  154. package/src/rabitq-hnsw/README.md +0 -303
  155. package/src/rabitq-hnsw/src/database.ts +0 -492
  156. package/src/rabitq-hnsw/src/heap.ts +0 -90
  157. package/src/rabitq-hnsw/src/hnsw.ts +0 -514
  158. package/src/rabitq-hnsw/src/store.ts +0 -994
  159. package/src/rabitq-hnsw/test/hnsw.test.ts +0 -1213
  160. /package/src/{rabitq-hnsw → rabitq-ivf}/src/rabitq.ts +0 -0
@@ -22,179 +22,157 @@ import { isChunk } from "../sema.js";
22
22
  *
23
23
  * Both O(n · maxGroup) bounded O(1) probes — never a scan of the corpus. */
24
24
  export function recognise(ctx, bytes) {
25
- // Per-response memo (see MindContext.recogniseMemo): think, articulate and
26
- // the pre-consume pass all recognise the same byte objects; each repeat is
27
- // O(n·maxGroup²) store probes. Skipped while tracing so every call still
28
- // emits its rationale step.
29
- if (ctx.recogniseMemo && !ctx.trace) {
30
- const hit = ctx.recogniseMemo.get(bytes);
31
- if (hit !== undefined) {
32
- return hit;
33
- }
34
- const fresh = recogniseImpl(ctx, bytes);
35
- ctx.recogniseMemo.set(bytes, fresh);
36
- return fresh;
37
- }
38
- return recogniseImpl(ctx, bytes);
25
+ // Per-response memo (see MindContext.recogniseMemo): think, articulate and
26
+ // the pre-consume pass all recognise the same byte objects; each repeat is
27
+ // O(n·maxGroup²) store probes. Skipped while tracing so every call still
28
+ // emits its rationale step.
29
+ if (ctx.recogniseMemo && !ctx.trace) {
30
+ const hit = ctx.recogniseMemo.get(bytes);
31
+ if (hit !== undefined)
32
+ return hit;
33
+ const fresh = recogniseImpl(ctx, bytes);
34
+ ctx.recogniseMemo.set(bytes, fresh);
35
+ return fresh;
36
+ }
37
+ return recogniseImpl(ctx, bytes);
39
38
  }
40
39
  function recogniseImpl(ctx, bytes) {
41
- const store = ctx.store;
42
- const sites = [];
43
- const leaves = [];
44
- const splits = new Set();
45
- if (bytes.length === 0) {
46
- return { sites, leaves, splits };
47
- }
48
- // Span-resolve memo for THIS call: the structural pass (sub-runs inside
49
- // leaf-parents) and the canonical pass (leaf-id chains) probe overlapping
50
- // spans, and each resolve() is a full fold of the sub-span (fresh subarray
51
- // objects the per-response perceive memo cannot see them). Keyed
52
- // numerically by (start, end); resolve is pure and the store is read-only
53
- // here, so a hit is exact.
54
- const spanIds = new Map();
55
- const resolveSpan = (start, end) => {
56
- const key = start * (bytes.length + 1) + end;
57
- let id = spanIds.get(key);
58
- if (id === undefined) {
59
- id = resolve(ctx, bytes.subarray(start, end));
60
- spanIds.set(key, id);
61
- }
62
- return id;
63
- };
64
- const emit = (start, end, id) => {
65
- if (leadsSomewhere(ctx, id)) {
66
- sites.push({ start, end, payload: id });
67
- }
68
- };
69
- // ── structural: the query's own perceived tree ──────────────────────
70
- const starts = new Set();
71
- starts.add(0);
72
- foldTree(ctx, perceive(ctx, bytes), 0, (n, start, end, node) => {
73
- if (n.kids === null) {
74
- leaves.push({ start, end, bytes: n.leaf ?? new Uint8Array(0), node });
75
- }
76
- if (node !== null) {
77
- emit(start, end, node);
78
- }
79
- if (isChunk(n)) {
80
- starts.add(start);
81
- // Try every sub-span within this leaf-parent.
82
- const leafOffsets = [];
83
- let off = start;
84
- for (const k of n.kids) {
85
- leafOffsets.push(off);
86
- off += k.leaf?.length ?? 0;
87
- }
88
- for (let i = 0; i < n.kids.length; i++) {
89
- const subIds = [];
90
- for (let j = i; j < n.kids.length; j++) {
91
- const kj = n.kids[j];
92
- if (kj.kids !== null || !kj.leaf) {
93
- break;
94
- }
95
- const lid = store.findLeaf(kj.leaf);
96
- if (lid === null) {
97
- break;
98
- }
99
- subIds.push(lid);
100
- const branch = store.findBranch(subIds);
101
- if (branch === null) {
102
- continue;
103
- }
104
- const subEnd = leafOffsets[j] + (kj.leaf?.length ?? 0);
105
- const resolved = resolveSpan(leafOffsets[i], subEnd);
106
- if (resolved !== null) {
107
- emit(leafOffsets[i], subEnd, resolved);
108
- }
40
+ const store = ctx.store;
41
+ const sites = [];
42
+ const leaves = [];
43
+ const splits = new Set();
44
+ if (bytes.length === 0)
45
+ return { sites, leaves, splits };
46
+ // Span-resolve memo for THIS call: the structural pass (sub-runs inside
47
+ // leaf-parents) and the canonical pass (leaf-id chains) probe overlapping
48
+ // spans, and each resolve() is a full fold of the sub-span (fresh subarray
49
+ // objects the per-response perceive memo cannot see them). Keyed
50
+ // numerically by (start, end); resolve is pure and the store is read-only
51
+ // here, so a hit is exact.
52
+ const spanIds = new Map();
53
+ const resolveSpan = (start, end) => {
54
+ const key = start * (bytes.length + 1) + end;
55
+ let id = spanIds.get(key);
56
+ if (id === undefined) {
57
+ id = resolve(ctx, bytes.subarray(start, end));
58
+ spanIds.set(key, id);
59
+ }
60
+ return id;
61
+ };
62
+ const emit = (start, end, id) => {
63
+ if (leadsSomewhere(ctx, id)) {
64
+ sites.push({ start, end, payload: id });
65
+ }
66
+ };
67
+ // ── structural: the query's own perceived tree ──────────────────────
68
+ const starts = new Set();
69
+ starts.add(0);
70
+ foldTree(ctx, perceive(ctx, bytes), 0, (n, start, end, node) => {
71
+ if (n.kids === null) {
72
+ leaves.push({ start, end, bytes: n.leaf ?? new Uint8Array(0), node });
73
+ }
74
+ if (node !== null)
75
+ emit(start, end, node);
76
+ if (isChunk(n)) {
77
+ starts.add(start);
78
+ // Try every sub-span within this leaf-parent.
79
+ const leafOffsets = [];
80
+ let off = start;
81
+ for (const k of n.kids) {
82
+ leafOffsets.push(off);
83
+ off += k.leaf?.length ?? 0;
84
+ }
85
+ for (let i = 0; i < n.kids.length; i++) {
86
+ const subIds = [];
87
+ for (let j = i; j < n.kids.length; j++) {
88
+ const kj = n.kids[j];
89
+ if (kj.kids !== null || !kj.leaf)
90
+ break;
91
+ const lid = store.findLeaf(kj.leaf);
92
+ if (lid === null)
93
+ break;
94
+ subIds.push(lid);
95
+ const branch = store.findBranch(subIds);
96
+ if (branch === null)
97
+ continue;
98
+ const subEnd = leafOffsets[j] + (kj.leaf?.length ?? 0);
99
+ const resolved = resolveSpan(leafOffsets[i], subEnd);
100
+ if (resolved !== null)
101
+ emit(leafOffsets[i], subEnd, resolved);
102
+ }
103
+ }
104
+ }
105
+ });
106
+ // ── canonical: longest-known-leaf re-segmentation ──────────────────
107
+ const W = ctx.space.maxGroup;
108
+ const singleLeaf = new Array(bytes.length).fill(null);
109
+ for (let p = 0; p < bytes.length; p++) {
110
+ const id = leafIdAt(ctx, bytes, p);
111
+ if (id !== null)
112
+ singleLeaf[p] = { id, end: p + 1 };
113
+ }
114
+ const leafFrom = (p) => {
115
+ if (p >= bytes.length)
116
+ return null;
117
+ return singleLeaf[p];
118
+ };
119
+ const chunkEnd = new Uint32Array(bytes.length);
120
+ const sorted = [...starts].sort((a, b) => a - b);
121
+ for (let si = 0; si < sorted.length; si++) {
122
+ const chunkStart = sorted[si];
123
+ const chunkLimit = si + 1 < sorted.length ? sorted[si + 1] : bytes.length;
124
+ for (let p = chunkStart; p < chunkLimit; p++) {
125
+ chunkEnd[p] = chunkLimit;
109
126
  }
110
- }
111
- }
112
- });
113
- // ── canonical: longest-known-leaf re-segmentation ──────────────────
114
- const W = ctx.space.maxGroup;
115
- const singleLeaf = new Array(bytes.length).fill(null);
116
- for (let p = 0; p < bytes.length; p++) {
117
- const id = leafIdAt(ctx, bytes, p);
118
- if (id !== null) {
119
- singleLeaf[p] = { id, end: p + 1 };
120
- }
121
- }
122
- const leafFrom = (p) => {
123
- if (p >= bytes.length) {
124
- return null;
125
- }
126
- return singleLeaf[p];
127
- };
128
- const chunkEnd = new Uint32Array(bytes.length);
129
- const sorted = [...starts].sort((a, b) => a - b);
130
- for (let si = 0; si < sorted.length; si++) {
131
- const chunkStart = sorted[si];
132
- const chunkLimit = si + 1 < sorted.length ? sorted[si + 1] : bytes.length;
133
- for (let p = chunkStart; p < chunkLimit; p++) {
134
- chunkEnd[p] = chunkLimit;
135
- }
136
- }
137
- const tryChain = (p, maxIds) => {
138
- const first = leafFrom(p);
139
- if (!first) {
140
- return;
141
- }
142
- emit(p, first.end, first.id);
143
- const ids = [first.id];
144
- let pos = first.end;
145
- let prevId = null;
146
- for (let depth = 1; pos < bytes.length && ids.length <= maxIds; depth++) {
147
- const nx = leafFrom(pos);
148
- if (!nx) {
149
- break;
150
- }
151
- ids.push(nx.id);
152
- pos = nx.end;
153
- if (store.findBranch(ids) === null) {
154
- continue;
155
- }
156
- const id = resolveSpan(p, pos);
157
- if (id === null || id === prevId) {
158
- continue;
159
- }
160
- prevId = id;
161
- emit(p, pos, id);
162
- }
163
- };
164
- for (let p = 0; p < bytes.length; p++) {
165
- if (starts.has(p)) {
166
- tryChain(p, chainReach(W)); // boundary start — full reach
167
- } else {
168
- const limit = chunkEnd[p] + W;
169
- tryChain(p, Math.min(limit - p, chainReach(W)));
170
- }
171
- }
172
- // ── splits: a form boundary that does not fall on a leaf edge ────────
173
- const leafEdges = new Set([bytes.length]);
174
- for (const lf of leaves) {
175
- leafEdges.add(lf.start);
176
- }
177
- for (const s of sites) {
178
- if (!leafEdges.has(s.start)) {
179
- splits.add(s.start);
180
127
  }
181
- if (!leafEdges.has(s.end)) {
182
- splits.add(s.end);
128
+ const tryChain = (p, maxIds) => {
129
+ const first = leafFrom(p);
130
+ if (!first)
131
+ return;
132
+ emit(p, first.end, first.id);
133
+ const ids = [first.id];
134
+ let pos = first.end;
135
+ let prevId = null;
136
+ for (let depth = 1; pos < bytes.length && ids.length <= maxIds; depth++) {
137
+ const nx = leafFrom(pos);
138
+ if (!nx)
139
+ break;
140
+ ids.push(nx.id);
141
+ pos = nx.end;
142
+ if (store.findBranch(ids) === null)
143
+ continue;
144
+ const id = resolveSpan(p, pos);
145
+ if (id === null || id === prevId)
146
+ continue;
147
+ prevId = id;
148
+ emit(p, pos, id);
149
+ }
150
+ };
151
+ for (let p = 0; p < bytes.length; p++) {
152
+ if (starts.has(p)) {
153
+ tryChain(p, chainReach(W)); // boundary start — full reach
154
+ }
155
+ else {
156
+ const limit = chunkEnd[p] + W;
157
+ tryChain(p, Math.min(limit - p, chainReach(W)));
158
+ }
183
159
  }
184
- }
185
- ctx.trace?.step(
186
- "recognise",
187
- [rItem(bytes, "query")],
188
- sites.map((s) =>
189
- rItem(bytes.subarray(s.start, s.end), "form", s.payload, [
160
+ // ── splits: a form boundary that does not fall on a leaf edge ────────
161
+ const leafEdges = new Set([bytes.length]);
162
+ for (const lf of leaves)
163
+ leafEdges.add(lf.start);
164
+ for (const s of sites) {
165
+ if (!leafEdges.has(s.start))
166
+ splits.add(s.start);
167
+ if (!leafEdges.has(s.end))
168
+ splits.add(s.end);
169
+ }
170
+ ctx.trace?.step("recognise", [rItem(bytes, "query")], sites.map((s) => rItem(bytes.subarray(s.start, s.end), "form", s.payload, [
190
171
  s.start,
191
172
  s.end,
192
- ])
193
- ),
194
- `decompose the query into ${sites.length} learnt form(s) that lead somewhere` +
195
- ` (over ${leaves.length} perceived leaves)`,
196
- );
197
- return { sites, leaves, splits };
173
+ ])), `decompose the query into ${sites.length} learnt form(s) that lead somewhere` +
174
+ ` (over ${leaves.length} perceived leaves)`);
175
+ return { sites, leaves, splits };
198
176
  }
199
177
  /** Segment bytes using the geometry's own groupings — leaf-parent
200
178
  * nodes from the perceived tree, with consecutive bare leaves merged
@@ -202,47 +180,44 @@ function recogniseImpl(ctx, bytes) {
202
180
  * IN ISOLATION, so the same content has the same gist regardless of
203
181
  * where it appears. */
204
182
  export function segment(ctx, bytes) {
205
- const tree = perceive(ctx, bytes);
206
- const out = [];
207
- let pendingStart = -1;
208
- let pendingEnd = -1;
209
- const flush = () => {
210
- if (pendingStart >= 0 && pendingEnd > pendingStart) {
211
- out.push({
212
- start: pendingStart,
213
- end: pendingEnd,
214
- v: gistOf(ctx, bytes.subarray(pendingStart, pendingEnd)),
215
- });
216
- }
217
- pendingStart = -1;
218
- pendingEnd = -1;
219
- };
220
- const walk = (n, start) => {
221
- if (n.kids === null) {
222
- const end = start + (n.leaf?.length ?? 0);
223
- if (pendingStart < 0) {
224
- pendingStart = start;
225
- }
226
- pendingEnd = end;
227
- return end;
228
- }
229
- if (isChunk(n)) {
230
- flush();
231
- let end = start;
232
- for (const c of n.kids) {
233
- end += c.leaf?.length ?? 0;
234
- }
235
- out.push({ start, end, v: gistOf(ctx, bytes.subarray(start, end)) });
236
- return end;
237
- }
183
+ const tree = perceive(ctx, bytes);
184
+ const out = [];
185
+ let pendingStart = -1;
186
+ let pendingEnd = -1;
187
+ const flush = () => {
188
+ if (pendingStart >= 0 && pendingEnd > pendingStart) {
189
+ out.push({
190
+ start: pendingStart,
191
+ end: pendingEnd,
192
+ v: gistOf(ctx, bytes.subarray(pendingStart, pendingEnd)),
193
+ });
194
+ }
195
+ pendingStart = -1;
196
+ pendingEnd = -1;
197
+ };
198
+ const walk = (n, start) => {
199
+ if (n.kids === null) {
200
+ const end = start + (n.leaf?.length ?? 0);
201
+ if (pendingStart < 0)
202
+ pendingStart = start;
203
+ pendingEnd = end;
204
+ return end;
205
+ }
206
+ if (isChunk(n)) {
207
+ flush();
208
+ let end = start;
209
+ for (const c of n.kids)
210
+ end += c.leaf?.length ?? 0;
211
+ out.push({ start, end, v: gistOf(ctx, bytes.subarray(start, end)) });
212
+ return end;
213
+ }
214
+ flush();
215
+ let pos = start;
216
+ for (const c of n.kids)
217
+ pos = walk(c, pos);
218
+ return pos;
219
+ };
220
+ walk(tree, 0);
238
221
  flush();
239
- let pos = start;
240
- for (const c of n.kids) {
241
- pos = walk(c, pos);
242
- }
243
- return pos;
244
- };
245
- walk(tree, 0);
246
- flush();
247
- return out;
222
+ return out;
248
223
  }
@@ -2,12 +2,7 @@ import type { MindContext } from "./types.js";
2
2
  /** The connector that belongs BETWEEN two adjacent results — the graded
3
3
  * junction ladder described in the module note above. Returns null when
4
4
  * the graph holds no evidence that the two ever ran together. */
5
- export declare function bridge(
6
- ctx: MindContext,
7
- left: Uint8Array,
8
- right: Uint8Array,
9
- interiorAllowance?: number,
10
- ): Promise<Uint8Array | null>;
5
+ export declare function bridge(ctx: MindContext, left: Uint8Array, right: Uint8Array, interiorAllowance?: number): Promise<Uint8Array | null>;
11
6
  /** Join two spans with the learnt connector between them, when one exists —
12
7
  * the composition step every out-of-search assembly (multi-topic fusion,
13
8
  * CAST's substitution and comparison) shares. A miss joins the pieces BARE
@@ -15,26 +10,14 @@ export declare function bridge(
15
10
  * so a degraded join is visible in the rationale regardless of which
16
11
  * mechanism paid it. (The in-search connector splice in graph-search.ts is
17
12
  * the same concept inside the deduction, where the join is a costed rule.) */
18
- export declare function joinWithBridge(
19
- ctx: MindContext,
20
- left: Uint8Array,
21
- right: Uint8Array,
22
- ): Promise<Uint8Array>;
13
+ export declare function joinWithBridge(ctx: MindContext, left: Uint8Array, right: Uint8Array): Promise<Uint8Array>;
23
14
  /** The pivot a produced answer bridges through: the longest UNCONSUMED learnt
24
15
  * CONTEXT (a node bearing a continuation edge) whose bytes `answer` literally
25
16
  * contains. Candidates are gathered by resonating the answer's sub-regions
26
17
  * (breadth-first, leaves skipped, probes capped by branch count), then
27
18
  * confirmed by exact byte containment — a near-resonance alone never hops. */
28
- export declare function pivotInto(
29
- ctx: MindContext,
30
- answer: Uint8Array,
31
- consumed: ReadonlySet<number>,
32
- ): Promise<number | null>;
33
- export declare function meaningOf(
34
- ctx: MindContext,
35
- bytes: Uint8Array,
36
- anchors: ReadonlyArray<{
19
+ export declare function pivotInto(ctx: MindContext, answer: Uint8Array, consumed: ReadonlySet<number>): Promise<number | null>;
20
+ export declare function meaningOf(ctx: MindContext, bytes: Uint8Array, anchors: ReadonlyArray<{
37
21
  name: string;
38
22
  form: Uint8Array;
39
- }>,
40
- ): Promise<string | null>;
23
+ }>): Promise<string | null>;
Binary file
@@ -1,34 +1,15 @@
1
1
  import type { MindContext } from "./types.js";
2
2
  import type { DerivationStep } from "./graph-search.js";
3
3
  import type { RationaleItem } from "./rationale.js";
4
- export declare function rItem(
5
- bytes: Uint8Array,
6
- role?: string,
7
- node?: number,
8
- span?: [number, number],
9
- ): RationaleItem;
10
- export declare function rNode(
11
- ctx: MindContext,
12
- id: number,
13
- role?: string,
14
- score?: number,
15
- ): RationaleItem;
16
- export declare function rDeriv(
17
- ctx: MindContext,
18
- it: DerivationStep["conclusion"],
19
- role?: string,
20
- ): RationaleItem;
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;
21
7
  /** The standard FALL-THROUGH closer every self-gating mechanism ends with:
22
8
  * close the open scope with no outputs and the reason, and return null so
23
9
  * the caller can `return fail("…")` in one expression. `t` is the scope an
24
10
  * enclosing `ctx.trace?.enter(...)` returned (undefined when not tracing). */
25
- export declare function traceFail(
26
- t: {
11
+ export declare function traceFail(t: {
27
12
  done(outputs: RationaleItem[], note?: string): void;
28
- } | undefined,
29
- ): (note: string) => null;
13
+ } | undefined): (note: string) => null;
30
14
  export declare const MOVE_NOTE: Record<string, string>;
31
- export declare function traceDerivation(
32
- ctx: MindContext,
33
- steps: ReadonlyArray<DerivationStep>,
34
- ): void;
15
+ export declare function traceDerivation(ctx: MindContext, steps: ReadonlyArray<DerivationStep>): void;
@@ -6,76 +6,68 @@
6
6
  import { read } from "./primitives.js";
7
7
  import { decodeText } from "./rationale.js";
8
8
  export function rItem(bytes, role, node, span) {
9
- return {
10
- text: decodeText(bytes),
11
- role,
12
- node: node ?? undefined,
13
- span,
14
- };
9
+ return {
10
+ text: decodeText(bytes),
11
+ role,
12
+ node: node ?? undefined,
13
+ span,
14
+ };
15
15
  }
16
16
  export function rNode(ctx, id, role, score) {
17
- return {
18
- text: decodeText(read(ctx, id)),
19
- node: id,
20
- role,
21
- score,
22
- };
17
+ return {
18
+ text: decodeText(read(ctx, id)),
19
+ node: id,
20
+ role,
21
+ score,
22
+ };
23
23
  }
24
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 };
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
33
  }
34
34
  /** The standard FALL-THROUGH closer every self-gating mechanism ends with:
35
35
  * close the open scope with no outputs and the reason, and return null so
36
36
  * the caller can `return fail("…")` in one expression. `t` is the scope an
37
37
  * enclosing `ctx.trace?.enter(...)` returned (undefined when not tracing). */
38
38
  export function traceFail(t) {
39
- return (note) => {
40
- t?.done([], note);
41
- return null;
42
- };
39
+ return (note) => {
40
+ t?.done([], note);
41
+ return null;
42
+ };
43
43
  }
44
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":
55
- "pool independent regions' evidence for a shared anchor (sum, not shortest path)",
56
- "axiom": "a seed: a perceived leaf, recognised form, or computed result",
57
- "step": "a derivation step",
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",
58
57
  };
59
58
  export function traceDerivation(ctx, steps) {
60
- const t = ctx.trace;
61
- if (!t) {
62
- return;
63
- }
64
- const indexOfOrder = new Map();
65
- for (const s of steps) {
66
- const note = MOVE_NOTE[s.move] ?? s.move;
67
- const deps = s.producers
68
- .map((o) => indexOfOrder.get(o))
69
- .filter((x) => x !== undefined);
70
- const premises = s.premises.map((p) => rDeriv(ctx, p));
71
- const conclusion = [rDeriv(ctx, s.conclusion)];
72
- const index = t.step(
73
- s.move,
74
- premises,
75
- conclusion,
76
- s.cost > 0 ? `${note} (cost ${s.cost})` : note,
77
- deps.length > 0 ? deps : undefined,
78
- );
79
- indexOfOrder.set(s.order, index);
80
- }
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
+ }
81
73
  }