@hviana/sema 0.1.0

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 (110) hide show
  1. package/AGENTS.md +470 -0
  2. package/AUTHORS.md +12 -0
  3. package/COMMERCIAL-LICENSE.md +19 -0
  4. package/CONTRIBUTING.md +15 -0
  5. package/HOW_IT_WORKS.md +4210 -0
  6. package/LICENSE.md +117 -0
  7. package/README.md +290 -0
  8. package/TRADEMARKS.md +19 -0
  9. package/example/demo.ts +46 -0
  10. package/example/train_base.ts +2675 -0
  11. package/index.html +893 -0
  12. package/package.json +25 -0
  13. package/src/alphabet.ts +34 -0
  14. package/src/alu/README.md +332 -0
  15. package/src/alu/src/alu.ts +541 -0
  16. package/src/alu/src/expr.ts +339 -0
  17. package/src/alu/src/index.ts +115 -0
  18. package/src/alu/src/kernel-arith.ts +377 -0
  19. package/src/alu/src/kernel-bits.ts +199 -0
  20. package/src/alu/src/kernel-logic.ts +102 -0
  21. package/src/alu/src/kernel-nd.ts +235 -0
  22. package/src/alu/src/kernel-numeric.ts +466 -0
  23. package/src/alu/src/operation.ts +344 -0
  24. package/src/alu/src/parser.ts +574 -0
  25. package/src/alu/src/resonance.ts +161 -0
  26. package/src/alu/src/text.ts +83 -0
  27. package/src/alu/src/value.ts +327 -0
  28. package/src/alu/test/alu.test.ts +1004 -0
  29. package/src/bytes.ts +62 -0
  30. package/src/config.ts +227 -0
  31. package/src/derive/README.md +295 -0
  32. package/src/derive/src/deduction.ts +263 -0
  33. package/src/derive/src/index.ts +24 -0
  34. package/src/derive/src/priority-queue.ts +70 -0
  35. package/src/derive/src/rewrite.ts +127 -0
  36. package/src/derive/src/trie.ts +242 -0
  37. package/src/derive/test/derive.test.ts +137 -0
  38. package/src/extension.ts +42 -0
  39. package/src/geometry.ts +511 -0
  40. package/src/index.ts +38 -0
  41. package/src/ingest-cache.ts +224 -0
  42. package/src/mind/articulation.ts +137 -0
  43. package/src/mind/attention.ts +1061 -0
  44. package/src/mind/canonical.ts +107 -0
  45. package/src/mind/graph-search.ts +1100 -0
  46. package/src/mind/index.ts +18 -0
  47. package/src/mind/junction.ts +347 -0
  48. package/src/mind/learning.ts +246 -0
  49. package/src/mind/match.ts +507 -0
  50. package/src/mind/mechanisms/alu.ts +33 -0
  51. package/src/mind/mechanisms/cast.ts +568 -0
  52. package/src/mind/mechanisms/confluence.ts +268 -0
  53. package/src/mind/mechanisms/cover.ts +248 -0
  54. package/src/mind/mechanisms/extraction.ts +422 -0
  55. package/src/mind/mechanisms/recall.ts +241 -0
  56. package/src/mind/mind.ts +483 -0
  57. package/src/mind/pipeline-mechanism.ts +326 -0
  58. package/src/mind/pipeline.ts +300 -0
  59. package/src/mind/primitives.ts +201 -0
  60. package/src/mind/rationale.ts +275 -0
  61. package/src/mind/reasoning.ts +198 -0
  62. package/src/mind/recognition.ts +234 -0
  63. package/src/mind/resonance.ts +0 -0
  64. package/src/mind/trace.ts +108 -0
  65. package/src/mind/traverse.ts +556 -0
  66. package/src/mind/types.ts +281 -0
  67. package/src/rabitq-hnsw/README.md +303 -0
  68. package/src/rabitq-hnsw/src/database.ts +492 -0
  69. package/src/rabitq-hnsw/src/heap.ts +90 -0
  70. package/src/rabitq-hnsw/src/hnsw.ts +514 -0
  71. package/src/rabitq-hnsw/src/index.ts +15 -0
  72. package/src/rabitq-hnsw/src/prng.ts +39 -0
  73. package/src/rabitq-hnsw/src/rabitq.ts +308 -0
  74. package/src/rabitq-hnsw/src/store.ts +994 -0
  75. package/src/rabitq-hnsw/test/hnsw.test.ts +1213 -0
  76. package/src/store-sqlite.ts +928 -0
  77. package/src/store.ts +2148 -0
  78. package/src/vec.ts +124 -0
  79. package/test/00-extract.test.mjs +151 -0
  80. package/test/01-floor.test.mjs +20 -0
  81. package/test/02-roundtrip.test.mjs +83 -0
  82. package/test/03-recall.test.mjs +98 -0
  83. package/test/04-think.test.mjs +627 -0
  84. package/test/05-concepts.test.mjs +84 -0
  85. package/test/08-storage.test.mjs +948 -0
  86. package/test/09-edges.test.mjs +65 -0
  87. package/test/11-universality.test.mjs +180 -0
  88. package/test/13-conversation.test.mjs +228 -0
  89. package/test/14-scaling.test.mjs +503 -0
  90. package/test/15-decomposition-gap.test.mjs +0 -0
  91. package/test/16-bridge.test.mjs +250 -0
  92. package/test/17-intelligence.test.mjs +240 -0
  93. package/test/18-alu.test.mjs +209 -0
  94. package/test/19-nd.test.mjs +254 -0
  95. package/test/20-stability.test.mjs +489 -0
  96. package/test/21-partial.test.mjs +158 -0
  97. package/test/22-multihop.test.mjs +130 -0
  98. package/test/23-rationale.test.mjs +316 -0
  99. package/test/24-generalization.test.mjs +416 -0
  100. package/test/25-embedding.test.mjs +75 -0
  101. package/test/26-cooperative.test.mjs +89 -0
  102. package/test/27-saturation-drop.test.mjs +637 -0
  103. package/test/28-unknowable.test.mjs +88 -0
  104. package/test/29-counterfactual.test.mjs +476 -0
  105. package/test/30-conflict-resolution.test.mjs +166 -0
  106. package/test/31-audit.test.mjs +288 -0
  107. package/test/32-confluence.test.mjs +173 -0
  108. package/test/33-multi-candidate.test.mjs +222 -0
  109. package/test/34-cross-region.test.mjs +252 -0
  110. package/tsconfig.json +16 -0
