@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.
- package/AGENTS.md +470 -0
- package/AUTHORS.md +12 -0
- package/COMMERCIAL-LICENSE.md +19 -0
- package/CONTRIBUTING.md +15 -0
- package/HOW_IT_WORKS.md +4210 -0
- package/LICENSE.md +117 -0
- package/README.md +290 -0
- package/TRADEMARKS.md +19 -0
- package/example/demo.ts +46 -0
- package/example/train_base.ts +2675 -0
- package/index.html +893 -0
- package/package.json +25 -0
- package/src/alphabet.ts +34 -0
- package/src/alu/README.md +332 -0
- package/src/alu/src/alu.ts +541 -0
- package/src/alu/src/expr.ts +339 -0
- package/src/alu/src/index.ts +115 -0
- package/src/alu/src/kernel-arith.ts +377 -0
- package/src/alu/src/kernel-bits.ts +199 -0
- package/src/alu/src/kernel-logic.ts +102 -0
- package/src/alu/src/kernel-nd.ts +235 -0
- package/src/alu/src/kernel-numeric.ts +466 -0
- package/src/alu/src/operation.ts +344 -0
- package/src/alu/src/parser.ts +574 -0
- package/src/alu/src/resonance.ts +161 -0
- package/src/alu/src/text.ts +83 -0
- package/src/alu/src/value.ts +327 -0
- package/src/alu/test/alu.test.ts +1004 -0
- package/src/bytes.ts +62 -0
- package/src/config.ts +227 -0
- package/src/derive/README.md +295 -0
- package/src/derive/src/deduction.ts +263 -0
- package/src/derive/src/index.ts +24 -0
- package/src/derive/src/priority-queue.ts +70 -0
- package/src/derive/src/rewrite.ts +127 -0
- package/src/derive/src/trie.ts +242 -0
- package/src/derive/test/derive.test.ts +137 -0
- package/src/extension.ts +42 -0
- package/src/geometry.ts +511 -0
- package/src/index.ts +38 -0
- package/src/ingest-cache.ts +224 -0
- package/src/mind/articulation.ts +137 -0
- package/src/mind/attention.ts +1061 -0
- package/src/mind/canonical.ts +107 -0
- package/src/mind/graph-search.ts +1100 -0
- package/src/mind/index.ts +18 -0
- package/src/mind/junction.ts +347 -0
- package/src/mind/learning.ts +246 -0
- package/src/mind/match.ts +507 -0
- package/src/mind/mechanisms/alu.ts +33 -0
- package/src/mind/mechanisms/cast.ts +568 -0
- package/src/mind/mechanisms/confluence.ts +268 -0
- package/src/mind/mechanisms/cover.ts +248 -0
- package/src/mind/mechanisms/extraction.ts +422 -0
- package/src/mind/mechanisms/recall.ts +241 -0
- package/src/mind/mind.ts +483 -0
- package/src/mind/pipeline-mechanism.ts +326 -0
- package/src/mind/pipeline.ts +300 -0
- package/src/mind/primitives.ts +201 -0
- package/src/mind/rationale.ts +275 -0
- package/src/mind/reasoning.ts +198 -0
- package/src/mind/recognition.ts +234 -0
- package/src/mind/resonance.ts +0 -0
- package/src/mind/trace.ts +108 -0
- package/src/mind/traverse.ts +556 -0
- package/src/mind/types.ts +281 -0
- package/src/rabitq-hnsw/README.md +303 -0
- package/src/rabitq-hnsw/src/database.ts +492 -0
- package/src/rabitq-hnsw/src/heap.ts +90 -0
- package/src/rabitq-hnsw/src/hnsw.ts +514 -0
- package/src/rabitq-hnsw/src/index.ts +15 -0
- package/src/rabitq-hnsw/src/prng.ts +39 -0
- package/src/rabitq-hnsw/src/rabitq.ts +308 -0
- package/src/rabitq-hnsw/src/store.ts +994 -0
- package/src/rabitq-hnsw/test/hnsw.test.ts +1213 -0
- package/src/store-sqlite.ts +928 -0
- package/src/store.ts +2148 -0
- package/src/vec.ts +124 -0
- package/test/00-extract.test.mjs +151 -0
- package/test/01-floor.test.mjs +20 -0
- package/test/02-roundtrip.test.mjs +83 -0
- package/test/03-recall.test.mjs +98 -0
- package/test/04-think.test.mjs +627 -0
- package/test/05-concepts.test.mjs +84 -0
- package/test/08-storage.test.mjs +948 -0
- package/test/09-edges.test.mjs +65 -0
- package/test/11-universality.test.mjs +180 -0
- package/test/13-conversation.test.mjs +228 -0
- package/test/14-scaling.test.mjs +503 -0
- package/test/15-decomposition-gap.test.mjs +0 -0
- package/test/16-bridge.test.mjs +250 -0
- package/test/17-intelligence.test.mjs +240 -0
- package/test/18-alu.test.mjs +209 -0
- package/test/19-nd.test.mjs +254 -0
- package/test/20-stability.test.mjs +489 -0
- package/test/21-partial.test.mjs +158 -0
- package/test/22-multihop.test.mjs +130 -0
- package/test/23-rationale.test.mjs +316 -0
- package/test/24-generalization.test.mjs +416 -0
- package/test/25-embedding.test.mjs +75 -0
- package/test/26-cooperative.test.mjs +89 -0
- package/test/27-saturation-drop.test.mjs +637 -0
- package/test/28-unknowable.test.mjs +88 -0
- package/test/29-counterfactual.test.mjs +476 -0
- package/test/30-conflict-resolution.test.mjs +166 -0
- package/test/31-audit.test.mjs +288 -0
- package/test/32-confluence.test.mjs +173 -0
- package/test/33-multi-candidate.test.mjs +222 -0
- package/test/34-cross-region.test.mjs +252 -0
- package/tsconfig.json +16 -0
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hviana/sema",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "An elementary, recursive, weight-free multimodal mind: one structure, two verbs, one memory. Zero runtime dependencies, pure web standards.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/src/index.js",
|
|
7
|
+
"types": "dist/src/index.d.ts",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "tsc",
|
|
10
|
+
"demo": "tsc && node dist/example/demo.js",
|
|
11
|
+
"test": "tsc && node --test test/**/*.test.mjs"
|
|
12
|
+
},
|
|
13
|
+
"license": "PolyForm-Noncommercial-1.0.0",
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@types/node": "^25.9.3",
|
|
16
|
+
"typescript": "^5.5.0"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"hyparquet": "^1.26.2",
|
|
20
|
+
"hyparquet-compressors": "^1.1.1"
|
|
21
|
+
},
|
|
22
|
+
"publishConfig": {
|
|
23
|
+
"access": "public"
|
|
24
|
+
}
|
|
25
|
+
}
|
package/src/alphabet.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// alphabet.ts — the byte→vector mapping.
|
|
2
|
+
//
|
|
3
|
+
// 256 unit vectors, one per byte value, built by recursive refinement:
|
|
4
|
+
// 16 coarse directions → 64 mids → 256 fines. Same-fine neighbours
|
|
5
|
+
// resonate; far-apart values are quasi-orthogonal.
|
|
6
|
+
|
|
7
|
+
import { addInto, copy, normalize, randomUnit, rng, Vec } from "./vec.js";
|
|
8
|
+
import type { AlphabetConfig } from "./config.js";
|
|
9
|
+
|
|
10
|
+
export class Alphabet {
|
|
11
|
+
readonly vecs: Vec[] = [];
|
|
12
|
+
readonly config: AlphabetConfig;
|
|
13
|
+
|
|
14
|
+
constructor(seed: number, D: number, config?: Partial<AlphabetConfig>) {
|
|
15
|
+
this.config = {
|
|
16
|
+
roughness: config?.roughness ?? 0.65,
|
|
17
|
+
seedMask: config?.seedMask ?? 0xa1fa17,
|
|
18
|
+
};
|
|
19
|
+
const rand = rng((seed ^ this.config.seedMask) >>> 0);
|
|
20
|
+
const refine = (parent: Vec): Vec => {
|
|
21
|
+
const v = copy(parent);
|
|
22
|
+
for (let i = 0; i < v.length; i++) {
|
|
23
|
+
v[i] *= Math.sqrt(1 - this.config.roughness);
|
|
24
|
+
}
|
|
25
|
+
addInto(v, randomUnit(D, rand), Math.sqrt(this.config.roughness));
|
|
26
|
+
return normalize(v);
|
|
27
|
+
};
|
|
28
|
+
const coarse: Vec[] = [];
|
|
29
|
+
for (let i = 0; i < 16; i++) coarse.push(randomUnit(D, rand));
|
|
30
|
+
const mid: Vec[] = [];
|
|
31
|
+
for (let i = 0; i < 64; i++) mid.push(refine(coarse[i >> 2]));
|
|
32
|
+
for (let b = 0; b < 256; b++) this.vecs.push(refine(mid[b >> 2]));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
# alu
|
|
2
|
+
|
|
3
|
+
A small, dependency-free **ALU**: a tiny irreducible kernel from which
|
|
4
|
+
arithmetic, logical, and numerical computation are all _derived_. It is the
|
|
5
|
+
manual-rules counterpart to `derive`'s learned rules — the operations a mind
|
|
6
|
+
should not have to learn one number at a time (how to add 2 and 2, how to negate
|
|
7
|
+
a truth value) are declared here once.
|
|
8
|
+
|
|
9
|
+
It joins the mind as a `PipelineMechanism`
|
|
10
|
+
([`../mind/pipeline-mechanism.ts`](../mind/pipeline-mechanism.ts)) whose only
|
|
11
|
+
special role is the optional `parse(query)` method every mechanism may
|
|
12
|
+
implement. The mind knows nothing about what the ALU computes; it only knows
|
|
13
|
+
that `parse` returns `ComputedSpan[]`, which enter the one lightest-derivation
|
|
14
|
+
search as authoritative axioms (at `STEP` cost, like a learned edge).
|
|
15
|
+
|
|
16
|
+
It has no dependency on the rest of the codebase except the pure byte helpers in
|
|
17
|
+
`../bytes.ts`, and is intended to be reused as a self-contained sublibrary in
|
|
18
|
+
the spirit of `derive/` and `rabitq-hnsw/`.
|
|
19
|
+
|
|
20
|
+
## The thesis: one tiny kernel, everything else is a rewrite
|
|
21
|
+
|
|
22
|
+
Each stratum bootstraps the next, so the ALU only _declares_ the irreducible
|
|
23
|
+
primitive(s) of each layer; everything else is a derivation rule layered on top.
|
|
24
|
+
|
|
25
|
+
### 1. Logic — the completeness layer (`kernel-logic.ts`)
|
|
26
|
+
|
|
27
|
+
One primitive: **`nand`** (functionally complete on its own). `not`, `and`, `or`
|
|
28
|
+
are exposed for ergonomics but are themselves derived. Fully derived: `nor`,
|
|
29
|
+
`xor`, `xnor`, `implies`, `iff`, and **`mux(s, a, b)`** — the bridge to control
|
|
30
|
+
flow (conditional selection, and with recursion, looping).
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
not(a) = nand(a, a)
|
|
34
|
+
and(a, b) = not(nand(a, b))
|
|
35
|
+
or(a, b) = nand(not a, not b)
|
|
36
|
+
xor(a, b) = or(and(a, not b), and(not a, b))
|
|
37
|
+
mux(s, a, b) = or(and(not s, a), and(s, b))
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### 2. Arithmetic — the field-and-order layer (`kernel-arith.ts`, `kernel-bits.ts`)
|
|
41
|
+
|
|
42
|
+
Identities `0`, `1`; primitives `add`, `negate`, `multiply`, `reciprocal`,
|
|
43
|
+
`sign` (plus optional `floor` / `mod` for integer number theory). Derived:
|
|
44
|
+
`subtract = add ∘ negate`, `divide = multiply ∘ reciprocal`, every comparison
|
|
45
|
+
`= sign ∘ subtract`, then `abs`, `min`, `max`, `power`, `gcd`, and the array
|
|
46
|
+
routines `polyEval`, `dot`, `matMul`, `linsolve` (Gaussian elimination — just
|
|
47
|
+
structured arithmetic, _not_ a new primitive).
|
|
48
|
+
|
|
49
|
+
**The bit-vector bootstrap is exact and exercised.** `kernel-bits.ts` builds
|
|
50
|
+
`full_adder` from the `xor`/`and`/`or` of layer 1, and from it derives ripple
|
|
51
|
+
`add` → two's-complement `negate` → shift-add `multiply` → `sign` → `compare`,
|
|
52
|
+
all on exact `bigint`. This is the literal proof that "add … everything derives
|
|
53
|
+
from nand"; the tests cross-check each against native `bigint`. It runs under a
|
|
54
|
+
`bits.` namespace so it is a separately-testable _exhibit_, never silently the
|
|
55
|
+
substrate of a real-number computation.
|
|
56
|
+
|
|
57
|
+
The arithmetic primitives are **polymorphic over the numeric domains**: when all
|
|
58
|
+
operands are exact (`bit`/`int`) they run on `bigint` and agree with the
|
|
59
|
+
bootstrap; the moment a `real` appears the expression lifts to IEEE doubles,
|
|
60
|
+
which is what the limit layer needs.
|
|
61
|
+
|
|
62
|
+
### 3. Numerical — the limit layer (`kernel-numeric.ts`)
|
|
63
|
+
|
|
64
|
+
One primitive: **`converge(step, tol)`** — iterate a refinement until successive
|
|
65
|
+
results agree within ε. This is the _only_ thing that makes the engine numerical
|
|
66
|
+
rather than a classical (exact, finite) ALU. Exposed: `diff`, `integrate`,
|
|
67
|
+
`solve`; derived: `exp`, `log`, `sin`, `cos`, `sqrt`, `optimize`
|
|
68
|
+
(`= solve(diff
|
|
69
|
+
f)`), `odeSolve`, `regress` (`= linsolve` on the normal
|
|
70
|
+
equations), `interpolate`, `powerEig` / `topSingular` (power iteration
|
|
71
|
+
`= converge`).
|
|
72
|
+
|
|
73
|
+
### 4. N-dimensional — the list layer (`kernel-nd.ts`)
|
|
74
|
+
|
|
75
|
+
A value may also be an **`nd`**: an ordered list whose elements are _themselves_
|
|
76
|
+
values of any domain — a scalar, or another `nd`. That one recursive case is the
|
|
77
|
+
whole generalisation: a matrix is an `nd` of `nd`s, a ragged table is an `nd` of
|
|
78
|
+
unequal-length `nd`s, a heterogeneous row mixes a number, a symbol, and a
|
|
79
|
+
sub-list. There is no separate vector/matrix type and no new primitive per rank.
|
|
80
|
+
|
|
81
|
+
Three structural primitives — the only ops that touch a list's elements:
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
nd(a, b, …) pack operands into a list (construct)
|
|
85
|
+
length(xs) the top-level element count (measure)
|
|
86
|
+
at(xs, i) the i-th element, ±from end (project)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Everything else derives from those three plus the scalar kernels. The
|
|
90
|
+
higher-order ops take an **operation as their argument**, resolved by the _same_
|
|
91
|
+
machinery any operator is (a surface form, else its resonant meaning — see
|
|
92
|
+
`OpContext.resolveOp`), so the fold/transform/predicate is **any operation the
|
|
93
|
+
kernel already has**, never a bespoke table:
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
map(xs, f) = nd( f(at xs i) for i in 0…length xs )
|
|
97
|
+
filter(xs, p) = the elements where p holds
|
|
98
|
+
reduce(xs, f[,z]) = f(… f(f(z, at xs 0), at xs 1) …) reduce(xs,+)=sum, (xs,*)=product, (xs,max)=maximum
|
|
99
|
+
find(xs, p) = the first element where p holds, else the empty nd
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
plus `concat`, `reverse`, `flatten`, `zip`, `range`, `rank` (nesting depth),
|
|
103
|
+
`shape`. Because `reduce`'s `f(acc, elem)` re-enters `apply`, a `reduce(rows,+)`
|
|
104
|
+
broadcasts `+` over the row-lists — a column sum falls out, no matrix code.
|
|
105
|
+
|
|
106
|
+
## The irreducible kernel
|
|
107
|
+
|
|
108
|
+
- one gate — `nand`
|
|
109
|
+
- two identities + six ops — `0, 1, add, negate, multiply, reciprocal, sign` (+
|
|
110
|
+
optional `floor`/`mod`)
|
|
111
|
+
- one limit operator — `converge`
|
|
112
|
+
- three structural ops — `nd, length, at`
|
|
113
|
+
|
|
114
|
+
Everything else is a rewrite rule over those.
|
|
115
|
+
|
|
116
|
+
## Values: byte-native, multimodal, and n-dimensional
|
|
117
|
+
|
|
118
|
+
SEMA computes on bytes of any modality, so ALU's value is a tagged union
|
|
119
|
+
(`value.ts`) — four scalar domains plus the recursive container:
|
|
120
|
+
|
|
121
|
+
```ts
|
|
122
|
+
type Value =
|
|
123
|
+
| { domain: "bit"; b: 0 | 1 }
|
|
124
|
+
| { domain: "int"; n: bigint }
|
|
125
|
+
| { domain: "real"; x: number }
|
|
126
|
+
| { domain: "symbol"; bytes: Uint8Array }
|
|
127
|
+
| { domain: "nd"; items: Value[] }; // recursive: a list of any-domain values
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
A **`symbol`** is an opaque byte span — text, an image region, an audio
|
|
131
|
+
fragment, any learned form. ALU never interprets it; it is the carrier for the
|
|
132
|
+
**polymorphic inverse**: the inverse of a number is its negation, but the
|
|
133
|
+
inverse of a symbol is its _resonant opposite_, found in the resonance space,
|
|
134
|
+
not by arithmetic. That single `inverse` op dispatches on the operand's domain —
|
|
135
|
+
so "the inverse of 3 is −3" and "the opposite of ‹a learned form› is ‹its
|
|
136
|
+
resonant opposite›" are one operation.
|
|
137
|
+
|
|
138
|
+
An **`nd`** is the recursive container above. The default codec spells it as a
|
|
139
|
+
bracket literal `[e0,e1,…]` (nestable, heterogeneous) that round-trips through
|
|
140
|
+
`parseValue`; a symbol element keeps its raw bytes, so a list of any modality
|
|
141
|
+
survives.
|
|
142
|
+
|
|
143
|
+
### Every operation supports `nd`, via one mechanism: **broadcast**
|
|
144
|
+
|
|
145
|
+
A scalar op applied to a list lifts over it element-wise, and because each
|
|
146
|
+
element re-enters `apply`, nesting recurses with no extra code — `add`, `sin`,
|
|
147
|
+
`nand`, and the polymorphic `inverse` all broadcast for free:
|
|
148
|
+
|
|
149
|
+
```
|
|
150
|
+
add([1,2,3], [4,5,6]) = [5,7,9] two lists zip
|
|
151
|
+
add([1,2,3], 10) = [11,12,13] a scalar is held constant
|
|
152
|
+
add([[1,2],[3,4]], …) recurses a matrix op is the same op
|
|
153
|
+
inverse([large,3,tall]) = [small,-3,short] numbers negate, symbols resonate
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
This is implemented in exactly one place (`OperationRegistry.context`). The list
|
|
157
|
+
layer's own ops are marked **structural** (broadcast-exempt) — a `reduce` must
|
|
158
|
+
see the whole list, not be lifted across the very elements it folds. The two
|
|
159
|
+
halves of "all operations support nd" — scalar ops broadcasting _down_ into
|
|
160
|
+
lists, structural ops consuming lists _whole_ — meet exactly there.
|
|
161
|
+
|
|
162
|
+
## How it joins the SEMA search
|
|
163
|
+
|
|
164
|
+
The ALU is completely decoupled from Sema. It joins the mind through
|
|
165
|
+
`aluToMechanism` ([`../mind/mechanisms/alu.ts`](../mind/mechanisms/alu.ts),
|
|
166
|
+
re-exported from [`../mind/pipeline.ts`](../mind/pipeline.ts)), a thin adapter
|
|
167
|
+
that wraps the ALU's `parse` in a `PipelineMechanism` — the same uniform
|
|
168
|
+
interface every grounding mechanism (CAST, confluence, cover, extraction,
|
|
169
|
+
recall) implements, so nothing about the ALU is special-cased in the pipeline.
|
|
170
|
+
|
|
171
|
+
### The contract
|
|
172
|
+
|
|
173
|
+
`PipelineMechanism`'s `parse` is the part the ALU actually uses:
|
|
174
|
+
|
|
175
|
+
```ts
|
|
176
|
+
interface PipelineMechanism {
|
|
177
|
+
parse?(query: Uint8Array): Promise<ComputedSpan[]>;
|
|
178
|
+
floor(ctx, query, pre): Promise<number | null>;
|
|
179
|
+
run(ctx, query, pre): Promise<MechanismResult[]>;
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
A `ComputedSpan` is `{ i, j, bytes }` — a half-open byte range and the
|
|
184
|
+
authoritative result bytes computed for it.
|
|
185
|
+
|
|
186
|
+
At construction, every extension factory receives an `ExtensionHost` — four
|
|
187
|
+
neutral capabilities the mind already has for its own purposes:
|
|
188
|
+
|
|
189
|
+
```ts
|
|
190
|
+
interface ExtensionHost {
|
|
191
|
+
meaningOf(
|
|
192
|
+
bytes: Uint8Array,
|
|
193
|
+
anchors: ReadonlyArray<{ name: string; form: Uint8Array }>,
|
|
194
|
+
): Promise<string | null>;
|
|
195
|
+
continuation(bytes: Uint8Array): Promise<Uint8Array | null>;
|
|
196
|
+
segment(bytes: Uint8Array): Array<{ i: number; j: number }>;
|
|
197
|
+
reach: number;
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
The host port knows nothing about ALU. The ALU adapts it into the specialised
|
|
202
|
+
`AluResonance` ([`resonance.ts`](src/resonance.ts)) it needs:
|
|
203
|
+
|
|
204
|
+
- `meaningOf` → `recogniseOp` — which registered operation does a span mean?
|
|
205
|
+
- `continuation` → `opposite` — the polymorphic inverse of a symbol
|
|
206
|
+
|
|
207
|
+
### The parser
|
|
208
|
+
|
|
209
|
+
The `QueryParser` ([`parser.ts`](src/parser.ts)) scans the raw query bytes for
|
|
210
|
+
two kinds of computation:
|
|
211
|
+
|
|
212
|
+
**Infix arithmetic** — literal numbers and symbolic operators (`"2+3*4"`). The
|
|
213
|
+
parser uses an expression grammar with precedence climbing
|
|
214
|
+
([`expr.ts`](src/expr.ts)) and byte-class constants ([`text.ts`](src/text.ts))
|
|
215
|
+
that are independent of the river's content-defined chunking, so a multi-digit
|
|
216
|
+
number the river would split across groups is still read whole. Each run is
|
|
217
|
+
evaluated through the kernel and emitted as a `ComputedSpan`.
|
|
218
|
+
|
|
219
|
+
**Operations by meaning** — a term may name an operation not by a literal
|
|
220
|
+
surface form (`"sqrt"`) but by _resonance_: its gist lands on a learned concept
|
|
221
|
+
anchor that was registered as an operation's meaning. This is the only path that
|
|
222
|
+
needs the host. The ALU also carries a `STRUCTURAL_HOST` constant — a host that
|
|
223
|
+
knows nothing beyond structure (whitespace-only segmentation, unbounded reach,
|
|
224
|
+
no resonance). Without a real host, the parser still reads literal notation;
|
|
225
|
+
only meaning-based paths stay silent.
|
|
226
|
+
|
|
227
|
+
### Pre-resolution — async to sync
|
|
228
|
+
|
|
229
|
+
Two of the parser's needs are asynchronous in Sema (they hit the resonance
|
|
230
|
+
index): recognising an operation by meaning, and finding the polymorphic inverse
|
|
231
|
+
of a symbol. The ALU uses the same async-to-sync prefetch pattern that the mind
|
|
232
|
+
uses for concept hops:
|
|
233
|
+
|
|
234
|
+
```ts
|
|
235
|
+
const sync = await prefetchResonance(resonance, spans);
|
|
236
|
+
// sync.ops: Map<bytes, OperationRecord> — operation by meaning
|
|
237
|
+
// sync.syms: Map<bytes, Uint8Array> — symbolic inverses
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
The synchronous op callbacks never await — they read from the pre-resolved
|
|
241
|
+
snapshots. The public `Mind.compute(name, operands)` path pre-resolves every
|
|
242
|
+
symbol span before the synchronous kernel runs, using the same discipline.
|
|
243
|
+
|
|
244
|
+
### The mind loop
|
|
245
|
+
|
|
246
|
+
`think()` collects every mechanism's `parse` result before the grounding loop
|
|
247
|
+
runs:
|
|
248
|
+
|
|
249
|
+
```ts
|
|
250
|
+
for (const m of mechanisms) {
|
|
251
|
+
if (m.parse) out.push(...await m.parse(query));
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
Each result is grounded into an `Out` item with `rec = true` (authoritative,
|
|
256
|
+
like a learned edge) at `STEP` cost. Then — crucially — any recognised site
|
|
257
|
+
whose span overlaps a computed span is **masked** before the search. This is the
|
|
258
|
+
"computation always wins" policy: a deliberately-trained `2+2 → 5` is masked;
|
|
259
|
+
the computed `4` is the cover's sole completion there. The search itself stays a
|
|
260
|
+
neutral cost engine (a computed `Out` and a learned edge both cost `STEP`);
|
|
261
|
+
precedence lives entirely in the masking step, which is in
|
|
262
|
+
`src/mind/pipeline.ts`, not in the search and not in the ALU.
|
|
263
|
+
|
|
264
|
+
A computation and an _unrelated_ rewrite still compose in one answer
|
|
265
|
+
(`"ice 2+2"` → `"cold 4"`) because the masking is scoped to the colliding span
|
|
266
|
+
only.
|
|
267
|
+
|
|
268
|
+
### The complete decoupling
|
|
269
|
+
|
|
270
|
+
```
|
|
271
|
+
src/mind/mind.ts alu/
|
|
272
|
+
└── mechanisms: PipelineMechanism[]
|
|
273
|
+
└── parse(query) ← the part the ALU uses
|
|
274
|
+
↑ aluToMechanism(alu) wraps
|
|
275
|
+
Alu ← plain class, no mechanism shape
|
|
276
|
+
↑ receives at construction
|
|
277
|
+
ExtensionHost port ← 4 neutral capabilities
|
|
278
|
+
↑ mind.extensionHost()
|
|
279
|
+
AluResonance adapter ← specialised reading
|
|
280
|
+
↑ parser.ts QueryParser
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
The ALU imports nothing from the mind except `../../bytes.js`. The mind imports
|
|
284
|
+
nothing from the ALU beyond its `Alu` class and the `PipelineMechanism`
|
|
285
|
+
contract. Each remains independently testable (the ALU test suite runs with zero
|
|
286
|
+
Sema dependency) and replaceable. A user-supplied extension — a CAS, a type
|
|
287
|
+
checker, a domain-specific solver — joins through the same `mechanismFactories`
|
|
288
|
+
hook (`MindOptions.mechanismFactories`), receives the same host port, and its
|
|
289
|
+
computed spans mask recall with the same precedence.
|
|
290
|
+
|
|
291
|
+
## Adding an operation
|
|
292
|
+
|
|
293
|
+
One declarative call, in the relevant kernel file or by the host:
|
|
294
|
+
|
|
295
|
+
```ts
|
|
296
|
+
registry.derive("hypot", 2, ["hypot"], (args, ctx) =>
|
|
297
|
+
ctx.apply("sqrt", [
|
|
298
|
+
ctx.apply("add", [
|
|
299
|
+
ctx.apply("multiply", [args[0], args[0]]),
|
|
300
|
+
ctx.apply("multiply", [args[1], args[1]]),
|
|
301
|
+
]),
|
|
302
|
+
]));
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
No kernel edit, no graph-search edit, no resonance edit — name it, list its
|
|
306
|
+
surface forms, write the body in terms of existing ops. A scalar op broadcasts
|
|
307
|
+
over `nd` automatically; pass `structural = true` (the trailing flag on
|
|
308
|
+
`prim`/`derive`) only for an op that consumes a list _whole_, like the `nd`
|
|
309
|
+
kernel's own.
|
|
310
|
+
|
|
311
|
+
## Layout
|
|
312
|
+
|
|
313
|
+
```
|
|
314
|
+
alu/
|
|
315
|
+
├── README.md this file
|
|
316
|
+
├── src/
|
|
317
|
+
│ ├── value.ts the Value union, parse, the byte⇄value codec
|
|
318
|
+
│ ├── operation.ts the Operation record + registry (derivations compose by name)
|
|
319
|
+
│ ├── parser.ts QueryParser: lexer, infix arithmetic, operation-by-meaning
|
|
320
|
+
│ ├── expr.ts expression grammar (precedence climbing), tokenizer
|
|
321
|
+
│ ├── text.ts byte-class constants (digit, whitespace, bracket, etc.)
|
|
322
|
+
│ ├── resonance.ts AluResonance (host-injected) + the async→sync prefetch
|
|
323
|
+
│ ├── kernel-logic.ts nand → not/and/or/nor/xor/xnor/implies/iff/mux
|
|
324
|
+
│ ├── kernel-bits.ts the exact full_adder→add→multiply bootstrap (bigint)
|
|
325
|
+
│ ├── kernel-arith.ts identities + add/negate/multiply/reciprocal/sign + derived
|
|
326
|
+
│ ├── kernel-numeric.ts converge → diff/integrate/solve → exp/log/sin/cos/sqrt/…
|
|
327
|
+
│ ├── kernel-nd.ts nd/length/at → map/reduce/filter/find/concat/zip/rank/shape
|
|
328
|
+
│ ├── alu.ts the assembled Alu: exposes parse(), owns the parser
|
|
329
|
+
│ └── index.ts public surface
|
|
330
|
+
└── test/
|
|
331
|
+
└── alu.test.ts self-contained tests (no Sema dependency)
|
|
332
|
+
```
|