@hviana/sema 0.5.3 → 0.5.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 (143) hide show
  1. package/AGENTS.md +6 -6
  2. package/HOW_IT_WORKS.md +16 -0
  3. package/jsr.json +1 -1
  4. package/package.json +1 -1
  5. package/src/mind/match.ts +81 -0
  6. package/src/mind/mechanisms/recall.ts +29 -3
  7. package/test/76-reference-binding.test.mjs +72 -0
  8. package/dist/example/demo.d.ts +0 -1
  9. package/dist/example/demo.js +0 -39
  10. package/dist/example/train_base.d.ts +0 -93
  11. package/dist/example/train_base.js +0 -2269
  12. package/dist/src/alphabet.d.ts +0 -7
  13. package/dist/src/alphabet.js +0 -33
  14. package/dist/src/alu/src/alu.d.ts +0 -185
  15. package/dist/src/alu/src/alu.js +0 -440
  16. package/dist/src/alu/src/expr.d.ts +0 -61
  17. package/dist/src/alu/src/expr.js +0 -318
  18. package/dist/src/alu/src/index.d.ts +0 -11
  19. package/dist/src/alu/src/index.js +0 -19
  20. package/dist/src/alu/src/kernel-arith.d.ts +0 -16
  21. package/dist/src/alu/src/kernel-arith.js +0 -264
  22. package/dist/src/alu/src/kernel-bits.d.ts +0 -19
  23. package/dist/src/alu/src/kernel-bits.js +0 -152
  24. package/dist/src/alu/src/kernel-logic.d.ts +0 -4
  25. package/dist/src/alu/src/kernel-logic.js +0 -60
  26. package/dist/src/alu/src/kernel-nd.d.ts +0 -3
  27. package/dist/src/alu/src/kernel-nd.js +0 -208
  28. package/dist/src/alu/src/kernel-numeric.d.ts +0 -54
  29. package/dist/src/alu/src/kernel-numeric.js +0 -366
  30. package/dist/src/alu/src/operation.d.ts +0 -168
  31. package/dist/src/alu/src/operation.js +0 -189
  32. package/dist/src/alu/src/parser.d.ts +0 -221
  33. package/dist/src/alu/src/parser.js +0 -577
  34. package/dist/src/alu/src/resonance.d.ts +0 -55
  35. package/dist/src/alu/src/resonance.js +0 -126
  36. package/dist/src/alu/src/text.d.ts +0 -31
  37. package/dist/src/alu/src/text.js +0 -73
  38. package/dist/src/alu/src/value.d.ts +0 -109
  39. package/dist/src/alu/src/value.js +0 -300
  40. package/dist/src/alu/test/alu.test.d.ts +0 -1
  41. package/dist/src/alu/test/alu.test.js +0 -764
  42. package/dist/src/bytes.d.ts +0 -14
  43. package/dist/src/bytes.js +0 -59
  44. package/dist/src/canon.d.ts +0 -45
  45. package/dist/src/canon.js +0 -85
  46. package/dist/src/config.d.ts +0 -111
  47. package/dist/src/config.js +0 -91
  48. package/dist/src/derive/src/deduction.d.ts +0 -136
  49. package/dist/src/derive/src/deduction.js +0 -159
  50. package/dist/src/derive/src/index.d.ts +0 -8
  51. package/dist/src/derive/src/index.js +0 -11
  52. package/dist/src/derive/src/priority-queue.d.ts +0 -20
  53. package/dist/src/derive/src/priority-queue.js +0 -73
  54. package/dist/src/derive/src/rewrite.d.ts +0 -56
  55. package/dist/src/derive/src/rewrite.js +0 -100
  56. package/dist/src/derive/src/trie.d.ts +0 -90
  57. package/dist/src/derive/src/trie.js +0 -217
  58. package/dist/src/derive/test/derive.test.d.ts +0 -1
  59. package/dist/src/derive/test/derive.test.js +0 -122
  60. package/dist/src/extension.d.ts +0 -37
  61. package/dist/src/extension.js +0 -7
  62. package/dist/src/geometry.d.ts +0 -233
  63. package/dist/src/geometry.js +0 -1089
  64. package/dist/src/index.d.ts +0 -17
  65. package/dist/src/index.js +0 -19
  66. package/dist/src/ingest-cache.d.ts +0 -41
  67. package/dist/src/ingest-cache.js +0 -165
  68. package/dist/src/meter.d.ts +0 -176
  69. package/dist/src/meter.js +0 -274
  70. package/dist/src/mind/articulation.d.ts +0 -6
  71. package/dist/src/mind/articulation.js +0 -99
  72. package/dist/src/mind/attention.d.ts +0 -430
  73. package/dist/src/mind/attention.js +0 -2418
  74. package/dist/src/mind/bridge.d.ts +0 -37
  75. package/dist/src/mind/bridge.js +0 -907
  76. package/dist/src/mind/canonical.d.ts +0 -34
  77. package/dist/src/mind/canonical.js +0 -93
  78. package/dist/src/mind/graph-search.d.ts +0 -294
  79. package/dist/src/mind/graph-search.js +0 -996
  80. package/dist/src/mind/index.d.ts +0 -9
  81. package/dist/src/mind/index.js +0 -5
  82. package/dist/src/mind/junction.d.ts +0 -137
  83. package/dist/src/mind/junction.js +0 -358
  84. package/dist/src/mind/learning.d.ts +0 -75
  85. package/dist/src/mind/learning.js +0 -265
  86. package/dist/src/mind/match.d.ts +0 -351
  87. package/dist/src/mind/match.js +0 -959
  88. package/dist/src/mind/mechanisms/alu.d.ts +0 -4
  89. package/dist/src/mind/mechanisms/alu.js +0 -36
  90. package/dist/src/mind/mechanisms/cast.d.ts +0 -89
  91. package/dist/src/mind/mechanisms/cast.js +0 -1186
  92. package/dist/src/mind/mechanisms/confluence.d.ts +0 -24
  93. package/dist/src/mind/mechanisms/confluence.js +0 -271
  94. package/dist/src/mind/mechanisms/cover.d.ts +0 -6
  95. package/dist/src/mind/mechanisms/cover.js +0 -232
  96. package/dist/src/mind/mechanisms/extraction.d.ts +0 -33
  97. package/dist/src/mind/mechanisms/extraction.js +0 -327
  98. package/dist/src/mind/mechanisms/prefix-completion.d.ts +0 -22
  99. package/dist/src/mind/mechanisms/prefix-completion.js +0 -243
  100. package/dist/src/mind/mechanisms/recall.d.ts +0 -16
  101. package/dist/src/mind/mechanisms/recall.js +0 -460
  102. package/dist/src/mind/mechanisms/reference.d.ts +0 -6
  103. package/dist/src/mind/mechanisms/reference.js +0 -296
  104. package/dist/src/mind/mind.d.ts +0 -386
  105. package/dist/src/mind/mind.js +0 -754
  106. package/dist/src/mind/pipeline-mechanism.d.ts +0 -238
  107. package/dist/src/mind/pipeline-mechanism.js +0 -622
  108. package/dist/src/mind/pipeline.d.ts +0 -49
  109. package/dist/src/mind/pipeline.js +0 -343
  110. package/dist/src/mind/primitives.d.ts +0 -85
  111. package/dist/src/mind/primitives.js +0 -333
  112. package/dist/src/mind/rationale.d.ts +0 -139
  113. package/dist/src/mind/rationale.js +0 -163
  114. package/dist/src/mind/reasoning.d.ts +0 -42
  115. package/dist/src/mind/reasoning.js +0 -305
  116. package/dist/src/mind/recognition.d.ts +0 -20
  117. package/dist/src/mind/recognition.js +0 -696
  118. package/dist/src/mind/resonance.d.ts +0 -35
  119. package/dist/src/mind/resonance.js +0 -365
  120. package/dist/src/mind/trace.d.ts +0 -15
  121. package/dist/src/mind/trace.js +0 -73
  122. package/dist/src/mind/traverse.d.ts +0 -196
  123. package/dist/src/mind/traverse.js +0 -806
  124. package/dist/src/mind/types.d.ts +0 -418
  125. package/dist/src/mind/types.js +0 -179
  126. package/dist/src/rabitq-ivf/src/database.d.ts +0 -113
  127. package/dist/src/rabitq-ivf/src/database.js +0 -201
  128. package/dist/src/rabitq-ivf/src/index.d.ts +0 -7
  129. package/dist/src/rabitq-ivf/src/index.js +0 -4
  130. package/dist/src/rabitq-ivf/src/ivf.d.ts +0 -200
  131. package/dist/src/rabitq-ivf/src/ivf.js +0 -1165
  132. package/dist/src/rabitq-ivf/src/prng.d.ts +0 -19
  133. package/dist/src/rabitq-ivf/src/prng.js +0 -36
  134. package/dist/src/rabitq-ivf/src/rabitq.d.ts +0 -95
  135. package/dist/src/rabitq-ivf/src/rabitq.js +0 -313
  136. package/dist/src/sema.d.ts +0 -41
  137. package/dist/src/sema.js +0 -77
  138. package/dist/src/store-sqlite.d.ts +0 -184
  139. package/dist/src/store-sqlite.js +0 -942
  140. package/dist/src/store.d.ts +0 -762
  141. package/dist/src/store.js +0 -1823
  142. package/dist/src/vec.d.ts +0 -31
  143. package/dist/src/vec.js +0 -109
