@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
@@ -1,7 +1,7 @@
1
1
  import { Vec } from "./vec.js";
2
2
  import type { AlphabetConfig } from "./config.js";
3
3
  export declare class Alphabet {
4
- readonly vecs: Vec[];
5
- readonly config: AlphabetConfig;
6
- constructor(seed: number, D: number, config?: Partial<AlphabetConfig>);
4
+ readonly vecs: Vec[];
5
+ readonly config: AlphabetConfig;
6
+ constructor(seed: number, D: number, config?: Partial<AlphabetConfig>);
7
7
  }
@@ -5,32 +5,29 @@
5
5
  // resonate; far-apart values are quasi-orthogonal.
6
6
  import { addInto, copy, normalize, randomUnit, rng } from "./vec.js";
7
7
  export class Alphabet {
8
- vecs = [];
9
- config;
10
- constructor(seed, D, config) {
11
- this.config = {
12
- roughness: config?.roughness ?? 0.65,
13
- seedMask: config?.seedMask ?? 0xa1fa17,
14
- };
15
- const rand = rng((seed ^ this.config.seedMask) >>> 0);
16
- const refine = (parent) => {
17
- const v = copy(parent);
18
- for (let i = 0; i < v.length; i++) {
19
- v[i] *= Math.sqrt(1 - this.config.roughness);
20
- }
21
- addInto(v, randomUnit(D, rand), Math.sqrt(this.config.roughness));
22
- return normalize(v);
23
- };
24
- const coarse = [];
25
- for (let i = 0; i < 16; i++) {
26
- coarse.push(randomUnit(D, rand));
8
+ vecs = [];
9
+ config;
10
+ constructor(seed, D, config) {
11
+ this.config = {
12
+ roughness: config?.roughness ?? 0.65,
13
+ seedMask: config?.seedMask ?? 0xa1fa17,
14
+ };
15
+ const rand = rng((seed ^ this.config.seedMask) >>> 0);
16
+ const refine = (parent) => {
17
+ const v = copy(parent);
18
+ for (let i = 0; i < v.length; i++) {
19
+ v[i] *= Math.sqrt(1 - this.config.roughness);
20
+ }
21
+ addInto(v, randomUnit(D, rand), Math.sqrt(this.config.roughness));
22
+ return normalize(v);
23
+ };
24
+ const coarse = [];
25
+ for (let i = 0; i < 16; i++)
26
+ coarse.push(randomUnit(D, rand));
27
+ const mid = [];
28
+ for (let i = 0; i < 64; i++)
29
+ mid.push(refine(coarse[i >> 2]));
30
+ for (let b = 0; b < 256; b++)
31
+ this.vecs.push(refine(mid[b >> 2]));
27
32
  }
28
- const mid = [];
29
- for (let i = 0; i < 64; i++) {
30
- mid.push(refine(coarse[i >> 2]));
31
- }
32
- for (let b = 0; b < 256; b++) {
33
- this.vecs.push(refine(mid[b >> 2]));
34
- }
35
- }
36
33
  }
@@ -5,206 +5,181 @@ import type { ConceptAnchor } from "./resonance.js";
5
5
  import { type AluHost, type ComputedSpan } from "./parser.js";
6
6
  /** A numeric literal found in the byte stream, with its parsed value. */
7
7
  export interface OperandSpan {
8
- i: number;
9
- j: number;
10
- value: Value;
8
+ i: number;
9
+ j: number;
10
+ value: Value;
11
11
  }
12
12
  /** A recognised operator span: the byte range and the canonical op it names. */
13
13
  export interface OperatorSpan {
14
- i: number;
15
- j: number;
16
- name: string;
17
- /** Operand count for INFIX use — a fixed arity as registered, or 2 for a
18
- * variadic op used as a binary infix operator. */
19
- arity: number;
14
+ i: number;
15
+ j: number;
16
+ name: string;
17
+ /** Operand count for INFIX use — a fixed arity as registered, or 2 for a
18
+ * variadic op used as a binary infix operator. */
19
+ arity: number;
20
20
  }
21
21
  /** Options for assembling an {@link Alu}. */
22
22
  export interface AluOptions {
23
- /** Decimal places a real result is rounded to before encoding (determinism). */
24
- precision?: number;
25
- /** Numerical convergence tolerance and iteration ceiling. */
26
- tol?: number;
27
- maxIter?: number;
23
+ /** Decimal places a real result is rounded to before encoding (determinism). */
24
+ precision?: number;
25
+ /** Numerical convergence tolerance and iteration ceiling. */
26
+ tol?: number;
27
+ maxIter?: number;
28
28
  }
29
29
  export declare class Alu {
30
- readonly registry: OperationRegistry;
31
- readonly codec: ValueCodec;
32
- private readonly rt;
33
- /** Symbolic operator forms (no ASCII letter/digit), as byte patterns, sorted
34
- * longest-first so the scanner matches "<=" before "<". */
35
- private readonly symbolicForms;
36
- private _grammar?;
37
- private _anchors?;
38
- /** How many {@link apply} calls ended in a caught throw this session, and
39
- * the most recent caught error. A caught throw is USUALLY a routine
40
- * decline (a symbol fed to arithmetic — the "rule does not fire"
41
- * contract), but the same catch would also swallow a genuine kernel bug;
42
- * these two fields make that observable instead of silent. Zero cost when
43
- * nothing throws. */
44
- applyCaught: number;
45
- lastApplyError: unknown;
46
- private readonly decoder;
47
- /** The query parser, wired to the host port — internal; hosts reach it only
48
- * through {@link parse} and {@link compute}. */
49
- private readonly parser;
50
- constructor(opts?: AluOptions, host?: AluHost);
51
- /** Recognise and evaluate every computation `query` invokes — infix
52
- * arithmetic runs, and operations named literally or by meaning (through the
53
- * host port). All async resonance is resolved inside, so the caller
54
- * receives finished spans it can fold synchronously into its search. See
55
- * {@link "./parser.js".QueryParser.parse}. */
56
- parse(query: Uint8Array): Promise<ComputedSpan[]>;
57
- /** Apply an operation to operand byte spans — operand STRUCTURE recognised
58
- * into Values, every reachable symbol's resonance pre-resolved through the
59
- * host port — and encode the result canonically; null when the computation
60
- * declines. See {@link "./parser.js".QueryParser.compute}. */
61
- compute(
62
- name: string,
63
- operandBytes: Uint8Array[],
64
- asSymbol?: (idx: number) => boolean,
65
- ): Promise<Uint8Array | null>;
66
- /** Infix arity of an op: its fixed arity, or 2 for a variadic op (an infix
67
- * operator binds two operands; the registry's variadic fold still accepts
68
- * the pair). */
69
- private infixArity;
70
- /** Collect the symbolic surface forms (punctuation, no letters/digits) as
71
- * UTF-8 byte patterns. Each maps to the binary claimant when one exists, so
72
- * an infix scan resolves a shared symbol to its two-operand reading. */
73
- private buildSymbolicForms;
74
- /** The canonical op name(s) a literal surface form names (exact lookup). */
75
- lookupOperator(form: string): readonly string[];
76
- /** The operation CONCEPT anchors: the (canonical name, form bytes) pairs a
77
- * span's MEANING is resonated against, so an operation the bytes do not
78
- * literally spell (an integral, a derivative, a limit, …, in any modality)
79
- * is recognised by gist nearness to one of these forms. This is what makes
80
- * operation recognition generic and modality-agnostic rather than a fixed
81
- * symbol table and the ALU, not the host, decides which of its surface
82
- * forms are anchors, using its own machinery:
83
- *
84
- * a form the SCANNER already reads in full (a pure operator symbol like
85
- * "<=", a numeral like "0") is excluded — the literal path owns it, and
86
- * its meaning-space image would only add noise;
87
- * a form must be COMPOUND (≥ 2 runes): a single atom's gist is a
88
- * coordinate of the alphabet, not a distributional meaning, so there is
89
- * nothing for resonance to read.
90
- *
91
- * Cached once; the stable array identity lets the host memoise whatever
92
- * representation (gists, indices) it derives from it. */
93
- conceptAnchors(): ReadonlyArray<ConceptAnchor>;
94
- /** The registry-derived expression grammar, built once: infix binding and
95
- * prefix/function/constant resolution all read off the registered ops, and
96
- * every evaluation step routes back through this registry's own arithmetic
97
- * recursion all the way down (see expr.ts). */
98
- get grammar(): ExprGrammar;
99
- /** Evaluate an expression's bytes at a variable binding, through this
100
- * registry's own arithmetic (see {@link grammar}). */
101
- evalExpression(
102
- bytes: Uint8Array,
103
- variable: string,
104
- at: number,
105
- ): number | null;
106
- /** Whether a name is a registered operation. */
107
- has(name: string): boolean;
108
- /** The infix arity of a registered op (for the host to size a rule), or 0. */
109
- arityOf(name: string): number;
110
- /** Whether an op acts on an EXPRESSION (a function) rather than plain numbers
111
- * — declared by the op itself at registration (the `expression` trait), so
112
- * there is no side table of names here. */
113
- isExpressionOp(name: string): boolean;
114
- /** Scan a byte span for operand (numeric) and operator (symbolic) spans. A
115
- * pure, deterministic left-to-right lexer: at each position take a numeral if
116
- * one starts there, else the longest symbolic operator form, else skip one
117
- * byte. Numerals and operator symbols are disjoint character classes, so the
118
- * two never overlap. */
119
- scan(bytes: Uint8Array): {
120
- operands: OperandSpan[];
121
- operators: OperatorSpan[];
122
- };
123
- private matchSymbolic;
124
- /** Read a byte span into a {@link Value} by recognising its STRUCTURE the
125
- * byte⇄Value boundary the host computes across. The kernel itself only knows
126
- * the irreducible scalar floor (a numeral's digits a quantity, via {@link
127
- * parseValue}); recognising whether a span is one quantity or a LIST of them is
128
- * layered here, over {@link scan}, so no caller re-implements it.
129
- *
130
- * A LIST is a run of element values joined by a CONSISTENT separator. No
131
- * spelling is privileged: two complementary readings cover the forms a list
132
- * takes
133
- *
134
- * CONTAINER an explicit `[ ]` group delimits a list whose elements may
135
- * be anything (symbols, nested groups, mixed): split its interior at the TOP
136
- * level (bracket-depth aware) on separator runs, each element recognised in
137
- * turn (so nesting and heterogeneity recurse for free). This is also the
138
- * codec's canonical OUTPUT spelling, so a computed list feeds straight back
139
- * in as an operand.
140
- * SEQUENCE a bare run of ≥2 numeric operands with a consistent connective
141
- * between them (`1 2 3`, `1, 2, 3`, `1 and 2 and 3`): the operands {@link
142
- * scan} finds are the elements, and whatever sits between them a space, a
143
- * comma, " and " is the separator, accepted as long as it is the same
144
- * throughout and the run has no leftover edges.
145
- *
146
- * Anything else is a SCALAR ({@link parseValue}): a numeral, or an opaque
147
- * symbol of any modality (a learnt form, an operator name a higher-order op
148
- * will resolve, a single word). */
149
- recogniseValue(bytes: Uint8Array): Value;
150
- /** Split a CONTAINER's interior into its element values top-level (bracket-
151
- * depth aware) spans divided by separator RUNS (maximal runs of {@link
152
- * isSepByte}). The brackets are the explicit delimiter, so the divider's
153
- * spelling is not privileged (`[1,2,3]`, `[1, 2, 3]`, `[1 2 3]` are the same
154
- * list). Each element is recognised in turn, so a nested `[ ]` element
155
- * recurses and a symbol element stays opaque. An empty interior is `[]`. */
156
- private recogniseContainer;
157
- /** Recognise a bare SEQUENCE ≥2 numeric operands separated by a consistent
158
- * connective, with no leftover material at the edges or null when the span
159
- * is not such a sequence. The operands are exactly the ones {@link scan}
160
- * finds; the bytes between consecutive operands are the separator, which need
161
- * only be the SAME throughout (a space, a comma, " and ", …) — its spelling is
162
- * not constrained, so no separator is privileged. */
163
- private recogniseSequence;
164
- /** Apply an op to operand values, with the given pre-resolved resonance.
165
- * Returns the result value, or null if the op is unknown or the computation
166
- * throws (e.g. a symbol fed to arithmetic) the caller treats null as "this
167
- * rule does not fire", never as a wrong answer. */
168
- apply(
169
- name: string,
170
- operands: Value[],
171
- resonance?: ResonanceSync,
172
- ): Value | null;
173
- /** The expression evaluator handed to op contexts, bound to the cached {@link
174
- * grammar}: the numerical layer's integrand is evaluated by a recursive
175
- * application of the same derived-from-nand arithmetic. */
176
- private makeEvalExpr;
177
- /** Decode operand byte spans, apply `name`, and encode the result — the pure
178
- * computation the graph rule materialises into an output span. Returns null
179
- * on any failure (unknown op, undecodable operand, thrown computation), so a
180
- * rule that cannot compute simply does not fire. The result bytes are
181
- * canonical (see {@link decimalCodec}), so two derivations of the same value
182
- * agree byte-for-byte required for the search's chart memoization. */
183
- applyBytes(
184
- name: string,
185
- operandBytes: Uint8Array[],
186
- resonance?: ResonanceSync,
187
- ): Uint8Array | null;
188
- /** Apply `name` to operand VALUES (a scalar, or an `nd` recognised by {@link
189
- * recogniseValue}), and encode the result canonically. This is the entry
190
- * point for computation over STRUCTURE: the scalar kernel and the nd kernel
191
- * both consume Values, so once a span is recognised the computation is the
192
- * same whether the operand came in as a number or a list. Returns null on any
193
- * failure (unknown op, thrown computation), the same "this rule does not fire"
194
- * contract as {@link applyBytes}. */
195
- applyValues(
196
- name: string,
197
- operands: Value[],
198
- resonance?: ResonanceSync,
199
- ): Uint8Array | null;
200
- /** Like {@link applyBytes}, but `asSymbol(idx)` marks operand positions that
201
- * must be kept as an opaque SYMBOL (not parsed as a number) — the convention
202
- * the numerical layer needs, where operand 0 is an EXPRESSION (a function's
203
- * bytes) the kernel samples via the expression evaluator, not a numeral. */
204
- applyBytesTyped(
205
- name: string,
206
- operandBytes: Uint8Array[],
207
- asSymbol: (idx: number) => boolean,
208
- resonance?: ResonanceSync,
209
- ): Uint8Array | null;
30
+ readonly registry: OperationRegistry;
31
+ readonly codec: ValueCodec;
32
+ private readonly rt;
33
+ /** Symbolic operator forms (no ASCII letter/digit), as byte patterns, sorted
34
+ * longest-first so the scanner matches "<=" before "<". */
35
+ private readonly symbolicForms;
36
+ private _grammar?;
37
+ private _anchors?;
38
+ /** How many {@link apply} calls ended in a caught throw this session, and
39
+ * the most recent caught error. A caught throw is USUALLY a routine
40
+ * decline (a symbol fed to arithmetic — the "rule does not fire"
41
+ * contract), but the same catch would also swallow a genuine kernel bug;
42
+ * these two fields make that observable instead of silent. Zero cost when
43
+ * nothing throws. */
44
+ applyCaught: number;
45
+ lastApplyError: unknown;
46
+ private readonly decoder;
47
+ /** The query parser, wired to the host port — internal; hosts reach it only
48
+ * through {@link parse} and {@link compute}. */
49
+ private readonly parser;
50
+ constructor(opts?: AluOptions, host?: AluHost);
51
+ /** Recognise and evaluate every computation `query` invokes — infix
52
+ * arithmetic runs, and operations named literally or by meaning (through the
53
+ * host port). All async resonance is resolved inside, so the caller
54
+ * receives finished spans it can fold synchronously into its search. See
55
+ * {@link "./parser.js".QueryParser.parse}. */
56
+ parse(query: Uint8Array): Promise<ComputedSpan[]>;
57
+ /** Apply an operation to operand byte spans — operand STRUCTURE recognised
58
+ * into Values, every reachable symbol's resonance pre-resolved through the
59
+ * host port — and encode the result canonically; null when the computation
60
+ * declines. See {@link "./parser.js".QueryParser.compute}. */
61
+ compute(name: string, operandBytes: Uint8Array[], asSymbol?: (idx: number) => boolean): Promise<Uint8Array | null>;
62
+ /** Infix arity of an op: its fixed arity, or 2 for a variadic op (an infix
63
+ * operator binds two operands; the registry's variadic fold still accepts
64
+ * the pair). */
65
+ private infixArity;
66
+ /** Collect the symbolic surface forms (punctuation, no letters/digits) as
67
+ * UTF-8 byte patterns. Each maps to the binary claimant when one exists, so
68
+ * an infix scan resolves a shared symbol to its two-operand reading. */
69
+ private buildSymbolicForms;
70
+ /** The canonical op name(s) a literal surface form names (exact lookup). */
71
+ lookupOperator(form: string): readonly string[];
72
+ /** The operation CONCEPT anchors: the (canonical name, form bytes) pairs a
73
+ * span's MEANING is resonated against, so an operation the bytes do not
74
+ * literally spell (an integral, a derivative, a limit, …, in any modality)
75
+ * is recognised by gist nearness to one of these forms. This is what makes
76
+ * operation recognition generic and modality-agnostic rather than a fixed
77
+ * symbol table and the ALU, not the host, decides which of its surface
78
+ * forms are anchors, using its own machinery:
79
+ *
80
+ * a form the SCANNER already reads in full (a pure operator symbol like
81
+ * "<=", a numeral like "0") is excluded the literal path owns it, and
82
+ * its meaning-space image would only add noise;
83
+ * • a form must be COMPOUND (≥ 2 runes): a single atom's gist is a
84
+ * coordinate of the alphabet, not a distributional meaning, so there is
85
+ * nothing for resonance to read.
86
+ *
87
+ * Cached once; the stable array identity lets the host memoise whatever
88
+ * representation (gists, indices) it derives from it. */
89
+ conceptAnchors(): ReadonlyArray<ConceptAnchor>;
90
+ /** The registry-derived expression grammar, built once: infix binding and
91
+ * prefix/function/constant resolution all read off the registered ops, and
92
+ * every evaluation step routes back through this registry's own arithmetic —
93
+ * recursion all the way down (see expr.ts). */
94
+ get grammar(): ExprGrammar;
95
+ /** Evaluate an expression's bytes at a variable binding, through this
96
+ * registry's own arithmetic (see {@link grammar}). */
97
+ evalExpression(bytes: Uint8Array, variable: string, at: number): number | null;
98
+ /** Whether a name is a registered operation. */
99
+ has(name: string): boolean;
100
+ /** The infix arity of a registered op (for the host to size a rule), or 0. */
101
+ arityOf(name: string): number;
102
+ /** Whether an op acts on an EXPRESSION (a function) rather than plain numbers
103
+ * — declared by the op itself at registration (the `expression` trait), so
104
+ * there is no side table of names here. */
105
+ isExpressionOp(name: string): boolean;
106
+ /** Scan a byte span for operand (numeric) and operator (symbolic) spans. A
107
+ * pure, deterministic left-to-right lexer: at each position take a numeral if
108
+ * one starts there, else the longest symbolic operator form, else skip one
109
+ * byte. Numerals and operator symbols are disjoint character classes, so the
110
+ * two never overlap. */
111
+ scan(bytes: Uint8Array): {
112
+ operands: OperandSpan[];
113
+ operators: OperatorSpan[];
114
+ };
115
+ private matchSymbolic;
116
+ /** Read a byte span into a {@link Value} by recognising its STRUCTURE — the
117
+ * byte⇄Value boundary the host computes across. The kernel itself only knows
118
+ * the irreducible scalar floor (a numeral's digits → a quantity, via {@link
119
+ * parseValue}); recognising whether a span is one quantity or a LIST of them is
120
+ * layered here, over {@link scan}, so no caller re-implements it.
121
+ *
122
+ * A LIST is a run of element values joined by a CONSISTENT separator. No
123
+ * spelling is privileged: two complementary readings cover the forms a list
124
+ * takes
125
+ *
126
+ * CONTAINER an explicit `[ ]` group delimits a list whose elements may
127
+ * be anything (symbols, nested groups, mixed): split its interior at the TOP
128
+ * level (bracket-depth aware) on separator runs, each element recognised in
129
+ * turn (so nesting and heterogeneity recurse for free). This is also the
130
+ * codec's canonical OUTPUT spelling, so a computed list feeds straight back
131
+ * in as an operand.
132
+ * SEQUENCE a bare run of ≥2 numeric operands with a consistent connective
133
+ * between them (`1 2 3`, `1, 2, 3`, `1 and 2 and 3`): the operands {@link
134
+ * scan} finds are the elements, and whatever sits between them a space, a
135
+ * comma, " and " — is the separator, accepted as long as it is the same
136
+ * throughout and the run has no leftover edges.
137
+ *
138
+ * Anything else is a SCALAR ({@link parseValue}): a numeral, or an opaque
139
+ * symbol of any modality (a learnt form, an operator name a higher-order op
140
+ * will resolve, a single word). */
141
+ recogniseValue(bytes: Uint8Array): Value;
142
+ /** Split a CONTAINER's interior into its element valuestop-level (bracket-
143
+ * depth aware) spans divided by separator RUNS (maximal runs of {@link
144
+ * isSepByte}). The brackets are the explicit delimiter, so the divider's
145
+ * spelling is not privileged (`[1,2,3]`, `[1, 2, 3]`, `[1 2 3]` are the same
146
+ * list). Each element is recognised in turn, so a nested `[ ]` element
147
+ * recurses and a symbol element stays opaque. An empty interior is `[]`. */
148
+ private recogniseContainer;
149
+ /** Recognise a bare SEQUENCE — ≥2 numeric operands separated by a consistent
150
+ * connective, with no leftover material at the edgesor null when the span
151
+ * is not such a sequence. The operands are exactly the ones {@link scan}
152
+ * finds; the bytes between consecutive operands are the separator, which need
153
+ * only be the SAME throughout (a space, a comma, " and ", …) its spelling is
154
+ * not constrained, so no separator is privileged. */
155
+ private recogniseSequence;
156
+ /** Apply an op to operand values, with the given pre-resolved resonance.
157
+ * Returns the result value, or null if the op is unknown or the computation
158
+ * throws (e.g. a symbol fed to arithmetic) — the caller treats null as "this
159
+ * rule does not fire", never as a wrong answer. */
160
+ apply(name: string, operands: Value[], resonance?: ResonanceSync): Value | null;
161
+ /** The expression evaluator handed to op contexts, bound to the cached {@link
162
+ * grammar}: the numerical layer's integrand is evaluated by a recursive
163
+ * application of the same derived-from-nand arithmetic. */
164
+ private makeEvalExpr;
165
+ /** Decode operand byte spans, apply `name`, and encode the result the pure
166
+ * computation the graph rule materialises into an output span. Returns null
167
+ * on any failure (unknown op, undecodable operand, thrown computation), so a
168
+ * rule that cannot compute simply does not fire. The result bytes are
169
+ * canonical (see {@link decimalCodec}), so two derivations of the same value
170
+ * agree byte-for-byte — required for the search's chart memoization. */
171
+ applyBytes(name: string, operandBytes: Uint8Array[], resonance?: ResonanceSync): Uint8Array | null;
172
+ /** Apply `name` to operand VALUES (a scalar, or an `nd` recognised by {@link
173
+ * recogniseValue}), and encode the result canonically. This is the entry
174
+ * point for computation over STRUCTURE: the scalar kernel and the nd kernel
175
+ * both consume Values, so once a span is recognised the computation is the
176
+ * same whether the operand came in as a number or a list. Returns null on any
177
+ * failure (unknown op, thrown computation), the same "this rule does not fire"
178
+ * contract as {@link applyBytes}. */
179
+ applyValues(name: string, operands: Value[], resonance?: ResonanceSync): Uint8Array | null;
180
+ /** Like {@link applyBytes}, but `asSymbol(idx)` marks operand positions that
181
+ * must be kept as an opaque SYMBOL (not parsed as a number) the convention
182
+ * the numerical layer needs, where operand 0 is an EXPRESSION (a function's
183
+ * bytes) the kernel samples via the expression evaluator, not a numeral. */
184
+ applyBytesTyped(name: string, operandBytes: Uint8Array[], asSymbol: (idx: number) => boolean, resonance?: ResonanceSync): Uint8Array | null;
210
185
  }