@@ -0,0 +1,344 @@
1
+ // operation.ts — the Operation record and the registry it lives in.
2
+ //
3
+ // An Operation is the irreducible unit of the ALU. A PRIMITIVE op has a
4
+ // hand-written callback (the kernel's irreducible roots: nand, the real
5
+ // arithmetic primitives, converge); a DERIVED op's callback only calls OTHER ops
6
+ // by canonical name through the {@link OpContext}. The two are the SAME type —
7
+ // a caller cannot tell a primitive from a derivation — which is the whole point:
8
+ // "subtract = add ∘ negate" is registered exactly like a primitive and competes
9
+ // in the search exactly like one. Because a derived callback's body is a
10
+ // sequence of `ctx.apply("…", …)` calls, the derivation DAG is literal,
11
+ // inspectable source: you can read off, from nand, how every gate is built, and
12
+ // from add/multiply/converge how every number-theoretic and numerical op is.
13
+ //
14
+ // The module is pure. The one window onto meaning a callback may need — the
15
+ // resonant opposite of a symbol, for the polymorphic inverse — arrives through
16
+ // {@link ResonanceSync}, which the host pre-resolves (SEMA's async resonance is
17
+ // hoisted out of the synchronous search, exactly as concept hops and connectors
18
+ // are). ALU never queries resonance itself.
19
+
20
+ import { isNd, nd, type Value } from "./value.js";
21
+
22
+ /** Arity: a fixed operand count, or "variadic" for a fold (and/or of many,
23
+ * dot, min/max, polynomial evaluation). */
24
+ export type Arity = number | "variadic";
25
+
26
+ /** Synchronous resonance an op callback may consult, pre-resolved by the host.
27
+ * This is the only path by which a computation reads MEANING from a symbol's
28
+ * opaque bytes; numbers never touch it. */
29
+ export interface ResonanceSync {
30
+ /** The resonant opposite of a symbol's bytes — its antonym / inverse in the
31
+ * resonance space, of whatever modality — or null if none is known. Found
32
+ * by the host's halo resonance and handed in pre-resolved (see
33
+ * resonance.ts). */
34
+ opposite(bytes: Uint8Array): Uint8Array | null;
35
+ /** The canonical operation a symbol's bytes MEAN, found by resonance over the
36
+ * operation concepts — the GENERIC, modality-agnostic recognition path, the
37
+ * same one the host uses to recognise an operator a query does not literally
38
+ * spell. Pre-resolved by the host; null when nothing resonates. This is how
39
+ * the FUNCTION ARGUMENT of a higher-order nd op (the "+" of a reduce, the
40
+ * predicate of a filter) is resolved when it is not a literal surface form —
41
+ * see {@link OpContext.resolveOp}. */
42
+ recogniseOp(bytes: Uint8Array): string | null;
43
+ }
44
+
45
+ /** Runtime knobs the numerical kernel reads (the limit layer's tolerance and
46
+ * iteration ceiling). Carried on the context so a derived op never closes
47
+ * over global state. */
48
+ export interface OpRuntime {
49
+ /** Convergence tolerance ε: a refinement stops when successive results agree
50
+ * within this. */
51
+ tol: number;
52
+ /** Hard iteration ceiling, so a non-converging step still terminates. */
53
+ maxIter: number;
54
+ }
55
+
56
+ /** Evaluate a symbolic EXPRESSION at a binding of its free variable, returning a
57
+ * plain number, or null when the expression cannot be evaluated (unparseable,
58
+ * or no evaluator wired in). This is the bridge that lets a NUMERICAL op act
59
+ * on a function: an integral, a derivative, a limit (or any refinement) needs
60
+ * to sample its integrand/argument at many points, and the integrand is itself
61
+ * a sub-expression with a free variable — evaluating it is a RECURSIVE
62
+ * application of the same ALU. Injected by the host (the {@link
63
+ * "./alu.js".Alu} facade); absent in a bare registry, where expression-ops
64
+ * simply decline. */
65
+ export type EvalExpr = (
66
+ bytes: Uint8Array,
67
+ variable: string,
68
+ at: number,
69
+ ) => number | null;
70
+
71
+ /** The context a callback runs in: the means to call sibling ops by name, the
72
+ * runtime knobs, pre-resolved resonance, and (when wired) an expression
73
+ * evaluator. This is what makes derivations compose without import cycles
74
+ * between kernel files. */
75
+ export interface OpContext {
76
+ /** Apply another registered op by canonical name. */
77
+ apply(name: string, args: Value[]): Value;
78
+ /** Whether an op is registered (lets a derivation pick a fast path when an
79
+ * optional sibling exists). */
80
+ has(name: string): boolean;
81
+ /** Resolve an operation-denoting VALUE to a canonical op name — the
82
+ * intelligent callback resolution the higher-order nd ops (map/reduce/filter/
83
+ * find) use for their FUNCTION ARGUMENT. An operation is named the SAME way
84
+ * any operation is recognised anywhere in the kernel, reusing the existing
85
+ * machinery rather than a bespoke table:
86
+ *
87
+ * 1. a literal SURFACE FORM — the op-value's bytes are a registered spelling
88
+ * ("+", "plus", "add", "*", "max", …) → the registry's own form index;
89
+ * 2. else its MEANING — {@link ResonanceSync.recogniseOp} over the same
90
+ * operation concepts, so a synonym or a multimodal gesture the bytes do
91
+ * not literally spell still resolves (pre-resolved by the host);
92
+ * 3. else a bare canonical NAME already (a symbol whose bytes equal an op
93
+ * name), or an int/bit treated as its decimal name — last resort.
94
+ *
95
+ * `arity` (when given) disambiguates a surface a unary and a binary op share
96
+ * (e.g. "-" is both negate and subtract): the claimant of that arity wins.
97
+ * Returns null when nothing resolves, so a higher-order op declines. */
98
+ resolveOp(op: Value, arity?: number): string | null;
99
+ /** The numerical runtime knobs. */
100
+ rt: OpRuntime;
101
+ /** Pre-resolved resonance for the polymorphic inverse and op recognition. */
102
+ resonance: ResonanceSync;
103
+ /** Evaluate a symbolic expression at a variable binding (see {@link
104
+ * EvalExpr}); undefined in a bare registry with no host evaluator. */
105
+ evalExpr?: EvalExpr;
106
+ }
107
+
108
+ /** The callback that executes an operation on resolved operands. */
109
+ export type OpFn = (args: Value[], ctx: OpContext) => Value;
110
+
111
+ /** How tightly an INFIX operation binds, and to which side — declared at
112
+ * registration, next to the op it describes, so the expression grammar is
113
+ * read off the registry rather than hardcoded in any parser. Higher
114
+ * `precedence` binds tighter. */
115
+ export interface InfixSyntax {
116
+ precedence: number;
117
+ rightAssoc?: boolean;
118
+ }
119
+
120
+ /** Optional syntactic/structure traits of an operation, declared where the op
121
+ * is registered. Every parser-facing distinction the ALU makes is one of
122
+ * these traits — there is no side table of names anywhere. */
123
+ export interface OpTraits {
124
+ /** Consumes an n-dimensional value WHOLE (exempt from broadcast). */
125
+ structural?: boolean;
126
+ /** Usable as an infix operator, with the given binding. */
127
+ infix?: InfixSyntax;
128
+ /** The FIRST operand is an EXPRESSION (a function's bytes) rather than a
129
+ * value; the remaining `arity − 1` operands are its points/bounds. The
130
+ * numerical layer's diff/integrate/solve/limit/optimize declare this. */
131
+ expression?: boolean;
132
+ }
133
+
134
+ /** An operation — primitive or derived, indistinguishable by type. */
135
+ export interface Operation extends OpTraits {
136
+ /** Canonical id, e.g. "add", "nand", "converge", "sin". */
137
+ name: string;
138
+ /** Operand count (fixed) or "variadic". */
139
+ arity: Arity;
140
+ /** True only for the kernel's irreducible roots. */
141
+ primitive: boolean;
142
+ /** Surface forms this op answers to — the spellings resonance maps to it,
143
+ * e.g. add ← ["+", "plus", "sum", "add"]. May be empty for an internal op
144
+ * that has no user-facing surface. */
145
+ forms: string[];
146
+ /** The callback. */
147
+ fn: OpFn;
148
+ }
149
+
150
+ /** A resonance that knows nothing — the default when no host is wired in, so
151
+ * the pure kernel and its tests run with zero coupling. Op recognition then
152
+ * falls back to literal surface forms / canonical names only. */
153
+ export const NO_RESONANCE: ResonanceSync = {
154
+ opposite: () => null,
155
+ recogniseOp: () => null,
156
+ };
157
+
158
+ /** The collection of operations, indexed by canonical name and by surface form.
159
+ * Building a kernel is a sequence of {@link prim}/{@link derive} calls; the
160
+ * registry then resolves names at apply time, so registration order need only
161
+ * respect the dependency DAG loosely (a derived op may reference an op
162
+ * registered later, since resolution is lazy). */
163
+ export class OperationRegistry {
164
+ private readonly ops = new Map<string, Operation>();
165
+ /** Surface form → the canonical names that claim it. A form may be shared
166
+ * (e.g. "-" is both subtract and negate); the caller disambiguates by arity
167
+ * and position, so the index keeps every claimant. */
168
+ private readonly formIndex = new Map<string, string[]>();
169
+
170
+ /** Register an operation record directly. */
171
+ register(op: Operation): void {
172
+ this.ops.set(op.name, op);
173
+ for (const f of op.forms) {
174
+ const a = this.formIndex.get(f);
175
+ if (a) {
176
+ if (!a.includes(op.name)) a.push(op.name);
177
+ } else this.formIndex.set(f, [op.name]);
178
+ }
179
+ }
180
+
181
+ /** Register a PRIMITIVE op (hand-written callback), with optional {@link
182
+ * OpTraits} — structural (consumes an nd whole, exempt from broadcast),
183
+ * infix binding, expression-operand — declared here, next to the op. */
184
+ prim(
185
+ name: string,
186
+ arity: Arity,
187
+ forms: string[],
188
+ fn: OpFn,
189
+ traits: OpTraits = {},
190
+ ): void {
191
+ this.register({ name, arity, primitive: true, forms, fn, ...traits });
192
+ }
193
+
194
+ /** Register a DERIVED op (callback composes other ops via ctx). `traits`
195
+ * as in {@link prim}. */
196
+ derive(
197
+ name: string,
198
+ arity: Arity,
199
+ forms: string[],
200
+ fn: OpFn,
201
+ traits: OpTraits = {},
202
+ ): void {
203
+ this.register({ name, arity, primitive: false, forms, fn, ...traits });
204
+ }
205
+
206
+ /** The op with this canonical name, or undefined. */
207
+ get(name: string): Operation | undefined {
208
+ return this.ops.get(name);
209
+ }
210
+
211
+ has(name: string): boolean {
212
+ return this.ops.has(name);
213
+ }
214
+
215
+ /** The canonical names a surface form maps to (empty if none). Several ops
216
+ * can share one surface (unary vs binary "-"), so this returns all. */
217
+ lookupForm(form: string): readonly string[] {
218
+ return this.formIndex.get(form) ?? [];
219
+ }
220
+
221
+ /** Every (surface form → canonical name) pair — the host enumerates these to
222
+ * seed its operator recogniser. */
223
+ *formEntries(): Iterable<{ form: string; name: string }> {
224
+ for (const [form, names] of this.formIndex) {
225
+ for (const name of names) yield { form, name };
226
+ }
227
+ }
228
+
229
+ /** Every registered canonical name. */
230
+ names(): Iterable<string> {
231
+ return this.ops.keys();
232
+ }
233
+
234
+ /** Build a context bound to a resonance and runtime — the object derived
235
+ * callbacks call back into. `apply` validates arity-vs-presence and surfaces
236
+ * a clear error rather than letting an undefined op silently produce NaN.
237
+ * An optional expression evaluator lets the numerical layer act on functions
238
+ * (see {@link EvalExpr}). */
239
+ context(
240
+ resonance: ResonanceSync,
241
+ rt: OpRuntime,
242
+ evalExpr?: EvalExpr,
243
+ ): OpContext {
244
+ const self = this;
245
+ const ctx: OpContext = {
246
+ rt,
247
+ resonance,
248
+ evalExpr,
249
+ has: (name) => self.ops.has(name),
250
+ resolveOp: (op: Value, arity?: number) =>
251
+ self.resolveOp(op, resonance, arity),
252
+ apply(name: string, args: Value[]): Value {
253
+ const op = self.ops.get(name);
254
+ if (!op) throw new Error(`ALU: unknown operation "${name}"`);
255
+ // ── ELEMENT-WISE BROADCAST ────────────────────────────────────────
256
+ // A SCALAR op (non-structural) applied to an n-dimensional argument
257
+ // lifts over it: the op runs on each element and the results re-pack
258
+ // into an nd of the same shape. This is the ONE place "every operation
259
+ // supports nd" is implemented — add, sin, nand, the polymorphic inverse
260
+ // all broadcast for free, and because each element re-enters `apply`,
261
+ // NESTING recurses (an nd of nd lifts twice) with no extra code.
262
+ //
263
+ // • several nd args ZIP position-wise (their top-level lengths must
264
+ // agree); a scalar arg is held constant against the list — so
265
+ // add([1,2,3],[4,5,6]) = [5,7,9] and add([1,2,3], 10) = [11,12,13].
266
+ // • a structural op is exempt: it wants the whole list (a reduce
267
+ // cannot be lifted across the very elements it folds).
268
+ if (!op.structural && args.some(isNd)) {
269
+ let len = -1;
270
+ for (const a of args) {
271
+ if (!isNd(a)) continue;
272
+ if (len === -1) len = a.items.length;
273
+ else if (a.items.length !== len) {
274
+ throw new Error(
275
+ `ALU: cannot broadcast "${name}" over lists of unequal length ` +
276
+ `(${len} vs ${a.items.length})`,
277
+ );
278
+ }
279
+ }
280
+ const out: Value[] = [];
281
+ for (let i = 0; i < len; i++) {
282
+ out.push(
283
+ ctx.apply(name, args.map((a) => isNd(a) ? a.items[i] : a)),
284
+ );
285
+ }
286
+ return nd(out);
287
+ }
288
+ if (op.arity !== "variadic" && args.length !== op.arity) {
289
+ throw new Error(
290
+ `ALU: "${name}" expects ${op.arity} operand(s), got ${args.length}`,
291
+ );
292
+ }
293
+ return op.fn(args, ctx);
294
+ },
295
+ };
296
+ return ctx;
297
+ }
298
+
299
+ /** Resolve an operation-denoting value to a canonical op name — the shared
300
+ * machinery behind {@link OpContext.resolveOp}. Tries, in order: a literal
301
+ * surface form (the registry's own index, arity-disambiguated), the meaning
302
+ * via `resonance.recogniseOp`, then a bare canonical name / decimal reading.
303
+ * Returns null when nothing resolves. Static-shaped (takes the resonance
304
+ * explicitly) so both the context closure and callers can use it. */
305
+ resolveOp(
306
+ op: Value,
307
+ resonance: ResonanceSync,
308
+ arity?: number,
309
+ ): string | null {
310
+ // The op-value's surface text, if it has a byte reading.
311
+ let text: string | null = null;
312
+ if (op.domain === "symbol") {
313
+ let s = "";
314
+ for (let i = 0; i < op.bytes.length; i++) {
315
+ s += String.fromCharCode(op.bytes[i]);
316
+ }
317
+ text = s.trim();
318
+ } else if (op.domain === "int") text = op.n.toString();
319
+ else if (op.domain === "bit") text = String(op.b);
320
+ if (text === null || text.length === 0) return null;
321
+
322
+ // (1) a literal SURFACE FORM, arity-disambiguated when asked.
323
+ const claimants = this.formIndex.get(text);
324
+ if (claimants && claimants.length > 0) {
325
+ if (arity !== undefined) {
326
+ for (const n of claimants) {
327
+ const o = this.ops.get(n);
328
+ const a = o && (o.arity === "variadic" ? 2 : o.arity);
329
+ if (a === arity) return n;
330
+ }
331
+ }
332
+ return claimants[0];
333
+ }
334
+ // (2) the MEANING, via pre-resolved resonance (synonym / multimodal gesture
335
+ // the bytes do not literally spell) — only a symbol carries meaning.
336
+ if (op.domain === "symbol") {
337
+ const byMeaning = resonance.recogniseOp(op.bytes);
338
+ if (byMeaning && this.ops.has(byMeaning)) return byMeaning;
339
+ }
340
+ // (3) a bare canonical NAME already registered.
341
+ if (this.ops.has(text)) return text;
342
+ return null;
343
+ }
344
+ }