@@ -1,343 +0,0 @@
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, read, 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 { hubBound } from "./traverse.js";
18
- import { Precomputed } from "./pipeline-mechanism.js";
19
- import { coverMechanism } from "./mechanisms/cover.js";
20
- import { castMechanism } from "./mechanisms/cast.js";
21
- import { confluenceMechanism } from "./mechanisms/confluence.js";
22
- import { extractionMechanism } from "./mechanisms/extraction.js";
23
- import { referenceMechanism } from "./mechanisms/reference.js";
24
- import { prefixMechanism } from "./mechanisms/prefix-completion.js";
25
- import { recallMechanism } from "./mechanisms/recall.js";
26
- // Re-exports: cover's pre-resolution helpers and the ALU adapter kept
27
- // importable from the pipeline module (their historical home).
28
- export { resolveConcepts, resolveConnectors } from "./mechanisms/cover.js";
29
- export { aluToMechanism } from "./mechanisms/alu.js";
30
- // ── Extension dispatch (pre-loop parse) ─────────────────────────────────────
31
- async function collectComputed(ctx, mechanisms, query) {
32
- const out = [];
33
- const meter = ctx.meter;
34
- for (const m of mechanisms) {
35
- if (!m.parse)
36
- continue;
37
- const spans = meter
38
- ? await meter.time(`${m.name}.parse`, () => m.parse(query))
39
- : await m.parse(query);
40
- out.push(...spans);
41
- }
42
- return out;
43
- }
44
- // ── Built-in mechanisms ─────────────────────────────────────────────────────
45
- // ORDER MATTERS, but only through the uniform floor/worthRunning pruning —
46
- // no mechanism is special-cased. Cover runs FIRST: when a computed
47
- // extension result (e.g. ALU) exists, cover masks it in at near-zero cost
48
- // (see mechanisms/cover.ts), which becomes `best` before any other mechanism
49
- // invests in its own precomputation. CAST's and confluence's floors (2*STEP,
50
- // 3*STEP) then fail `worthRunning` and are skipped by the SAME admissible-
51
- // floor pruning every mechanism is already subject to — not by asking
52
- // "is this an extension?". Grade TIES keep the earlier candidate, so this
53
- // order is also the tie-break priority: cover, cast, confluence, extraction,
54
- // reference, recall.
55
- //
56
- // REFERENCE sits after extraction and before recall because that is what its
57
- // claim is worth: extraction READS a span out of the query (no synthesis),
58
- // reference voices one through a learnt slot, and recall's tiers degrade
59
- // toward echo and silence. It does not PRUNE recall — its floor is two
60
- // projections, so recall's one-STEP floor still clears `worthRunning` — and it
61
- // is not meant to: both run, share one resonance read
62
- // (Precomputed.resonance), and the ladder decides.
63
- export const defaultMechanisms = [
64
- coverMechanism,
65
- castMechanism,
66
- confluenceMechanism,
67
- extractionMechanism,
68
- referenceMechanism,
69
- recallMechanism,
70
- prefixMechanism,
71
- ];
72
- /** Think: a single lightest-derivation exploration of the Sema graph.
73
- *
74
- * Every answer travels the same path:
75
- * 1. Pre-computation — recognise, extension parse, guide; everything
76
- * expensive stays lazy on Precomputed until a mechanism asks.
77
- * 2. Grounding — every mechanism yields candidates weighed in the one
78
- * cost ladder; the lightest grounding derivation wins.
79
- * 3. Post-grounding — diagnostics (narrowDecision, thinGrounding),
80
- * reasoning (multi-hop), fusion (multi-topic). */
81
- export async function think(ctx, query, mechs) {
82
- if (query.length === 0)
83
- return null;
84
- ctx._edgeGuide = gistOf(ctx, query);
85
- ctx._edgeChoice.clear();
86
- const t = ctx.trace?.enter("think", [rItem(query, "query")]);
87
- const done = (answer, note) => {
88
- t?.done(answer
89
- ? [rItem(answer, "answer", resolve(ctx, answer) ?? undefined)]
90
- : [], note);
91
- return answer;
92
- };
93
- // ── Pre-computation ──────────────────────────────────────────────────
94
- const mechanisms = mechs ?? defaultMechanisms;
95
- const rec = recognise(ctx, query);
96
- // Phase 1: collect computed spans from mechanisms that implement parse()
97
- const computed = await collectComputed(ctx, mechanisms, query);
98
- if (computed.length > 0) {
99
- 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)`);
100
- for (const u of computed) {
101
- 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");
102
- }
103
- }
104
- // Phase 2: the shared pre-computation container. Eager fields only
105
- // (recognition, computed spans, guide) — every expensive analysis
106
- // (consensus climb, weave, span-shape classification) is a lazily-cached
107
- // method on Precomputed, first-touched by whichever mechanism's floor
108
- // survives its cheap gates and the worthRunning check. A query no
109
- // mechanism climbs for (e.g. one an extension decided) never climbs.
110
- const pre = new Precomputed(ctx, query, rec, computed, ctx._edgeGuide);
111
- const grade = (w) => Math.floor(w / STEP);
112
- const unaccounted = (spans) => unexplainedSpans(query.length, spans)
113
- .reduce((sum, [s, e]) => sum + (e - s), 0);
114
- const weigh = (accounted, moves) => moves + PASS * unaccounted(accounted);
115
- const candidates = [];
116
- let best = null;
117
- const consider = (c) => {
118
- if (c.bytes.length === 0)
119
- return;
120
- if (ctx.meter)
121
- ctx.meter.candidates++;
122
- candidates.push(c);
123
- if (best === null) {
124
- best = c;
125
- return;
126
- }
127
- const g = grade(c.weight), gb = grade(best.weight);
128
- if (g < gb) {
129
- best = c;
130
- return;
131
- }
132
- // TIE-BREAK: AT EQUAL GRADE, PREFER THE ANSWER THAT INVENTS LESS.
133
- //
134
- // The ladder prices what a candidate leaves UNACCOUNTED, which is the
135
- // right primary question but cannot separate two candidates that leave
136
- // the same bytes unaccounted — and then the winner is whichever mechanism
137
- // happened to be considered first, which is not a reason.
138
- //
139
- // What still separates them is what they DID with those bytes. A
140
- // candidate that carries an unexplained span into its answer is passing
141
- // the asker's own words back as if they were derived; one that leaves
142
- // them out has made a smaller, honest claim. Measured on test/22's
143
- // two-fact chain: cover and recall both graded 11001 over 11 unexplained
144
- // bytes, cover answering "The capital of France is Paris famous for" (11
145
- // bytes of scaffolding) against recall's crossing of the hop (0). Order
146
- // alone decided it, and the shallower reading won.
147
- //
148
- // This never overrides the ladder — it only orders within one grade, so
149
- // coverage and moves still dominate exactly as before.
150
- if (g === gb && (c.scaffolding ?? 0) < (best.scaffolding ?? 0))
151
- best = c;
152
- };
153
- const worthRunning = (floor) => best === null || grade(floor) < grade(best.weight);
154
- // Phase 3: grounding loop
155
- // Per-mechanism accounting (src/meter.ts). The market's whole premise is
156
- // that mechanisms compete on one cost scale — so the profiling read-out is
157
- // also per-mechanism, uniformly: the loop never asks which one it holds.
158
- const meter = ctx.meter;
159
- for (const mech of mechanisms) {
160
- const floor = meter
161
- ? await meter.time(`${mech.name}.floor`, () => mech.floor(ctx, query, pre, worthRunning))
162
- : await mech.floor(ctx, query, pre, worthRunning);
163
- if (meter) {
164
- if (floor === null)
165
- meter.mechanismSkips++;
166
- else
167
- meter.mechanismFloors++;
168
- }
169
- if (floor === null) {
170
- ctx.trace?.step("skipMechanism", [], [], `${mech.name} skipped — structural precondition failed`);
171
- continue;
172
- }
173
- if (!worthRunning(floor)) {
174
- ctx.trace?.step("skipMechanism", [], [], `${mech.name} skipped — floor ${floor} cannot beat incumbent (grade ${grade(best.weight)})`);
175
- continue;
176
- }
177
- if (meter)
178
- meter.mechanismRuns++;
179
- const results = meter
180
- ? await meter.time(`${mech.name}.run`, () => mech.run(ctx, query, pre))
181
- : await mech.run(ctx, query, pre);
182
- for (const r of results) {
183
- const weight = r.weight ?? weigh(r.accounted, r.moves);
184
- consider({
185
- bytes: r.bytes,
186
- provenance: r.provenance ?? mech.provenance,
187
- weight,
188
- used: r.used,
189
- accounted: r.accounted,
190
- unexplained: r.unexplained,
191
- complete: r.complete,
192
- scaffolding: r.scaffolding,
193
- });
194
- }
195
- }
196
- // (TS cannot see the closure assignments into `best` and narrows it to its
197
- // initial null, so the read-back needs the assertion.)
198
- const decided = best;
199
- if (candidates.length > 1) {
200
- // The runner-up is computed BEFORE the decideGrounding step so its grade
201
- // margin can ride along in the step's structured data payload; the
202
- // computation itself is pure and was always unconditional — only its
203
- // position moved.
204
- let runnerUp = null;
205
- if (decided !== null) {
206
- for (const c of candidates) {
207
- if (c === decided)
208
- continue;
209
- if (runnerUp === null || grade(c.weight) < grade(runnerUp.weight)) {
210
- runnerUp = c;
211
- }
212
- }
213
- }
214
- const margin = decided !== null && runnerUp !== null
215
- ? grade(runnerUp.weight) - grade(decided.weight)
216
- : null;
217
- 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, {
218
- version: 1,
219
- candidates: candidates.map((c) => ({
220
- provenance: c.provenance,
221
- weight: c.weight,
222
- grade: grade(c.weight),
223
- unexplainedBytes: unaccounted(c.accounted),
224
- decided: c === decided,
225
- })),
226
- ...(margin !== null ? { runnerUpMargin: margin } : {}),
227
- });
228
- if (decided !== null && runnerUp !== null && margin !== null) {
229
- if (margin <= 1) {
230
- ctx.trace?.step("narrowDecision", [
231
- rItem(decided.bytes, `${decided.provenance} (weight ${decided.weight.toFixed(3)})`),
232
- ], [
233
- rItem(runnerUp.bytes, `${runnerUp.provenance} (weight ${runnerUp.weight.toFixed(3)})`),
234
- ], `margin ${margin} grade-unit(s) — the decision could change with one more training fact`, undefined, { version: 1, margin });
235
- }
236
- }
237
- }
238
- if (decided === null) {
239
- done(null, "no mechanism grounded an answer");
240
- return null;
241
- }
242
- // Honesty density
243
- {
244
- const covered = query.length - unaccounted(decided.accounted);
245
- const density = query.length > 0 ? covered / query.length : 1;
246
- const thinBar = 1 / ctx.space.maxGroup;
247
- if (density < thinBar) {
248
- ctx.trace?.step("thinGrounding", [rItem(decided.bytes, decided.provenance)], [], `grounded but thin — density ${density.toFixed(3)} is below 1/W (${thinBar.toFixed(3)})`);
249
- }
250
- }
251
- const answer = decided.bytes;
252
- const provenance = decided.provenance;
253
- const castUsed = decided.used ?? new Set();
254
- // ── Post-grounding, gated by provenance ──────────────────────────────
255
- const preConsumed = provenance === "cast" || provenance === "join"
256
- ? castUsed
257
- : provenance === "recall" || provenance === "recall-echo"
258
- ? new Set()
259
- : new Set(recognise(ctx, answer).sites.map((s) => s.payload));
260
- // A grounding that DECLARED itself complete is not extended: the answer is
261
- // already a trained form's own continuation, reached through an identity
262
- // claim about the query, so a multi-hop pivot could only chain past the
263
- // fact that produced it (see MechanismResult.complete).
264
- // WHAT THE MECHANISM WITHHELD, NOT WHAT IT VOICED. A pivot must not
265
- // re-open content a grounding deliberately kept out: comparison cites two
266
- // analogs and refuses their own downstream facts, so pivoting into one is
267
- // the mechanism's own refusal undone one step later (test/29 C2 pivoted
268
- // through `speare` — a stored fragment of the analog `William Shakespeare`
269
- // — into the biography CAST had declined).
270
- //
271
- // Reading the used anchors' OWN bytes here says something stronger and
272
- // wrong: that nothing INSIDE what was voiced may be pivoted through. A
273
- // comparison's seat sentence legitimately contains further terms with
274
- // their own unrelated facts, and C3 pins exactly that — `Mona Lisa`, inside
275
- // the voiced seat `The Mona Lisa was painted by Leonardo da Vinci.`, leads
276
- // on to `Mona Lisa hangs in the Louvre`, which is about neither analog.
277
- // The withheld content is the used anchors' CONTINUATIONS, so that is what
278
- // the containment rule reads: `speare` is contained in `Shakespeare wrote
279
- // 39 plays` and stays refused, while `Mona Lisa` appears in no withheld
280
- // continuation and the genuine further hop fires.
281
- //
282
- // Only a mechanism carrying its own `used` set (cast/join) gets this: there
283
- // `preConsumed` is a deliberate, short list of the anchors the answer
284
- // speaks for, so the fan-out is bounded. For every other provenance
285
- // `preConsumed` is derived by re-recognising the answer — "everything in
286
- // it", not "what it voiced" — and a containment rule over that would
287
- // suppress every pivot the answer legitimately contains.
288
- const voiced = (provenance === "cast" || provenance === "join")
289
- ? [...castUsed].flatMap((id) => ctx.store.nextFirst(id, hubBound(ctx)).map((n) => read(ctx, n)))
290
- : [];
291
- const reasoned = decided.complete ? answer : meter
292
- ? await meter.time("reason", () => reason(ctx, query, answer, preConsumed, pre, voiced))
293
- : await reason(ctx, query, answer, preConsumed, pre, voiced);
294
- // Fuse only when the query has a genuine REMAINDER no mechanism's
295
- // structural evidence touched at all. `decided.accounted` alone
296
- // undercounts this: it is a COST-LADDER quantity (cover.ts prices its
297
- // masked/computed spans at near-zero and deliberately leaves them out of
298
- // `accounted` so PASS-bridged bytes are still charged), not a coverage
299
- // one — a query fully explained by one computed span plus bridged
300
- // connectors can report `accounted: []` while nothing is actually left
301
- // unexplained. The genuine remainder is what NEITHER the winning
302
- // candidate's accounted spans NOR any recognised extension's computed
303
- // span (`pre.computed` — every mechanism's parse() output, ALU included)
304
- // ever touched. A remainder under one river-fold quantum (W, the same
305
- // floor cover.ts's restatedSpan and the honesty-density bar above both
306
- // use) is bridging punctuation/whitespace, never a second topic —
307
- // observed: a single space between two fully-computed arithmetic spans
308
- // ("2+2 3+3") registered as "unaccounted" and pulled in an unrelated
309
- // corpus fact, corrupting "4 6" into "4 63".
310
- const explained = [
311
- ...decided.accounted,
312
- ...pre.computed.map((u) => [u.i, u.j]),
313
- ];
314
- const remainder = unaccounted(explained);
315
- // Whether the winning candidate's entire recognised substance is
316
- // COMPUTED — every accounted span exactly a pre.computed span, nothing
317
- // from a genuinely recognised/climbed site. fuseAttention's lone-root
318
- // shortcut assumes a single point of attention already IS primary's own
319
- // source; that assumption is exactly backwards for a pure computation
320
- // (an ALU result has no anchor of its own) — see fuseAttention's
321
- // `unclimbed` parameter, gated there by Attention.breadth so a
322
- // coincidental echo (which this flag alone cannot distinguish) is still
323
- // rejected.
324
- const unclimbed = decided.accounted.length > 0 &&
325
- decided.accounted.every(([i, j]) => pre.computed.some((u) => u.i === i && u.j === j));
326
- // Where the winning grounding stands in the query — fusion places primary
327
- // by it (see fuseAttention's `primarySpans`). `accounted` is the
328
- // cost-ladder read and is authoritative when non-empty; when it is empty
329
- // the grounding is a pure COMPUTATION, whose evidence is its computed span.
330
- // Exactly the cost-ladder-vs-coverage distinction `explained` above draws,
331
- // read here for POSITION instead of for coverage — and resolved here, where
332
- // both readings are in hand, rather than inside fuseAttention.
333
- const primarySpans = decided.accounted.length > 0
334
- ? decided.accounted
335
- : pre.computed.map((u) => [u.i, u.j]);
336
- const fused = remainder < ctx.space.maxGroup
337
- ? reasoned
338
- : meter
339
- ? await meter.time("fuse", () => fuseAttention(ctx, query, reasoned, pre, unclimbed, primarySpans))
340
- : await fuseAttention(ctx, query, reasoned, pre, unclimbed, decided.accounted);
341
- done(fused, "grounded, reasoned forward, fused across points of attention");
342
- return { bytes: fused, provenance };
343
- }
@@ -1,85 +0,0 @@
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
- /** The {@link perceive} memo key: the span's content PLUS the boundary set it
10
- * was folded under. The tree is a function of BOTH — the same bytes fold
11
- * plainly with no boundaries and into a left-nested stable-prefix shape with
12
- * them — so a content-only key returns whichever shape was computed first.
13
- * That is exactly what happened: a conversation seeded its cumulative context
14
- * under the content key, and every later plain `perceive` of those bytes was
15
- * served the boundary tree instead (measured: respondTurn answered where
16
- * respond() on byte-identical input did not). NUL separates the two parts —
17
- * the boundary rendering is digits and commas, so no content byte can forge
18
- * the split. */
19
- export declare function perceiveKey(bytes: Uint8Array, boundaries?: readonly number[]): string;
20
- /** Perceive input into a content-defined tree (the river fold).
21
- * Deterministic — identical bytes always produce an identical tree.
22
- *
23
- * `boundaries` is an optional sorted list of proper byte offsets where the
24
- * fold must split so that each prefix segment folds identically to how it
25
- * folded when it was learned (§10.3 stable-prefix contract). Only the
26
- * CALLER — who assembled the multi-turn context — knows where those
27
- * boundaries are; the geometry never guesses them from the bytes. */
28
- export declare function perceive(ctx: MindContext, input: Input, leafAt?: (i: number) => number | null, lookup?: (ids: number[]) => number | null, boundaries?: readonly number[]): Sema;
29
- /** The DEPOSIT-shaped perceive. Folds over the stream's own content cuts —
30
- * bit-identical to what inference computes for the same bytes. That
31
- * train/inference agreement is the whole contract: the trained context node
32
- * and the node `resolve(query)` reaches must be the SAME node, and the only
33
- * way to guarantee it is to give this function nothing extra to say. It
34
- * imposes no boundaries, knows nothing about turns, and reads no convention
35
- * out of the bytes.
36
- *
37
- * An input that EXTENDS a previously deposited one — a conversation context
38
- * grown by a turn, or a resumed replay — reuses that deposit's already-folded
39
- * content segments ({@link contentFoldIncremental}), so it costs O(new bytes)
40
- * instead of O(context). The reuse is TRANSPARENT by construction: a segment
41
- * is a pure function of its own bytes, so a reused one is bit-identical to a
42
- * refolded one. Nothing has to prove that the extending deposit is "really"
43
- * a next turn — a coincidental byte prefix reuses the same segments and gets
44
- * the same tree it would have got anyway. (It used to matter: while this
45
- * path imposed turn BOUNDARIES, a wrong guess changed the tree, so the cache
46
- * needed a continuation-bytes proof to gate it. Nothing is imposed now, so
47
- * there is nothing to gate.) */
48
- export declare function perceiveDeposit(ctx: MindContext, bytes: Uint8Array, conversational?: boolean): Sema;
49
- /** The raw bytes of an input — modality-neutral conversion. */
50
- export declare function inputBytes(ctx: MindContext, input: Input): Uint8Array;
51
- /** Convenience: the gist vector of a byte span. */
52
- export declare function gistOf(ctx: MindContext, bytes: Uint8Array): Vec;
53
- /** Fold a perceived tree bottom-up against the store's content-addressed maps:
54
- * every leaf is named by findLeaf, every branch by findBranch over its kids'
55
- * ids (null the moment any child is unknown). `visit`, when given, sees each
56
- * node with its byte span and resolved id. Returns the node's byte end and
57
- * resolved id. */
58
- export declare function foldTree(ctx: MindContext, n: Sema, start: number, visit?: (n: Sema, start: number, end: number, node: number | null) => void): {
59
- end: number;
60
- node: number | null;
61
- };
62
- /** The canonical node id of a byte span: perceive it in isolation — the way
63
- * training did — and recover its root bottom-up. Returns null if any part is
64
- * unknown. */
65
- export declare function resolve(ctx: MindContext, bytes: Uint8Array): number | null;
66
- /** Equivalence-class resolution: when the exact content-addressed lookup
67
- * misses, find a stored node whose CANONICAL key equals the span's — the
68
- * store's canon index proposes candidates by key hash, and each is verified
69
- * by re-canonicalizing its bytes (hash-then-verify, like every content
70
- * lookup). Among verified candidates, one that leads somewhere (has a
71
- * continuation edge) is preferred; ties break to the lowest id — a corpus
72
- * property, not a seed property. Null when the response carries no
73
- * canonicalizer, the store has no canon index, or nothing verifies. */
74
- export declare function canonResolve(ctx: MindContext, bytes: Uint8Array): number | null;
75
- /** Walk a perceived tree in POST-ORDER with byte offsets — children before
76
- * their parent, `visit(node, start, end)` for every node including leaves.
77
- * Returns the byte end. The one shared traversal the offset-carrying tree
78
- * readers (recognition via foldTree's richer variant, attention's region
79
- * collection, resonance's branch counting) build on, so each does not
80
- * re-derive the offset bookkeeping. (recognition.segment keeps its own
81
- * walk: its flush semantics need PRE-order decisions at leaf-parents, which
82
- * a post-order visitor cannot express.) */
83
- export declare function walkTree(n: Sema, start: number, visit: (node: Sema, start: number, end: number) => void): number;
84
- /** Reconstruct a node's byte content from the DAG, up to `maxLen` bytes. */
85
- export declare function read(ctx: MindContext, id: number, maxLen?: number): Uint8Array;