@hviana/sema 0.9.0 → 0.9.2
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 +7 -7
- package/dist/src/alu/src/index.d.ts +1 -1
- package/dist/src/alu/src/index.js +1 -1
- package/dist/src/alu/src/parser.js +2 -6
- package/dist/src/alu/src/resonance.d.ts +13 -0
- package/dist/src/alu/src/resonance.js +41 -0
- package/dist/src/alu/test/alu.test.js +39 -0
- package/dist/src/bytes.d.ts +6 -2
- package/dist/src/bytes.js +10 -4
- package/dist/src/canon.js +44 -0
- package/dist/src/geometry.d.ts +19 -1
- package/dist/src/geometry.js +125 -141
- package/dist/src/meter.d.ts +33 -0
- package/dist/src/meter.js +34 -1
- package/dist/src/mind/articulation.js +14 -1
- package/dist/src/mind/attention.d.ts +12 -0
- package/dist/src/mind/attention.js +44 -16
- package/dist/src/mind/bridge.js +3 -3
- package/dist/src/mind/derivation.d.ts +40 -0
- package/dist/src/mind/derivation.js +34 -0
- package/dist/src/mind/evidence.d.ts +24 -0
- package/dist/src/mind/evidence.js +90 -0
- package/dist/src/mind/graph-search.d.ts +89 -15
- package/dist/src/mind/graph-search.js +345 -174
- package/dist/src/mind/learning.js +1 -1
- package/dist/src/mind/mechanisms/cover.d.ts +19 -3
- package/dist/src/mind/mechanisms/cover.js +142 -61
- package/dist/src/mind/mechanisms/recall.js +10 -3
- package/dist/src/mind/mind.d.ts +6 -0
- package/dist/src/mind/mind.js +5 -2
- package/dist/src/mind/pipeline.d.ts +5 -1
- package/dist/src/mind/pipeline.js +220 -90
- package/dist/src/mind/primitives.d.ts +25 -5
- package/dist/src/mind/primitives.js +107 -44
- package/dist/src/mind/reasoning.d.ts +18 -4
- package/dist/src/mind/reasoning.js +487 -328
- package/dist/src/mind/recognition.js +29 -13
- package/dist/src/mind/resonance.js +1 -11
- package/dist/src/mind/traverse.d.ts +45 -5
- package/dist/src/mind/traverse.js +285 -8
- package/dist/src/mind/types.d.ts +16 -1
- package/dist/src/store-sqlite.d.ts +25 -0
- package/dist/src/store-sqlite.js +89 -1
- package/dist/src/store.d.ts +48 -4
- package/dist/src/store.js +86 -6
- package/docs/INDEX.md +20 -19
- package/docs/INVARIANTS.md +17 -16
- package/docs/architecture/bounded-reads.md +1 -1
- package/docs/architecture/caches.md +5 -4
- package/docs/architecture/closure.md +45 -5
- package/docs/architecture/cost-model.md +16 -0
- package/docs/architecture/evidence.md +113 -0
- package/docs/architecture/exact-vs-approximate.md +10 -9
- package/docs/architecture/factored-machinery.md +14 -13
- package/docs/architecture/fold-contract.md +51 -1
- package/docs/architecture/mechanism-market.md +21 -0
- package/docs/architecture/memoization.md +3 -3
- package/docs/architecture/meter.md +2 -1
- package/docs/architecture/saturation.md +12 -0
- package/docs/architecture/store.md +25 -2
- package/docs/failures/tempting-but-wrong.md +13 -2
- package/docs/harness/gates.md +12 -10
- package/docs/mechanisms/cover.md +23 -6
- package/jsr.json +1 -1
- package/package.json +1 -1
- package/src/alu/README.md +10 -2
- package/src/alu/src/index.ts +1 -0
- package/src/alu/src/parser.ts +6 -6
- package/src/alu/src/resonance.ts +42 -0
- package/src/alu/test/alu.test.ts +40 -0
- package/src/bytes.ts +13 -3
- package/src/canon.ts +40 -0
- package/src/geometry.ts +183 -154
- package/src/meter.ts +34 -1
- package/src/mind/articulation.ts +14 -2
- package/src/mind/attention.ts +47 -25
- package/src/mind/bridge.ts +3 -3
- package/src/mind/derivation.ts +77 -0
- package/src/mind/evidence.ts +107 -0
- package/src/mind/graph-search.ts +449 -221
- package/src/mind/learning.ts +1 -7
- package/src/mind/match.ts +1 -2
- package/src/mind/mechanisms/cast.ts +1 -2
- package/src/mind/mechanisms/cover.ts +207 -87
- package/src/mind/mechanisms/extraction.ts +1 -2
- package/src/mind/mechanisms/prefix-completion.ts +1 -1
- package/src/mind/mechanisms/recall.ts +17 -5
- package/src/mind/mechanisms/reference.ts +1 -1
- package/src/mind/mind.ts +9 -30
- package/src/mind/pipeline.ts +263 -104
- package/src/mind/primitives.ts +119 -43
- package/src/mind/reasoning.ts +611 -419
- package/src/mind/recognition.ts +24 -9
- package/src/mind/resonance.ts +2 -16
- package/src/mind/trace.ts +1 -1
- package/src/mind/traverse.ts +321 -8
- package/src/mind/types.ts +15 -11
- package/src/store-sqlite.ts +92 -1
- package/src/store.ts +113 -7
- package/test/105-derive-through-reports-its-refusal.test.mjs +8 -5
- package/test/106-the-join-fires.test.mjs +21 -0
- package/test/111-the-cover-assembly-is-counted.test.mjs +8 -5
- package/test/128-the-leads-somewhere-pair-agrees.test.mjs +18 -12
- package/test/136-the-two-named-limits.test.mjs +3 -2
- package/test/137-the-law-lives-once-and-below.test.mjs +21 -0
- package/test/148-exact-shortcuts-agree.test.mjs +188 -0
- package/test/149-the-closure-engine.test.mjs +138 -0
- package/test/150-the-join-is-output-sensitive.test.mjs +66 -0
- package/test/151-the-cover-pays-for-what-it-reaches.test.mjs +142 -0
- package/test/152-the-read-side-names-as-the-write-side.test.mjs +146 -0
- package/test/153-a-cheaper-bound-is-looked-at-first.test.mjs +155 -0
- package/test/154-the-question-names-the-step.test.mjs +281 -0
- package/test/24-generalization.test.mjs +32 -0
- package/test/36-bloom.test.mjs +53 -0
- package/test/37-cluster-dispersion-fusion.test.mjs +75 -0
- package/test/48-recognise-turn-connective.test.mjs +3 -2
- package/test/55-cost-meter.test.mjs +4 -4
- package/test/90-connector-read-cap.test.mjs +7 -7
|
@@ -11,12 +11,14 @@
|
|
|
11
11
|
import { PASS, STEP } from "./graph-search.js";
|
|
12
12
|
import { gistOf, read, resolve } from "./primitives.js";
|
|
13
13
|
import { recognise } from "./recognition.js";
|
|
14
|
-
import {
|
|
15
|
-
import { closed, remainderOf, unaccountedBytes, unexplainedSpans, windowOf, } from "./derivation.js";
|
|
14
|
+
import { fusionLayer, walkLayer } from "./reasoning.js";
|
|
15
|
+
import { closed, closeOver, remainderOf, unaccountedBytes, unexplainedSpans, windowOf, } from "./derivation.js";
|
|
16
16
|
import { rItem } from "./trace.js";
|
|
17
17
|
import { unexplainedLabel } from "./rationale.js";
|
|
18
|
-
import { hubBound } from "./traverse.js";
|
|
19
|
-
import {
|
|
18
|
+
import { hubBound, offsetCanon, scaffoldExtents } from "./traverse.js";
|
|
19
|
+
import { windowIndex, witness } from "./evidence.js";
|
|
20
|
+
import { indexOf } from "../bytes.js";
|
|
21
|
+
import { Precomputed, } from "./pipeline-mechanism.js";
|
|
20
22
|
import { coverMechanism } from "./mechanisms/cover.js";
|
|
21
23
|
import { castMechanism } from "./mechanisms/cast.js";
|
|
22
24
|
import { confluenceMechanism } from "./mechanisms/confluence.js";
|
|
@@ -26,7 +28,7 @@ import { prefixMechanism } from "./mechanisms/prefix-completion.js";
|
|
|
26
28
|
import { recallMechanism } from "./mechanisms/recall.js";
|
|
27
29
|
// Re-exports: cover's pre-resolution helpers and the ALU adapter kept
|
|
28
30
|
// importable from the pipeline module (their historical home).
|
|
29
|
-
export {
|
|
31
|
+
export { offerConcepts, offerConnectors } from "./mechanisms/cover.js";
|
|
30
32
|
export { aluToMechanism } from "./mechanisms/alu.js";
|
|
31
33
|
// ── Extension dispatch (pre-loop parse) ─────────────────────────────────────
|
|
32
34
|
async function collectComputed(ctx, mechanisms, query) {
|
|
@@ -83,6 +85,13 @@ export async function think(ctx, query, mechs) {
|
|
|
83
85
|
if (query.length === 0)
|
|
84
86
|
return null;
|
|
85
87
|
ctx._edgeGuide = gistOf(ctx, query);
|
|
88
|
+
{
|
|
89
|
+
const asked = offsetCanon(ctx, query);
|
|
90
|
+
ctx._edgeAsked = {
|
|
91
|
+
bytes: asked,
|
|
92
|
+
index: windowIndex(asked, ctx.space.maxGroup),
|
|
93
|
+
};
|
|
94
|
+
}
|
|
86
95
|
ctx._edgeChoice.clear();
|
|
87
96
|
const t = ctx.trace?.enter("think", [rItem(query, "query")]);
|
|
88
97
|
const done = (answer, note) => {
|
|
@@ -197,12 +206,14 @@ export async function think(ctx, query, mechs) {
|
|
|
197
206
|
// below.
|
|
198
207
|
const incumbent = best;
|
|
199
208
|
const incumbentGrade = incumbent === null ? null : grade(incumbent.weight);
|
|
200
|
-
const regime =
|
|
209
|
+
const regime = worthDeclared(2 * STEP)
|
|
201
210
|
? "composition"
|
|
202
211
|
: "retrieval";
|
|
203
212
|
ctx.trace?.step("regimePrediction", [rItem(query, "query")], [], regime === "retrieval"
|
|
204
|
-
?
|
|
205
|
-
`
|
|
213
|
+
? (incumbentGrade !== null && incumbentGrade <= climbFloorGrade
|
|
214
|
+
? `retrieval regime — incumbent grade ${incumbentGrade} ≤ climb floor ${climbFloorGrade}, `
|
|
215
|
+
: `retrieval regime — grade ${bound} already reached by a mechanism run ahead, below climb floor ${climbFloorGrade}, `) +
|
|
216
|
+
`so no mechanism floored above that grade runs; CAST will not climb`
|
|
206
217
|
: `composition regime — ${incumbentGrade === null
|
|
207
218
|
? "no incumbent (nothing grounded)"
|
|
208
219
|
: `incumbent grade ${incumbentGrade}`} above climb floor ${climbFloorGrade}, so the full market and climb run`, undefined, {
|
|
@@ -210,38 +221,147 @@ export async function think(ctx, query, mechs) {
|
|
|
210
221
|
regime,
|
|
211
222
|
incumbentGrade,
|
|
212
223
|
climbFloorGrade,
|
|
224
|
+
...(bound !== Infinity ? { boundGrade: bound } : {}),
|
|
213
225
|
});
|
|
214
226
|
};
|
|
215
227
|
// Phase 3: grounding loop
|
|
216
228
|
// Per-mechanism accounting (src/meter.ts). The market's whole premise is
|
|
217
229
|
// that mechanisms compete on one cost scale — so the profiling read-out is
|
|
218
230
|
// also per-mechanism, uniformly: the loop never asks which one it holds.
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
231
|
+
//
|
|
232
|
+
// A CHEAPER BOUND IS LOOKED AT BEFORE A DEARER ONE IS PAID FOR.
|
|
233
|
+
//
|
|
234
|
+
// The declared order is the tie-break priority, and the pruning above is
|
|
235
|
+
// only as strong as the incumbent it has: a mechanism floored LOWER than the
|
|
236
|
+
// one about to invest, but declared after it, could not prune it. Measured
|
|
237
|
+
// on the 31.7M-node store: a lowercased dialogue turn (#97 of the battery)
|
|
238
|
+
// was won by recall at grade 1 — after CAST (floor grade 2) had paid the
|
|
239
|
+
// consensus climb and the weave, confluence (3) a reach climb, and extraction
|
|
240
|
+
// and reference their reads: ~10 s of a 12.6 s response, for candidates that
|
|
241
|
+
// could not win.
|
|
242
|
+
//
|
|
243
|
+
// So before mechanism `m` first-touches anything, every LATER mechanism whose
|
|
244
|
+
// bound is strictly lower runs AHEAD of it, cheapest bound first, and the
|
|
245
|
+
// lowest grade any of them reaches becomes `bound`. A mechanism whose floor
|
|
246
|
+
// grade exceeds `bound` is then skipped. THE DECISION IS UNCHANGED — the
|
|
247
|
+
// same candidate wins as in the declared order:
|
|
248
|
+
// • a mechanism `p` run ahead with best grade g bounds the final grade by
|
|
249
|
+
// g: in the declared order p either runs (its candidate is weighed) or is
|
|
250
|
+
// pruned by an incumbent already at or below p's floor ≤ g;
|
|
251
|
+
// • so a mechanism floored above `bound` has only candidates the final
|
|
252
|
+
// winner strictly outgrades — and with every candidate above `bound`
|
|
253
|
+
// dropped, every mechanism floored at or below it meets the same
|
|
254
|
+
// run-or-prune decision (`f < incumbent` iff `f < min(incumbent,
|
|
255
|
+
// bound + 1)` for f ≤ bound) and yields the same candidates;
|
|
256
|
+
// • and the winner is chosen from the candidates at or below `bound`, in
|
|
257
|
+
// declared order — `consider` replays them where they are declared.
|
|
258
|
+
// Equal-grade floors are NOT skipped (≤, not <): a mechanism declared earlier
|
|
259
|
+
// keeps the tie it would have won. Running `p` ahead is never extra work:
|
|
260
|
+
// what prunes p in the declared order is a candidate at or below p's floor,
|
|
261
|
+
// which only a mechanism floored at or below it can produce — and every such
|
|
262
|
+
// mechanism is either already run or run ahead of p.
|
|
263
|
+
//
|
|
264
|
+
// The bound is learnt by asking `floor` with a `worthRunning` that refuses:
|
|
265
|
+
// under the investment discipline (pipeline-mechanism.ts) a floor that cannot
|
|
266
|
+
// pay returns its bound UNINVESTED, so the question costs no analysis.
|
|
267
|
+
const refuse = () => false;
|
|
268
|
+
const probed = new Array(mechanisms.length);
|
|
269
|
+
const probeGrade = async (i) => {
|
|
270
|
+
if (probed[i] === undefined) {
|
|
271
|
+
const f = await mechanisms[i].floor(ctx, query, pre, refuse);
|
|
272
|
+
probed[i] = f === null ? null : grade(f);
|
|
273
|
+
}
|
|
274
|
+
return probed[i];
|
|
275
|
+
};
|
|
276
|
+
/** Per mechanism: its floor once computed, and its results once run. */
|
|
277
|
+
const floors = new Map();
|
|
278
|
+
const runs = new Map();
|
|
279
|
+
let bound = Infinity;
|
|
280
|
+
const worthAhead = (floor) => grade(floor) <
|
|
281
|
+
Math.min(best === null ? Infinity : grade(best.weight), bound);
|
|
282
|
+
const worthDeclared = (floor) => worthRunning(floor) && grade(floor) <= bound;
|
|
283
|
+
const floorOf = async (i, worth) => {
|
|
284
|
+
if (floors.has(i))
|
|
285
|
+
return floors.get(i);
|
|
286
|
+
const mech = mechanisms[i];
|
|
223
287
|
const floor = meter
|
|
224
|
-
? await meter.time(`${mech.name}.floor`, () => mech.floor(ctx, query, pre,
|
|
225
|
-
: await mech.floor(ctx, query, pre,
|
|
288
|
+
? await meter.time(`${mech.name}.floor`, () => mech.floor(ctx, query, pre, worth))
|
|
289
|
+
: await mech.floor(ctx, query, pre, worth);
|
|
226
290
|
if (meter) {
|
|
227
291
|
if (floor === null)
|
|
228
292
|
meter.mechanismSkips++;
|
|
229
293
|
else
|
|
230
294
|
meter.mechanismFloors++;
|
|
231
295
|
}
|
|
296
|
+
floors.set(i, floor);
|
|
297
|
+
return floor;
|
|
298
|
+
};
|
|
299
|
+
const runOf = async (i) => {
|
|
300
|
+
let results = runs.get(i);
|
|
301
|
+
if (results === undefined) {
|
|
302
|
+
const mech = mechanisms[i];
|
|
303
|
+
if (meter)
|
|
304
|
+
meter.mechanismRuns++;
|
|
305
|
+
results = meter
|
|
306
|
+
? await meter.time(`${mech.name}.run`, () => mech.run(ctx, query, pre))
|
|
307
|
+
: await mech.run(ctx, query, pre);
|
|
308
|
+
runs.set(i, results);
|
|
309
|
+
}
|
|
310
|
+
return results;
|
|
311
|
+
};
|
|
312
|
+
const runAhead = async (mi) => {
|
|
313
|
+
const g = await probeGrade(mi);
|
|
314
|
+
if (g === null)
|
|
315
|
+
return;
|
|
316
|
+
const ahead = [];
|
|
317
|
+
for (let j = mi + 1; j < mechanisms.length; j++) {
|
|
318
|
+
if (floors.has(j))
|
|
319
|
+
continue;
|
|
320
|
+
const gj = await probeGrade(j);
|
|
321
|
+
if (gj !== null && gj < g)
|
|
322
|
+
ahead.push([gj, j]);
|
|
323
|
+
}
|
|
324
|
+
ahead.sort((a, b) => a[0] - b[0] || a[1] - b[1]);
|
|
325
|
+
for (const [gj, j] of ahead) {
|
|
326
|
+
// Only what the declared order would also run: a bound that cannot beat
|
|
327
|
+
// what is already held is not even asked for its real floor.
|
|
328
|
+
if (!(gj < Math.min(best === null ? Infinity : grade(best.weight), bound))) {
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
const floor = await floorOf(j, worthAhead);
|
|
332
|
+
if (floor === null || !worthAhead(floor))
|
|
333
|
+
continue;
|
|
334
|
+
ctx.trace?.step("runAhead", [], [], `${mechanisms[j].name} runs ahead of ${mechanisms[mi].name} — its floor (grade ${grade(floor)}) is below ${mechanisms[mi].name}'s (grade ${g}), so its result bounds what ${mechanisms[mi].name} could win`);
|
|
335
|
+
for (const r of await runOf(j)) {
|
|
336
|
+
// `consider` drops an empty answer, so it bounds nothing.
|
|
337
|
+
if (r.bytes.length === 0)
|
|
338
|
+
continue;
|
|
339
|
+
bound = Math.min(bound, grade(weigh(r.accounted, r.moves)));
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
for (let mi = 0; mi < mechanisms.length; mi++) {
|
|
344
|
+
const mech = mechanisms[mi];
|
|
345
|
+
if (mi > 0) {
|
|
346
|
+
await runAhead(mi);
|
|
347
|
+
reportRegime();
|
|
348
|
+
}
|
|
349
|
+
const floor = await floorOf(mi, worthDeclared);
|
|
232
350
|
if (floor === null) {
|
|
233
351
|
ctx.trace?.step("skipMechanism", [], [], `${mech.name} skipped — structural precondition failed`);
|
|
234
352
|
continue;
|
|
235
353
|
}
|
|
354
|
+
if (grade(floor) > bound) {
|
|
355
|
+
if (meter)
|
|
356
|
+
meter.mechanismsBounded++;
|
|
357
|
+
ctx.trace?.step("skipMechanism", [], [], `${mech.name} skipped — floor ${floor} cannot beat grade ${bound}, already reached by a mechanism run ahead`);
|
|
358
|
+
continue;
|
|
359
|
+
}
|
|
236
360
|
if (!worthRunning(floor)) {
|
|
237
361
|
ctx.trace?.step("skipMechanism", [], [], `${mech.name} skipped — floor ${floor} cannot beat incumbent (grade ${grade(best.weight)})`);
|
|
238
362
|
continue;
|
|
239
363
|
}
|
|
240
|
-
|
|
241
|
-
meter.mechanismRuns++;
|
|
242
|
-
const results = meter
|
|
243
|
-
? await meter.time(`${mech.name}.run`, () => mech.run(ctx, query, pre))
|
|
244
|
-
: await mech.run(ctx, query, pre);
|
|
364
|
+
const results = await runOf(mi);
|
|
245
365
|
for (const r of results) {
|
|
246
366
|
// ONE FORMULA, EVERY CANDIDATE: the chart's derivation reports how many
|
|
247
367
|
// discrete moves it made and which bytes it could not recognise; the
|
|
@@ -352,19 +472,28 @@ export async function think(ctx, query, mechs) {
|
|
|
352
472
|
// without evidence stays owed, and a later transition pays it only by carrying
|
|
353
473
|
// it (the law reads the window; see derivation.ts). Same reading, one
|
|
354
474
|
// definition — not a second spelling of it here.
|
|
355
|
-
const
|
|
475
|
+
const priced = [
|
|
356
476
|
...decided.accounted,
|
|
357
477
|
...pre.computed.map((u) => [u.i, u.j]),
|
|
358
|
-
]
|
|
478
|
+
];
|
|
479
|
+
const explained = priced.filter(([a, b]) => windowOf([a, b], answer, query, ctx.space.maxGroup) !== null);
|
|
480
|
+
// THE DERIVATION IS BORN OWING ITS DISCRIMINATIVE MATERIAL. The bytes a
|
|
481
|
+
// corpus-global scaffolding window reaches (traverse.ts, `scaffoldExtents`)
|
|
482
|
+
// are nobody's debt — otherwise a later step could claim to pay them by
|
|
483
|
+
// restating ` is `, which every fact holds, and the law (which measures
|
|
484
|
+
// carrying by any window of what is owed) would admit it; the substitution
|
|
485
|
+
// bridge reads gaps the same way (`explainedSpan`). PRICING is untouched:
|
|
486
|
+
// the ladder still charges every unexplained byte, because for a question
|
|
487
|
+
// made of nothing but scaffolding (`How are you today?`) covering those bytes
|
|
488
|
+
// IS the evidence.
|
|
489
|
+
const scaffold = scaffoldExtents(ctx, query);
|
|
490
|
+
const paid = remainderOf(query.length, [...explained, ...scaffold], ctx.space.maxGroup);
|
|
359
491
|
// WHAT THE CONSTRUCTION WITHHOLDS, at or above one quantum: the difference between
|
|
360
492
|
// the remainder paid in full and the remainder paid by carrying. Both readings
|
|
361
|
-
// are the law's, so the floor is applied once and in one place
|
|
362
|
-
|
|
363
|
-
...decided.accounted,
|
|
364
|
-
...pre.computed.map((u) => [u.i, u.j]),
|
|
365
|
-
], ctx.space.maxGroup);
|
|
366
|
-
const paid = remainderOf(query.length, explained, ctx.space.maxGroup);
|
|
493
|
+
// are the law's, so the floor is applied once and in one place — and the
|
|
494
|
+
// paid-in-full reading is computed only when a meter will read it.
|
|
367
495
|
if (ctx.meter) {
|
|
496
|
+
const paidInFull = remainderOf(query.length, priced, ctx.space.maxGroup);
|
|
368
497
|
ctx.meter.groundingWithheldBytes += unaccountedBytes(paid) -
|
|
369
498
|
unaccountedBytes(paidInFull);
|
|
370
499
|
}
|
|
@@ -378,8 +507,23 @@ export async function think(ctx, query, mechs) {
|
|
|
378
507
|
};
|
|
379
508
|
const uncovered = state.remainder;
|
|
380
509
|
// ── Post-grounding, gated by the declaration and the remainder ────────
|
|
510
|
+
// WHAT THE GROUNDING SPOKE FOR, when it did not declare it: the forms inside
|
|
511
|
+
// the answer that the ASKER already holds. An answer is the asker's material
|
|
512
|
+
// plus what the corpus added — the fact's own value — and only the former was
|
|
513
|
+
// spoken for: re-entering it walks back to the question. The latter is what a
|
|
514
|
+
// chain continues THROUGH. Consuming every form recognised in the answer
|
|
515
|
+
// consumed that too, so a chain could start only where recognition happened
|
|
516
|
+
// to miss the next entity — measured on 133 held-out 2Wiki compositional
|
|
517
|
+
// questions, 3 pivot steps in all once interior recognition named the entity
|
|
518
|
+
// inside every fact. Witnessed exactly, as `chooseNext`'s exact tier reads the
|
|
519
|
+
// question (evidence.ts); a form below one window cannot be witnessed, and is
|
|
520
|
+
// consumed as before.
|
|
521
|
+
const asked = ctx._edgeAsked;
|
|
381
522
|
const preConsumed = declaredUsed ??
|
|
382
|
-
new Set(recognise(ctx, answer).sites
|
|
523
|
+
new Set(recognise(ctx, answer).sites
|
|
524
|
+
.filter((s) => asked === null || s.end - s.start < ctx.space.maxGroup ||
|
|
525
|
+
witness(offsetCanon(ctx, answer.subarray(s.start, s.end)), [asked.index], ctx.space.maxGroup).complete)
|
|
526
|
+
.map((s) => s.payload));
|
|
383
527
|
// A grounding that DECLARED itself complete is not extended: the answer is
|
|
384
528
|
// already a trained form's own continuation, reached through an identity
|
|
385
529
|
// claim about the query, so a multi-hop pivot could only chain past the
|
|
@@ -408,7 +552,15 @@ export async function think(ctx, query, mechs) {
|
|
|
408
552
|
// `preConsumed` is derived by re-recognising the answer — "everything in
|
|
409
553
|
// it", not "what it voiced" — and a containment rule over that would
|
|
410
554
|
// suppress every pivot the answer legitimately contains.
|
|
411
|
-
|
|
555
|
+
//
|
|
556
|
+
// …and a continuation the ANSWER ITSELF holds was voiced, not withheld. A
|
|
557
|
+
// substitution that answers with its anchor's own continuation (`The director
|
|
558
|
+
// of Beat Girl is Edmond T. Gréville.`) declared that anchor used, so reading
|
|
559
|
+
// its continuations as withheld refused every pivot inside the answer — the
|
|
560
|
+
// chain could never step past the entity the first hop introduced.
|
|
561
|
+
const voiced = declaredUsed === undefined ? [] : [...declaredUsed].flatMap((id) => ctx.store.nextFirst(id, hubBound(ctx))
|
|
562
|
+
.map((n) => read(ctx, n))
|
|
563
|
+
.filter((v) => indexOf(answer, v, 0) < 0));
|
|
412
564
|
// WHAT THIS BRANCH READ, published where it was read. Post-grounding decides
|
|
413
565
|
// by the DECLARATION (`decided.used`, which becomes `voiced`), by what the
|
|
414
566
|
// recognition already consumed (`preConsumed`) and by the derivation's own
|
|
@@ -451,73 +603,51 @@ export async function think(ctx, query, mechs) {
|
|
|
451
603
|
meter.postGroundingRemainderSpans += uncovered.length;
|
|
452
604
|
meter.postGroundingRemainderBytes += unaccountedBytes(uncovered);
|
|
453
605
|
}
|
|
454
|
-
// THE
|
|
455
|
-
//
|
|
456
|
-
//
|
|
457
|
-
//
|
|
458
|
-
//
|
|
459
|
-
//
|
|
460
|
-
//
|
|
461
|
-
//
|
|
606
|
+
// ── THE CLOSURE ENGINE ───────────────────────────────────────────────
|
|
607
|
+
//
|
|
608
|
+
// The grounding's state is CLOSED under the law by two layers, in order: the
|
|
609
|
+
// multi-hop WALK (`walkLayer`: a forward absorb or a pivot, offered one at a
|
|
610
|
+
// time) and the multi-topic FUSION (`fusionLayer`: one composed transition).
|
|
611
|
+
// Every step either layer offers goes through the same `closure` and the same
|
|
612
|
+
// law; this function no longer sequences them or gates them by hand.
|
|
613
|
+
//
|
|
614
|
+
// WHAT USED TO BE TWO HAND-WRITTEN GATES IS NOW THE LAW'S, OR THE LAYER'S:
|
|
615
|
+
// • a declared-complete grounding (`fixed`) admits no transition — the
|
|
616
|
+
// engine enters no layer for it (the law's first clause), which is the
|
|
617
|
+
// walk-skip and the fusion-skip this branch used to spell separately;
|
|
618
|
+
// • a CLOSED derivation has nothing left for a second topic to account for,
|
|
619
|
+
// so the fusion layer does not ENGAGE — read off the state the walk
|
|
620
|
+
// reached, the one fusion is actually offered against.
|
|
621
|
+
//
|
|
622
|
+
// What the fusion needs from the grounding — whether its substance is purely
|
|
623
|
+
// computed (`unclimbed`) and where it stands in the query (`primarySpans`) —
|
|
624
|
+
// is the grounding's own evidence, resolved here where both readings are in
|
|
625
|
+
// hand.
|
|
462
626
|
//
|
|
463
|
-
//
|
|
464
|
-
//
|
|
465
|
-
//
|
|
466
|
-
//
|
|
467
|
-
//
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
: await reason(ctx, query, state, preConsumed, pre, voiced);
|
|
471
|
-
const reasoned = extension ?? state;
|
|
472
|
-
// Fuse only when the query has a genuine REMAINDER no mechanism's
|
|
473
|
-
// structural evidence touched at all. `decided.accounted` alone
|
|
474
|
-
// undercounts this: it is a COST-LADDER quantity (cover.ts prices its
|
|
475
|
-
// masked/computed spans at near-zero and deliberately leaves them out of
|
|
476
|
-
// `accounted` so PASS-bridged bytes are still charged), not a coverage
|
|
477
|
-
// one — a query fully explained by one computed span plus bridged
|
|
478
|
-
// connectors can report `accounted: []` while nothing is actually left
|
|
479
|
-
// unexplained. The genuine remainder is what NEITHER the winning
|
|
480
|
-
// candidate's accounted spans NOR any recognised extension's computed
|
|
481
|
-
// span (`pre.computed` — every mechanism's parse() output, ALU included)
|
|
482
|
-
// ever touched. A remainder under one river-fold quantum (W, the same
|
|
483
|
-
// floor cover.ts's restatedSpan and the honesty-density bar above both
|
|
484
|
-
// use) is bridging punctuation/whitespace, never a second topic —
|
|
485
|
-
// observed: a single space between two fully-computed arithmetic spans
|
|
486
|
-
// ("2+2 3+3") registered as "unaccounted" and pulled in an unrelated
|
|
487
|
-
// corpus fact, corrupting "4 6" into "4 63".
|
|
488
|
-
// THE GATE ASKS THE LAW, and that is an OPTIMISATION, not a tidy-up: the state
|
|
489
|
-
// above ALREADY carries the remainder (`remainderOf`, per-span, with the W
|
|
490
|
-
// floor applied), so asking it costs nothing, while the total this line used to
|
|
491
|
-
// compute (`unaccounted(explained)`) was one more sum over the spans on every
|
|
492
|
-
// response. The two readings are the same condition, not two: the ACCOUNTING
|
|
493
|
-
// applies the same W floor the gate does, so a gap below one quantum never
|
|
494
|
-
// survives into `explained` and the total cannot reach W without some single
|
|
495
|
-
// gap reaching it. Measured over twelve constructions at W = 4 (test/136.3,
|
|
496
|
-
// which pins the equivalence and both sides of it).
|
|
497
|
-
// Whether the winning candidate's entire recognised substance is
|
|
498
|
-
// COMPUTED — every accounted span exactly a pre.computed span, nothing
|
|
499
|
-
// from a genuinely recognised/climbed site. fuseAttention's lone-root
|
|
500
|
-
// shortcut assumes a single point of attention already IS primary's own
|
|
501
|
-
// source; that assumption is exactly backwards for a pure computation
|
|
502
|
-
// (an ALU result has no anchor of its own) — see fuseAttention's
|
|
503
|
-
// `unclimbed` parameter, gated there by Attention.breadth so a
|
|
504
|
-
// coincidental echo (which this flag alone cannot distinguish) is still
|
|
505
|
-
// rejected.
|
|
627
|
+
// Whether the winning candidate's entire recognised substance is COMPUTED —
|
|
628
|
+
// every accounted span exactly a pre.computed span, nothing from a genuinely
|
|
629
|
+
// recognised/climbed site. fuseAttention's lone-root shortcut assumes a
|
|
630
|
+
// single point of attention already IS primary's own source; that assumption
|
|
631
|
+
// is exactly backwards for a pure computation (an ALU result has no anchor of
|
|
632
|
+
// its own) — gated there by Attention.breadth so a coincidental echo (which
|
|
633
|
+
// this flag alone cannot distinguish) is still rejected.
|
|
506
634
|
const unclimbed = state.accounted.length > 0 &&
|
|
507
635
|
state.accounted.every(([i, j]) => pre.computed.some((u) => u.i === i && u.j === j));
|
|
508
|
-
// Where the winning grounding stands in the query — fusion places primary
|
|
509
|
-
//
|
|
510
|
-
//
|
|
511
|
-
//
|
|
512
|
-
//
|
|
513
|
-
// read here for POSITION instead of for coverage — and resolved here, where
|
|
514
|
-
// both readings are in hand, rather than inside fuseAttention.
|
|
636
|
+
// Where the winning grounding stands in the query — fusion places primary by
|
|
637
|
+
// it. `accounted` is the cost-ladder read and is authoritative when
|
|
638
|
+
// non-empty; when it is empty the grounding is a pure COMPUTATION, whose
|
|
639
|
+
// evidence is its computed span — the cost-ladder-vs-coverage distinction
|
|
640
|
+
// `explained` above draws, read here for POSITION instead of coverage.
|
|
515
641
|
const primarySpans = state.accounted.length > 0
|
|
516
642
|
? state.accounted
|
|
517
643
|
: pre.computed.map((u) => [u.i, u.j]);
|
|
518
|
-
const fused =
|
|
519
|
-
|
|
520
|
-
|
|
644
|
+
const fused = await closeOver(state, query, ctx.space.maxGroup, [
|
|
645
|
+
walkLayer(ctx, query, preConsumed, pre, voiced),
|
|
646
|
+
{
|
|
647
|
+
...fusionLayer(ctx, query, pre, unclimbed, primarySpans),
|
|
648
|
+
engages: (d) => !closed(d),
|
|
649
|
+
},
|
|
650
|
+
], meter ? (name, walk) => meter.time(name, walk) : undefined);
|
|
521
651
|
done(fused.product,
|
|
522
652
|
// NO CLAIM ABOUT FUSION HERE. `fuseAttention` is entered whenever a
|
|
523
653
|
// remainder ≥ W exists and returns early when there is nothing to bridge, so
|
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
import { Vec } from "../vec.js";
|
|
2
2
|
import { Sema } from "../sema.js";
|
|
3
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
4
|
/** The {@link perceive} memo key: the span's content PLUS the boundary set it
|
|
10
5
|
* was folded under. The tree is a function of BOTH — the same bytes fold
|
|
11
6
|
* plainly with no boundaries and into a left-nested stable-prefix shape with
|
|
@@ -59,6 +54,31 @@ export declare function foldTree(ctx: MindContext, n: Sema, start: number, visit
|
|
|
59
54
|
end: number;
|
|
60
55
|
node: number | null;
|
|
61
56
|
};
|
|
57
|
+
/** The EXACT content-addressed node of a byte stream — `foldTree(perceive)`,
|
|
58
|
+
* read for identity alone.
|
|
59
|
+
*
|
|
60
|
+
* A fold names a branch only when every child is named, so identity needs the
|
|
61
|
+
* fold's SHAPE and the store's answer per node, never its vectors:
|
|
62
|
+
* {@link contentIdentity} walks the same shape (geometry.ts — one grouping
|
|
63
|
+
* rule, two algebras) and asks the store bottom-up, building no D-dimensional
|
|
64
|
+
* gist and leaving nothing in the perception memo. Each node is named the
|
|
65
|
+
* way the store's write side names it ({@link branchNaming}). `test/148` pins
|
|
66
|
+
* the agreement with the full fold over random and corpus spans. */
|
|
67
|
+
export declare function exactNode(ctx: MindContext, bytes: Uint8Array): number | null;
|
|
68
|
+
/** {@link exactNode}, with whether the span's own name was found only through
|
|
69
|
+
* its BYTES — its children named no branch, and the flat node over the same
|
|
70
|
+
* bytes did ({@link branchNaming}). That is where the exact lookup used to
|
|
71
|
+
* MISS, so it is where {@link resolve} still asks the canonical class: the
|
|
72
|
+
* class may hold the learnt member that leads somewhere, which a flat index
|
|
73
|
+
* entry need not (measured: `tonight` named an edge-less window and
|
|
74
|
+
* pre-empted the case-folded `Tonight` whose edge a composition stood on).
|
|
75
|
+
* Recognition's probes reach it through `resolve`; asking it again for the
|
|
76
|
+
* perceived tree's own byte-named groups changed none of 116 real queries and
|
|
77
|
+
* no test, so it is not asked there. */
|
|
78
|
+
export declare function exactNaming(ctx: MindContext, bytes: Uint8Array): {
|
|
79
|
+
id: number | null;
|
|
80
|
+
byBytes: boolean;
|
|
81
|
+
};
|
|
62
82
|
/** The canonical node id of a byte span: perceive it in isolation — the way
|
|
63
83
|
* training did — and recover its root bottom-up. Returns null if any part is
|
|
64
84
|
* unknown. */
|