@hviana/sema 0.4.2 → 0.4.4

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 (135) hide show
  1. package/dist/example/demo.d.ts +1 -0
  2. package/dist/example/demo.js +39 -0
  3. package/dist/example/train_base.d.ts +87 -0
  4. package/dist/example/train_base.js +2252 -0
  5. package/dist/src/alphabet.d.ts +7 -0
  6. package/dist/src/alphabet.js +33 -0
  7. package/dist/src/alu/src/alu.d.ts +185 -0
  8. package/dist/src/alu/src/alu.js +440 -0
  9. package/dist/src/alu/src/expr.d.ts +61 -0
  10. package/dist/src/alu/src/expr.js +318 -0
  11. package/dist/src/alu/src/index.d.ts +11 -0
  12. package/dist/src/alu/src/index.js +19 -0
  13. package/dist/src/alu/src/kernel-arith.d.ts +16 -0
  14. package/dist/src/alu/src/kernel-arith.js +264 -0
  15. package/dist/src/alu/src/kernel-bits.d.ts +19 -0
  16. package/dist/src/alu/src/kernel-bits.js +152 -0
  17. package/dist/src/alu/src/kernel-logic.d.ts +4 -0
  18. package/dist/src/alu/src/kernel-logic.js +60 -0
  19. package/dist/src/alu/src/kernel-nd.d.ts +3 -0
  20. package/dist/src/alu/src/kernel-nd.js +208 -0
  21. package/dist/src/alu/src/kernel-numeric.d.ts +54 -0
  22. package/dist/src/alu/src/kernel-numeric.js +366 -0
  23. package/dist/src/alu/src/operation.d.ts +168 -0
  24. package/dist/src/alu/src/operation.js +189 -0
  25. package/dist/src/alu/src/parser.d.ts +221 -0
  26. package/dist/src/alu/src/parser.js +577 -0
  27. package/dist/src/alu/src/resonance.d.ts +55 -0
  28. package/dist/src/alu/src/resonance.js +126 -0
  29. package/dist/src/alu/src/text.d.ts +31 -0
  30. package/dist/src/alu/src/text.js +73 -0
  31. package/dist/src/alu/src/value.d.ts +109 -0
  32. package/dist/src/alu/src/value.js +300 -0
  33. package/dist/src/alu/test/alu.test.d.ts +1 -0
  34. package/dist/src/alu/test/alu.test.js +764 -0
  35. package/dist/src/bytes.d.ts +14 -0
  36. package/dist/src/bytes.js +59 -0
  37. package/dist/src/canon.d.ts +26 -0
  38. package/dist/src/canon.js +57 -0
  39. package/dist/src/config.d.ts +111 -0
  40. package/dist/src/config.js +91 -0
  41. package/dist/src/derive/src/deduction.d.ts +136 -0
  42. package/dist/src/derive/src/deduction.js +159 -0
  43. package/dist/src/derive/src/index.d.ts +8 -0
  44. package/dist/src/derive/src/index.js +11 -0
  45. package/dist/src/derive/src/priority-queue.d.ts +20 -0
  46. package/dist/src/derive/src/priority-queue.js +73 -0
  47. package/dist/src/derive/src/rewrite.d.ts +56 -0
  48. package/dist/src/derive/src/rewrite.js +100 -0
  49. package/dist/src/derive/src/trie.d.ts +90 -0
  50. package/dist/src/derive/src/trie.js +217 -0
  51. package/dist/src/derive/test/derive.test.d.ts +1 -0
  52. package/dist/src/derive/test/derive.test.js +122 -0
  53. package/dist/src/extension.d.ts +37 -0
  54. package/dist/src/extension.js +7 -0
  55. package/dist/src/geometry.d.ts +175 -0
  56. package/dist/src/geometry.js +823 -0
  57. package/dist/src/index.d.ts +17 -0
  58. package/dist/src/index.js +19 -0
  59. package/dist/src/ingest-cache.d.ts +41 -0
  60. package/dist/src/ingest-cache.js +165 -0
  61. package/dist/src/meter.d.ts +176 -0
  62. package/dist/src/meter.js +274 -0
  63. package/dist/src/mind/articulation.d.ts +6 -0
  64. package/dist/src/mind/articulation.js +99 -0
  65. package/dist/src/mind/attention.d.ts +414 -0
  66. package/dist/src/mind/attention.js +2082 -0
  67. package/dist/src/mind/bridge.d.ts +39 -0
  68. package/dist/src/mind/bridge.js +972 -0
  69. package/dist/src/mind/canonical.d.ts +34 -0
  70. package/dist/src/mind/canonical.js +93 -0
  71. package/dist/src/mind/graph-search.d.ts +294 -0
  72. package/dist/src/mind/graph-search.js +996 -0
  73. package/dist/src/mind/index.d.ts +9 -0
  74. package/dist/src/mind/index.js +5 -0
  75. package/dist/src/mind/junction.d.ts +137 -0
  76. package/dist/src/mind/junction.js +342 -0
  77. package/dist/src/mind/learning.d.ts +75 -0
  78. package/dist/src/mind/learning.js +270 -0
  79. package/dist/src/mind/match.d.ts +181 -0
  80. package/dist/src/mind/match.js +655 -0
  81. package/dist/src/mind/mechanisms/alu.d.ts +4 -0
  82. package/dist/src/mind/mechanisms/alu.js +36 -0
  83. package/dist/src/mind/mechanisms/cast.d.ts +89 -0
  84. package/dist/src/mind/mechanisms/cast.js +784 -0
  85. package/dist/src/mind/mechanisms/confluence.d.ts +24 -0
  86. package/dist/src/mind/mechanisms/confluence.js +255 -0
  87. package/dist/src/mind/mechanisms/cover.d.ts +6 -0
  88. package/dist/src/mind/mechanisms/cover.js +227 -0
  89. package/dist/src/mind/mechanisms/extraction.d.ts +33 -0
  90. package/dist/src/mind/mechanisms/extraction.js +300 -0
  91. package/dist/src/mind/mechanisms/recall.d.ts +16 -0
  92. package/dist/src/mind/mechanisms/recall.js +364 -0
  93. package/dist/src/mind/mind.d.ts +337 -0
  94. package/dist/src/mind/mind.js +626 -0
  95. package/dist/src/mind/pipeline-mechanism.d.ts +172 -0
  96. package/dist/src/mind/pipeline-mechanism.js +465 -0
  97. package/dist/src/mind/pipeline.d.ts +49 -0
  98. package/dist/src/mind/pipeline.js +275 -0
  99. package/dist/src/mind/primitives.d.ts +66 -0
  100. package/dist/src/mind/primitives.js +306 -0
  101. package/dist/src/mind/rationale.d.ts +139 -0
  102. package/dist/src/mind/rationale.js +163 -0
  103. package/dist/src/mind/reasoning.d.ts +40 -0
  104. package/dist/src/mind/reasoning.js +280 -0
  105. package/dist/src/mind/recognition.d.ts +20 -0
  106. package/dist/src/mind/recognition.js +504 -0
  107. package/dist/src/mind/resonance.d.ts +23 -0
  108. package/dist/src/mind/resonance.js +0 -0
  109. package/dist/src/mind/trace.d.ts +15 -0
  110. package/dist/src/mind/trace.js +73 -0
  111. package/dist/src/mind/traverse.d.ts +126 -0
  112. package/dist/src/mind/traverse.js +650 -0
  113. package/dist/src/mind/types.d.ts +333 -0
  114. package/dist/src/mind/types.js +130 -0
  115. package/dist/src/rabitq-ivf/src/database.d.ts +113 -0
  116. package/dist/src/rabitq-ivf/src/database.js +201 -0
  117. package/dist/src/rabitq-ivf/src/index.d.ts +7 -0
  118. package/dist/src/rabitq-ivf/src/index.js +4 -0
  119. package/dist/src/rabitq-ivf/src/ivf.d.ts +200 -0
  120. package/dist/src/rabitq-ivf/src/ivf.js +1165 -0
  121. package/dist/src/rabitq-ivf/src/prng.d.ts +19 -0
  122. package/dist/src/rabitq-ivf/src/prng.js +36 -0
  123. package/dist/src/rabitq-ivf/src/rabitq.d.ts +95 -0
  124. package/dist/src/rabitq-ivf/src/rabitq.js +283 -0
  125. package/dist/src/sema.d.ts +31 -0
  126. package/dist/src/sema.js +63 -0
  127. package/dist/src/store-sqlite.d.ts +184 -0
  128. package/dist/src/store-sqlite.js +942 -0
  129. package/dist/src/store.d.ts +678 -0
  130. package/dist/src/store.js +1703 -0
  131. package/dist/src/vec.d.ts +31 -0
  132. package/dist/src/vec.js +109 -0
  133. package/package.json +1 -1
  134. package/src/mind/bridge.ts +55 -18
  135. package/src/mind/mind.ts +11 -2
@@ -0,0 +1,49 @@
1
+ import type { MindContext } from "./types.js";
2
+ import { type PipelineMechanism } from "./pipeline-mechanism.js";
3
+ export { resolveConcepts, resolveConnectors } from "./mechanisms/cover.js";
4
+ export { aluToMechanism } from "./mechanisms/alu.js";
5
+ export declare const defaultMechanisms: PipelineMechanism[];
6
+ export type Provenance = "cast" | "join" | "cover" | "extract" | "recall" | "recall-echo";
7
+ export interface Thought {
8
+ bytes: Uint8Array;
9
+ provenance: Provenance;
10
+ }
11
+ /** Structured payload of the "decideGrounding" rationale step — the same
12
+ * numbers the human-readable candidate labels already carry, exposed as
13
+ * data so a downstream tool need not parse free text. Purely additive
14
+ * instrumentation: built only under `ctx.trace?.` (optional chaining
15
+ * short-circuits its arguments), never read by inference. */
16
+ export interface DecideGroundingData {
17
+ version: 1;
18
+ /** Every grounding candidate weighed, in consideration order. */
19
+ candidates: Array<{
20
+ provenance: string;
21
+ /** The candidate's exact weight in the one cost ladder. */
22
+ weight: number;
23
+ /** The DISCRETE grade the decision actually compares (floor(weight/STEP)). */
24
+ grade: number;
25
+ /** Query bytes the candidate's accounted spans leave unexplained. */
26
+ unexplainedBytes: number;
27
+ /** Whether this candidate won the decision. */
28
+ decided: boolean;
29
+ }>;
30
+ /** Grade margin between the winner and the runner-up, when both exist —
31
+ * the same quantity the "narrowDecision" step reports as narrow when
32
+ * ≤ 1. Absent for a single-candidate decision. */
33
+ runnerUpMargin?: number;
34
+ }
35
+ /** Structured payload of the "narrowDecision" rationale step. */
36
+ export interface NarrowDecisionData {
37
+ version: 1;
38
+ margin: number;
39
+ }
40
+ /** Think: a single lightest-derivation exploration of the Sema graph.
41
+ *
42
+ * Every answer travels the same path:
43
+ * 1. Pre-computation — recognise, extension parse, guide; everything
44
+ * expensive stays lazy on Precomputed until a mechanism asks.
45
+ * 2. Grounding — every mechanism yields candidates weighed in the one
46
+ * cost ladder; the lightest grounding derivation wins.
47
+ * 3. Post-grounding — diagnostics (narrowDecision, thinGrounding),
48
+ * reasoning (multi-hop), fusion (multi-topic). */
49
+ export declare function think(ctx: MindContext, query: Uint8Array, mechs?: readonly PipelineMechanism[]): Promise<Thought | null>;
@@ -0,0 +1,275 @@
1
+ // pipeline.ts — the think pipeline (Section 5 of the mind).
2
+ //
3
+ // think() is the whole file's job: one lightest-derivation choice among
4
+ // UNIFORM mechanisms. The pipeline sees mechanisms through the
5
+ // PipelineMechanism interface only — it never imports a mechanism-specific
6
+ // type and never has a special-case branch for any mechanism. Adding a
7
+ // mechanism means registering one object; removing one means dropping it
8
+ // from the list. The mechanisms themselves live in mechanisms/ (one file
9
+ // each); the shared pre-computation they exchange lives in Precomputed
10
+ // (pipeline-mechanism.ts).
11
+ import { PASS, STEP } from "./graph-search.js";
12
+ import { gistOf, resolve } from "./primitives.js";
13
+ import { recognise } from "./recognition.js";
14
+ import { fuseAttention, reason } from "./reasoning.js";
15
+ import { unexplainedSpans } from "./rationale.js";
16
+ import { rItem } from "./trace.js";
17
+ import { Precomputed } from "./pipeline-mechanism.js";
18
+ import { coverMechanism } from "./mechanisms/cover.js";
19
+ import { castMechanism } from "./mechanisms/cast.js";
20
+ import { confluenceMechanism } from "./mechanisms/confluence.js";
21
+ import { extractionMechanism } from "./mechanisms/extraction.js";
22
+ import { recallMechanism } from "./mechanisms/recall.js";
23
+ // Re-exports: cover's pre-resolution helpers and the ALU adapter kept
24
+ // importable from the pipeline module (their historical home).
25
+ export { resolveConcepts, resolveConnectors } from "./mechanisms/cover.js";
26
+ export { aluToMechanism } from "./mechanisms/alu.js";
27
+ // ── Extension dispatch (pre-loop parse) ─────────────────────────────────────
28
+ async function collectComputed(ctx, mechanisms, query) {
29
+ const out = [];
30
+ const meter = ctx.meter;
31
+ for (const m of mechanisms) {
32
+ if (!m.parse)
33
+ continue;
34
+ const spans = meter
35
+ ? await meter.time(`${m.name}.parse`, () => m.parse(query))
36
+ : await m.parse(query);
37
+ out.push(...spans);
38
+ }
39
+ return out;
40
+ }
41
+ // ── Built-in mechanisms ─────────────────────────────────────────────────────
42
+ // ORDER MATTERS, but only through the uniform floor/worthRunning pruning —
43
+ // no mechanism is special-cased. Cover runs FIRST: when a computed
44
+ // extension result (e.g. ALU) exists, cover masks it in at near-zero cost
45
+ // (see mechanisms/cover.ts), which becomes `best` before any other mechanism
46
+ // invests in its own precomputation. CAST's and confluence's floors (2*STEP,
47
+ // 3*STEP) then fail `worthRunning` and are skipped by the SAME admissible-
48
+ // floor pruning every mechanism is already subject to — not by asking
49
+ // "is this an extension?". Grade TIES keep the earlier candidate, so this
50
+ // order is also the tie-break priority: cover, cast, confluence, extraction,
51
+ // recall.
52
+ export const defaultMechanisms = [
53
+ coverMechanism,
54
+ castMechanism,
55
+ confluenceMechanism,
56
+ extractionMechanism,
57
+ recallMechanism,
58
+ ];
59
+ /** Think: a single lightest-derivation exploration of the Sema graph.
60
+ *
61
+ * Every answer travels the same path:
62
+ * 1. Pre-computation — recognise, extension parse, guide; everything
63
+ * expensive stays lazy on Precomputed until a mechanism asks.
64
+ * 2. Grounding — every mechanism yields candidates weighed in the one
65
+ * cost ladder; the lightest grounding derivation wins.
66
+ * 3. Post-grounding — diagnostics (narrowDecision, thinGrounding),
67
+ * reasoning (multi-hop), fusion (multi-topic). */
68
+ export async function think(ctx, query, mechs) {
69
+ if (query.length === 0)
70
+ return null;
71
+ ctx._edgeGuide = gistOf(ctx, query);
72
+ ctx._edgeChoice.clear();
73
+ const t = ctx.trace?.enter("think", [rItem(query, "query")]);
74
+ const done = (answer, note) => {
75
+ t?.done(answer
76
+ ? [rItem(answer, "answer", resolve(ctx, answer) ?? undefined)]
77
+ : [], note);
78
+ return answer;
79
+ };
80
+ // ── Pre-computation ──────────────────────────────────────────────────
81
+ const mechanisms = mechs ?? defaultMechanisms;
82
+ const rec = recognise(ctx, query);
83
+ // Phase 1: collect computed spans from mechanisms that implement parse()
84
+ const computed = await collectComputed(ctx, mechanisms, query);
85
+ if (computed.length > 0) {
86
+ ctx.trace?.step("computeExtensions", [rItem(query, "query")], computed.map((u) => rItem(query.subarray(u.i, u.j), "operand", undefined, [u.i, u.j])), `extensions recognised and evaluated ${computed.length} computation(s)`);
87
+ for (const u of computed) {
88
+ ctx.trace?.step("evalComputation", [rItem(query.subarray(u.i, u.j), "expression", undefined, [u.i, u.j])], [rItem(u.bytes, "result", resolve(ctx, u.bytes) ?? undefined)], "evaluate the recognised operation to its authoritative result");
89
+ }
90
+ }
91
+ // Phase 2: the shared pre-computation container. Eager fields only
92
+ // (recognition, computed spans, guide) — every expensive analysis
93
+ // (consensus climb, weave, span-shape classification) is a lazily-cached
94
+ // method on Precomputed, first-touched by whichever mechanism's floor
95
+ // survives its cheap gates and the worthRunning check. A query no
96
+ // mechanism climbs for (e.g. one an extension decided) never climbs.
97
+ const pre = new Precomputed(ctx, query, rec, computed, ctx._edgeGuide);
98
+ const grade = (w) => Math.floor(w / STEP);
99
+ const unaccounted = (spans) => unexplainedSpans(query.length, spans)
100
+ .reduce((sum, [s, e]) => sum + (e - s), 0);
101
+ const weigh = (accounted, moves) => moves + PASS * unaccounted(accounted);
102
+ const candidates = [];
103
+ let best = null;
104
+ const consider = (c) => {
105
+ if (c.bytes.length === 0)
106
+ return;
107
+ if (ctx.meter)
108
+ ctx.meter.candidates++;
109
+ candidates.push(c);
110
+ if (best === null || grade(c.weight) < grade(best.weight))
111
+ best = c;
112
+ };
113
+ const worthRunning = (floor) => best === null || grade(floor) < grade(best.weight);
114
+ // Phase 3: grounding loop
115
+ // Per-mechanism accounting (src/meter.ts). The market's whole premise is
116
+ // that mechanisms compete on one cost scale — so the profiling read-out is
117
+ // also per-mechanism, uniformly: the loop never asks which one it holds.
118
+ const meter = ctx.meter;
119
+ for (const mech of mechanisms) {
120
+ const floor = meter
121
+ ? await meter.time(`${mech.name}.floor`, () => mech.floor(ctx, query, pre, worthRunning))
122
+ : await mech.floor(ctx, query, pre, worthRunning);
123
+ if (meter) {
124
+ if (floor === null)
125
+ meter.mechanismSkips++;
126
+ else
127
+ meter.mechanismFloors++;
128
+ }
129
+ if (floor === null) {
130
+ ctx.trace?.step("skipMechanism", [], [], `${mech.name} skipped — structural precondition failed`);
131
+ continue;
132
+ }
133
+ if (!worthRunning(floor)) {
134
+ ctx.trace?.step("skipMechanism", [], [], `${mech.name} skipped — floor ${floor} cannot beat incumbent (grade ${grade(best.weight)})`);
135
+ continue;
136
+ }
137
+ if (meter)
138
+ meter.mechanismRuns++;
139
+ const results = meter
140
+ ? await meter.time(`${mech.name}.run`, () => mech.run(ctx, query, pre))
141
+ : await mech.run(ctx, query, pre);
142
+ for (const r of results) {
143
+ const weight = r.weight ?? weigh(r.accounted, r.moves);
144
+ consider({
145
+ bytes: r.bytes,
146
+ provenance: r.provenance ?? mech.provenance,
147
+ weight,
148
+ used: r.used,
149
+ accounted: r.accounted,
150
+ unexplained: r.unexplained,
151
+ complete: r.complete,
152
+ });
153
+ }
154
+ }
155
+ // (TS cannot see the closure assignments into `best` and narrows it to its
156
+ // initial null, so the read-back needs the assertion.)
157
+ const decided = best;
158
+ if (candidates.length > 1) {
159
+ // The runner-up is computed BEFORE the decideGrounding step so its grade
160
+ // margin can ride along in the step's structured data payload; the
161
+ // computation itself is pure and was always unconditional — only its
162
+ // position moved.
163
+ let runnerUp = null;
164
+ if (decided !== null) {
165
+ for (const c of candidates) {
166
+ if (c === decided)
167
+ continue;
168
+ if (runnerUp === null || grade(c.weight) < grade(runnerUp.weight)) {
169
+ runnerUp = c;
170
+ }
171
+ }
172
+ }
173
+ const margin = decided !== null && runnerUp !== null
174
+ ? grade(runnerUp.weight) - grade(decided.weight)
175
+ : null;
176
+ ctx.trace?.step("decideGrounding", candidates.map((c) => rItem(c.bytes, `${c.provenance} (weight ${c.weight.toFixed(3)}${c.unexplained ? `, unexplained: "${c.unexplained}"` : ""})`)), decided ? [rItem(decided.bytes, decided.provenance)] : [], "the lightest grounding derivation wins — every mechanism weighed in the one cost ladder", undefined, {
177
+ version: 1,
178
+ candidates: candidates.map((c) => ({
179
+ provenance: c.provenance,
180
+ weight: c.weight,
181
+ grade: grade(c.weight),
182
+ unexplainedBytes: unaccounted(c.accounted),
183
+ decided: c === decided,
184
+ })),
185
+ ...(margin !== null ? { runnerUpMargin: margin } : {}),
186
+ });
187
+ if (decided !== null && runnerUp !== null && margin !== null) {
188
+ if (margin <= 1) {
189
+ ctx.trace?.step("narrowDecision", [
190
+ rItem(decided.bytes, `${decided.provenance} (weight ${decided.weight.toFixed(3)})`),
191
+ ], [
192
+ rItem(runnerUp.bytes, `${runnerUp.provenance} (weight ${runnerUp.weight.toFixed(3)})`),
193
+ ], `margin ${margin} grade-unit(s) — the decision could change with one more training fact`, undefined, { version: 1, margin });
194
+ }
195
+ }
196
+ }
197
+ if (decided === null) {
198
+ done(null, "no mechanism grounded an answer");
199
+ return null;
200
+ }
201
+ // Honesty density
202
+ {
203
+ const covered = query.length - unaccounted(decided.accounted);
204
+ const density = query.length > 0 ? covered / query.length : 1;
205
+ const thinBar = 1 / ctx.space.maxGroup;
206
+ if (density < thinBar) {
207
+ ctx.trace?.step("thinGrounding", [rItem(decided.bytes, decided.provenance)], [], `grounded but thin — density ${density.toFixed(3)} is below 1/W (${thinBar.toFixed(3)})`);
208
+ }
209
+ }
210
+ const answer = decided.bytes;
211
+ const provenance = decided.provenance;
212
+ const castUsed = decided.used ?? new Set();
213
+ // ── Post-grounding, gated by provenance ──────────────────────────────
214
+ const preConsumed = provenance === "cast" || provenance === "join"
215
+ ? castUsed
216
+ : provenance === "recall" || provenance === "recall-echo"
217
+ ? new Set()
218
+ : new Set(recognise(ctx, answer).sites.map((s) => s.payload));
219
+ // A grounding that DECLARED itself complete is not extended: the answer is
220
+ // already a trained form's own continuation, reached through an identity
221
+ // claim about the query, so a multi-hop pivot could only chain past the
222
+ // fact that produced it (see MechanismResult.complete).
223
+ const reasoned = decided.complete ? answer : meter
224
+ ? await meter.time("reason", () => reason(ctx, query, answer, preConsumed, pre))
225
+ : await reason(ctx, query, answer, preConsumed, pre);
226
+ // Fuse only when the query has a genuine REMAINDER no mechanism's
227
+ // structural evidence touched at all. `decided.accounted` alone
228
+ // undercounts this: it is a COST-LADDER quantity (cover.ts prices its
229
+ // masked/computed spans at near-zero and deliberately leaves them out of
230
+ // `accounted` so PASS-bridged bytes are still charged), not a coverage
231
+ // one — a query fully explained by one computed span plus bridged
232
+ // connectors can report `accounted: []` while nothing is actually left
233
+ // unexplained. The genuine remainder is what NEITHER the winning
234
+ // candidate's accounted spans NOR any recognised extension's computed
235
+ // span (`pre.computed` — every mechanism's parse() output, ALU included)
236
+ // ever touched. A remainder under one river-fold quantum (W, the same
237
+ // floor cover.ts's restatedSpan and the honesty-density bar above both
238
+ // use) is bridging punctuation/whitespace, never a second topic —
239
+ // observed: a single space between two fully-computed arithmetic spans
240
+ // ("2+2 3+3") registered as "unaccounted" and pulled in an unrelated
241
+ // corpus fact, corrupting "4 6" into "4 63".
242
+ const explained = [
243
+ ...decided.accounted,
244
+ ...pre.computed.map((u) => [u.i, u.j]),
245
+ ];
246
+ const remainder = unaccounted(explained);
247
+ // Whether the winning candidate's entire recognised substance is
248
+ // COMPUTED — every accounted span exactly a pre.computed span, nothing
249
+ // from a genuinely recognised/climbed site. fuseAttention's lone-root
250
+ // shortcut assumes a single point of attention already IS primary's own
251
+ // source; that assumption is exactly backwards for a pure computation
252
+ // (an ALU result has no anchor of its own) — see fuseAttention's
253
+ // `unclimbed` parameter, gated there by Attention.breadth so a
254
+ // coincidental echo (which this flag alone cannot distinguish) is still
255
+ // rejected.
256
+ const unclimbed = decided.accounted.length > 0 &&
257
+ decided.accounted.every(([i, j]) => pre.computed.some((u) => u.i === i && u.j === j));
258
+ // Where the winning grounding stands in the query — fusion places primary
259
+ // by it (see fuseAttention's `primarySpans`). `accounted` is the
260
+ // cost-ladder read and is authoritative when non-empty; when it is empty
261
+ // the grounding is a pure COMPUTATION, whose evidence is its computed span.
262
+ // Exactly the cost-ladder-vs-coverage distinction `explained` above draws,
263
+ // read here for POSITION instead of for coverage — and resolved here, where
264
+ // both readings are in hand, rather than inside fuseAttention.
265
+ const primarySpans = decided.accounted.length > 0
266
+ ? decided.accounted
267
+ : pre.computed.map((u) => [u.i, u.j]);
268
+ const fused = remainder < ctx.space.maxGroup
269
+ ? reasoned
270
+ : meter
271
+ ? await meter.time("fuse", () => fuseAttention(ctx, query, reasoned, pre, unclimbed, primarySpans))
272
+ : await fuseAttention(ctx, query, reasoned, pre, unclimbed, decided.accounted);
273
+ done(fused, "grounded, reasoned forward, fused across points of attention");
274
+ return { bytes: fused, provenance };
275
+ }
@@ -0,0 +1,66 @@
1
+ import { Vec } from "../vec.js";
2
+ import { Sema } from "../sema.js";
3
+ import type { Input, MindContext } from "./types.js";
4
+ /** The content key of a byte span — one latin1 char per byte, an exact,
5
+ * collision-free encoding. Spans on the perception path are query-scale
6
+ * (windows, regions, candidate spans), so key construction is far cheaper
7
+ * than the river fold it deduplicates. */
8
+ export declare function latin1Key(bytes: Uint8Array): string;
9
+ /** Perceive input into a content-defined tree (the river fold).
10
+ * Deterministic — identical bytes always produce an identical tree.
11
+ *
12
+ * `boundaries` is an optional sorted list of proper byte offsets where the
13
+ * fold must split so that each prefix segment folds identically to how it
14
+ * folded when it was learned (§10.3 stable-prefix contract). Only the
15
+ * CALLER — who assembled the multi-turn context — knows where those
16
+ * boundaries are; the geometry never guesses them from the bytes. */
17
+ export declare function perceive(ctx: MindContext, input: Input, leafAt?: (i: number) => number | null, lookup?: (ids: number[]) => number | null, boundaries?: readonly number[]): Sema;
18
+ /** The DEPOSIT-shaped perceive. Folds over the stream's own content cuts —
19
+ * bit-identical to what inference computes for the same bytes, and that
20
+ * train/inference agreement is load-bearing for exact recall. An input that
21
+ * EXTENDS a previously deposited one is a conversation context grown by one
22
+ * turn; the cached prefix length IS the turn boundary (derived from the deposit
23
+ * sequence itself, never from a content convention) and joins the cut set, so
24
+ * the trained context node and the query's context subtree are the SAME node.
25
+ * Segment folds reuse across deposits ({@link stablePrefixFoldIncremental}) —
26
+ * O(turn) instead of O(context) per turn. All of it is purely a cache: an
27
+ * evicted chain loses only the turn boundaries, and since the content cuts do
28
+ * not depend on the cache, the segments themselves are unchanged. */
29
+ export declare function perceiveDeposit(ctx: MindContext, bytes: Uint8Array, conversational?: boolean): Sema;
30
+ /** The raw bytes of an input — modality-neutral conversion. */
31
+ export declare function inputBytes(ctx: MindContext, input: Input): Uint8Array;
32
+ /** Convenience: the gist vector of a byte span. */
33
+ export declare function gistOf(ctx: MindContext, bytes: Uint8Array): Vec;
34
+ /** Fold a perceived tree bottom-up against the store's content-addressed maps:
35
+ * every leaf is named by findLeaf, every branch by findBranch over its kids'
36
+ * ids (null the moment any child is unknown). `visit`, when given, sees each
37
+ * node with its byte span and resolved id. Returns the node's byte end and
38
+ * resolved id. */
39
+ export declare function foldTree(ctx: MindContext, n: Sema, start: number, visit?: (n: Sema, start: number, end: number, node: number | null) => void): {
40
+ end: number;
41
+ node: number | null;
42
+ };
43
+ /** The canonical node id of a byte span: perceive it in isolation — the way
44
+ * training did — and recover its root bottom-up. Returns null if any part is
45
+ * unknown. */
46
+ export declare function resolve(ctx: MindContext, bytes: Uint8Array): number | null;
47
+ /** Equivalence-class resolution: when the exact content-addressed lookup
48
+ * misses, find a stored node whose CANONICAL key equals the span's — the
49
+ * store's canon index proposes candidates by key hash, and each is verified
50
+ * by re-canonicalizing its bytes (hash-then-verify, like every content
51
+ * lookup). Among verified candidates, one that leads somewhere (has a
52
+ * continuation edge) is preferred; ties break to the lowest id — a corpus
53
+ * property, not a seed property. Null when the response carries no
54
+ * canonicalizer, the store has no canon index, or nothing verifies. */
55
+ export declare function canonResolve(ctx: MindContext, bytes: Uint8Array): number | null;
56
+ /** Walk a perceived tree in POST-ORDER with byte offsets — children before
57
+ * their parent, `visit(node, start, end)` for every node including leaves.
58
+ * Returns the byte end. The one shared traversal the offset-carrying tree
59
+ * readers (recognition via foldTree's richer variant, attention's region
60
+ * collection, resonance's branch counting) build on, so each does not
61
+ * re-derive the offset bookkeeping. (recognition.segment keeps its own
62
+ * walk: its flush semantics need PRE-order decisions at leaf-parents, which
63
+ * a post-order visitor cannot express.) */
64
+ export declare function walkTree(n: Sema, start: number, visit: (node: Sema, start: number, end: number) => void): number;
65
+ /** Reconstruct a node's byte content from the DAG, up to `maxLen` bytes. */
66
+ export declare function read(ctx: MindContext, id: number, maxLen?: number): Uint8Array;