@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
package/src/mind/pipeline.ts
CHANGED
|
@@ -14,9 +14,10 @@ import { PASS, STEP } from "./graph-search.js";
|
|
|
14
14
|
import type { ComputedSpan } from "../extension.js";
|
|
15
15
|
import { gistOf, read, resolve } from "./primitives.js";
|
|
16
16
|
import { recognise } from "./recognition.js";
|
|
17
|
-
import {
|
|
17
|
+
import { fusionLayer, walkLayer } from "./reasoning.js";
|
|
18
18
|
import {
|
|
19
19
|
closed,
|
|
20
|
+
closeOver,
|
|
20
21
|
type DerivationState,
|
|
21
22
|
remainderOf,
|
|
22
23
|
type Span,
|
|
@@ -26,8 +27,14 @@ import {
|
|
|
26
27
|
} from "./derivation.js";
|
|
27
28
|
import { rItem } from "./trace.js";
|
|
28
29
|
import { unexplainedLabel } from "./rationale.js";
|
|
29
|
-
import { hubBound } from "./traverse.js";
|
|
30
|
-
import {
|
|
30
|
+
import { hubBound, offsetCanon, scaffoldExtents } from "./traverse.js";
|
|
31
|
+
import { windowIndex, witness } from "./evidence.js";
|
|
32
|
+
import { indexOf } from "../bytes.js";
|
|
33
|
+
import {
|
|
34
|
+
type MechanismResult,
|
|
35
|
+
type PipelineMechanism,
|
|
36
|
+
Precomputed,
|
|
37
|
+
} from "./pipeline-mechanism.js";
|
|
31
38
|
import { coverMechanism } from "./mechanisms/cover.js";
|
|
32
39
|
import { castMechanism } from "./mechanisms/cast.js";
|
|
33
40
|
import { confluenceMechanism } from "./mechanisms/confluence.js";
|
|
@@ -38,7 +45,7 @@ import { recallMechanism } from "./mechanisms/recall.js";
|
|
|
38
45
|
|
|
39
46
|
// Re-exports: cover's pre-resolution helpers and the ALU adapter kept
|
|
40
47
|
// importable from the pipeline module (their historical home).
|
|
41
|
-
export {
|
|
48
|
+
export { offerConcepts, offerConnectors } from "./mechanisms/cover.js";
|
|
42
49
|
export { aluToMechanism } from "./mechanisms/alu.js";
|
|
43
50
|
|
|
44
51
|
// ── Extension dispatch (pre-loop parse) ─────────────────────────────────────
|
|
@@ -161,6 +168,10 @@ export interface RegimePredictionData {
|
|
|
161
168
|
* CAST's floor) — the bar the incumbent must sit at or below for the
|
|
162
169
|
* consensus climb to be skipped. */
|
|
163
170
|
climbFloorGrade: number;
|
|
171
|
+
/** The lowest grade reached by a mechanism run AHEAD of a dearer one (see
|
|
172
|
+
* the grounding loop), when one ran and grounded: a bound below
|
|
173
|
+
* `climbFloorGrade` makes the regime retrieval whatever the incumbent. */
|
|
174
|
+
boundGrade?: number;
|
|
164
175
|
}
|
|
165
176
|
|
|
166
177
|
/** Think: a single lightest-derivation exploration of the Sema graph.
|
|
@@ -180,6 +191,13 @@ export async function think(
|
|
|
180
191
|
if (query.length === 0) return null;
|
|
181
192
|
|
|
182
193
|
ctx._edgeGuide = gistOf(ctx, query);
|
|
194
|
+
{
|
|
195
|
+
const asked = offsetCanon(ctx, query);
|
|
196
|
+
ctx._edgeAsked = {
|
|
197
|
+
bytes: asked,
|
|
198
|
+
index: windowIndex(asked, ctx.space.maxGroup),
|
|
199
|
+
};
|
|
200
|
+
}
|
|
183
201
|
ctx._edgeChoice.clear();
|
|
184
202
|
|
|
185
203
|
const t = ctx.trace?.enter("think", [rItem(query, "query")]);
|
|
@@ -335,7 +353,7 @@ export async function think(
|
|
|
335
353
|
// below.
|
|
336
354
|
const incumbent = best as Candidate | null;
|
|
337
355
|
const incumbentGrade = incumbent === null ? null : grade(incumbent.weight);
|
|
338
|
-
const regime: "retrieval" | "composition" =
|
|
356
|
+
const regime: "retrieval" | "composition" = worthDeclared(2 * STEP)
|
|
339
357
|
? "composition"
|
|
340
358
|
: "retrieval";
|
|
341
359
|
ctx.trace?.step(
|
|
@@ -343,8 +361,10 @@ export async function think(
|
|
|
343
361
|
[rItem(query, "query")],
|
|
344
362
|
[],
|
|
345
363
|
regime === "retrieval"
|
|
346
|
-
?
|
|
347
|
-
`
|
|
364
|
+
? (incumbentGrade !== null && incumbentGrade <= climbFloorGrade
|
|
365
|
+
? `retrieval regime — incumbent grade ${incumbentGrade} ≤ climb floor ${climbFloorGrade}, `
|
|
366
|
+
: `retrieval regime — grade ${bound} already reached by a mechanism run ahead, below climb floor ${climbFloorGrade}, `) +
|
|
367
|
+
`so no mechanism floored above that grade runs; CAST will not climb`
|
|
348
368
|
: `composition regime — ${
|
|
349
369
|
incumbentGrade === null
|
|
350
370
|
? "no incumbent (nothing grounded)"
|
|
@@ -356,6 +376,7 @@ export async function think(
|
|
|
356
376
|
regime,
|
|
357
377
|
incumbentGrade,
|
|
358
378
|
climbFloorGrade,
|
|
379
|
+
...(bound !== Infinity ? { boundGrade: bound } : {}),
|
|
359
380
|
} satisfies RegimePredictionData,
|
|
360
381
|
);
|
|
361
382
|
};
|
|
@@ -363,19 +384,139 @@ export async function think(
|
|
|
363
384
|
// Per-mechanism accounting (src/meter.ts). The market's whole premise is
|
|
364
385
|
// that mechanisms compete on one cost scale — so the profiling read-out is
|
|
365
386
|
// also per-mechanism, uniformly: the loop never asks which one it holds.
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
387
|
+
//
|
|
388
|
+
// A CHEAPER BOUND IS LOOKED AT BEFORE A DEARER ONE IS PAID FOR.
|
|
389
|
+
//
|
|
390
|
+
// The declared order is the tie-break priority, and the pruning above is
|
|
391
|
+
// only as strong as the incumbent it has: a mechanism floored LOWER than the
|
|
392
|
+
// one about to invest, but declared after it, could not prune it. Measured
|
|
393
|
+
// on the 31.7M-node store: a lowercased dialogue turn (#97 of the battery)
|
|
394
|
+
// was won by recall at grade 1 — after CAST (floor grade 2) had paid the
|
|
395
|
+
// consensus climb and the weave, confluence (3) a reach climb, and extraction
|
|
396
|
+
// and reference their reads: ~10 s of a 12.6 s response, for candidates that
|
|
397
|
+
// could not win.
|
|
398
|
+
//
|
|
399
|
+
// So before mechanism `m` first-touches anything, every LATER mechanism whose
|
|
400
|
+
// bound is strictly lower runs AHEAD of it, cheapest bound first, and the
|
|
401
|
+
// lowest grade any of them reaches becomes `bound`. A mechanism whose floor
|
|
402
|
+
// grade exceeds `bound` is then skipped. THE DECISION IS UNCHANGED — the
|
|
403
|
+
// same candidate wins as in the declared order:
|
|
404
|
+
// • a mechanism `p` run ahead with best grade g bounds the final grade by
|
|
405
|
+
// g: in the declared order p either runs (its candidate is weighed) or is
|
|
406
|
+
// pruned by an incumbent already at or below p's floor ≤ g;
|
|
407
|
+
// • so a mechanism floored above `bound` has only candidates the final
|
|
408
|
+
// winner strictly outgrades — and with every candidate above `bound`
|
|
409
|
+
// dropped, every mechanism floored at or below it meets the same
|
|
410
|
+
// run-or-prune decision (`f < incumbent` iff `f < min(incumbent,
|
|
411
|
+
// bound + 1)` for f ≤ bound) and yields the same candidates;
|
|
412
|
+
// • and the winner is chosen from the candidates at or below `bound`, in
|
|
413
|
+
// declared order — `consider` replays them where they are declared.
|
|
414
|
+
// Equal-grade floors are NOT skipped (≤, not <): a mechanism declared earlier
|
|
415
|
+
// keeps the tie it would have won. Running `p` ahead is never extra work:
|
|
416
|
+
// what prunes p in the declared order is a candidate at or below p's floor,
|
|
417
|
+
// which only a mechanism floored at or below it can produce — and every such
|
|
418
|
+
// mechanism is either already run or run ahead of p.
|
|
419
|
+
//
|
|
420
|
+
// The bound is learnt by asking `floor` with a `worthRunning` that refuses:
|
|
421
|
+
// under the investment discipline (pipeline-mechanism.ts) a floor that cannot
|
|
422
|
+
// pay returns its bound UNINVESTED, so the question costs no analysis.
|
|
423
|
+
const refuse = () => false;
|
|
424
|
+
const probed: Array<number | null | undefined> = new Array(
|
|
425
|
+
mechanisms.length,
|
|
426
|
+
);
|
|
427
|
+
const probeGrade = async (i: number): Promise<number | null> => {
|
|
428
|
+
if (probed[i] === undefined) {
|
|
429
|
+
const f = await mechanisms[i].floor(ctx, query, pre, refuse);
|
|
430
|
+
probed[i] = f === null ? null : grade(f);
|
|
431
|
+
}
|
|
432
|
+
return probed[i]!;
|
|
433
|
+
};
|
|
434
|
+
/** Per mechanism: its floor once computed, and its results once run. */
|
|
435
|
+
const floors = new Map<number, number | null>();
|
|
436
|
+
const runs = new Map<number, MechanismResult[]>();
|
|
437
|
+
let bound = Infinity;
|
|
438
|
+
const worthAhead = (floor: number) =>
|
|
439
|
+
grade(floor) <
|
|
440
|
+
Math.min(best === null ? Infinity : grade(best.weight), bound);
|
|
441
|
+
const worthDeclared = (floor: number) =>
|
|
442
|
+
worthRunning(floor) && grade(floor) <= bound;
|
|
443
|
+
const floorOf = async (
|
|
444
|
+
i: number,
|
|
445
|
+
worth: (floor: number) => boolean,
|
|
446
|
+
): Promise<number | null> => {
|
|
447
|
+
if (floors.has(i)) return floors.get(i)!;
|
|
448
|
+
const mech = mechanisms[i];
|
|
369
449
|
const floor = meter
|
|
370
450
|
? await meter.time(
|
|
371
451
|
`${mech.name}.floor`,
|
|
372
|
-
() => mech.floor(ctx, query, pre,
|
|
452
|
+
() => mech.floor(ctx, query, pre, worth),
|
|
373
453
|
)
|
|
374
|
-
: await mech.floor(ctx, query, pre,
|
|
454
|
+
: await mech.floor(ctx, query, pre, worth);
|
|
375
455
|
if (meter) {
|
|
376
456
|
if (floor === null) meter.mechanismSkips++;
|
|
377
457
|
else meter.mechanismFloors++;
|
|
378
458
|
}
|
|
459
|
+
floors.set(i, floor);
|
|
460
|
+
return floor;
|
|
461
|
+
};
|
|
462
|
+
const runOf = async (i: number): Promise<MechanismResult[]> => {
|
|
463
|
+
let results = runs.get(i);
|
|
464
|
+
if (results === undefined) {
|
|
465
|
+
const mech = mechanisms[i];
|
|
466
|
+
if (meter) meter.mechanismRuns++;
|
|
467
|
+
results = meter
|
|
468
|
+
? await meter.time(`${mech.name}.run`, () => mech.run(ctx, query, pre))
|
|
469
|
+
: await mech.run(ctx, query, pre);
|
|
470
|
+
runs.set(i, results);
|
|
471
|
+
}
|
|
472
|
+
return results;
|
|
473
|
+
};
|
|
474
|
+
const runAhead = async (mi: number) => {
|
|
475
|
+
const g = await probeGrade(mi);
|
|
476
|
+
if (g === null) return;
|
|
477
|
+
const ahead: Array<[number, number]> = [];
|
|
478
|
+
for (let j = mi + 1; j < mechanisms.length; j++) {
|
|
479
|
+
if (floors.has(j)) continue;
|
|
480
|
+
const gj = await probeGrade(j);
|
|
481
|
+
if (gj !== null && gj < g) ahead.push([gj, j]);
|
|
482
|
+
}
|
|
483
|
+
ahead.sort((a, b) => a[0] - b[0] || a[1] - b[1]);
|
|
484
|
+
for (const [gj, j] of ahead) {
|
|
485
|
+
// Only what the declared order would also run: a bound that cannot beat
|
|
486
|
+
// what is already held is not even asked for its real floor.
|
|
487
|
+
if (
|
|
488
|
+
!(gj < Math.min(best === null ? Infinity : grade(best.weight), bound))
|
|
489
|
+
) {
|
|
490
|
+
continue;
|
|
491
|
+
}
|
|
492
|
+
const floor = await floorOf(j, worthAhead);
|
|
493
|
+
if (floor === null || !worthAhead(floor)) continue;
|
|
494
|
+
ctx.trace?.step(
|
|
495
|
+
"runAhead",
|
|
496
|
+
[],
|
|
497
|
+
[],
|
|
498
|
+
`${mechanisms[j].name} runs ahead of ${
|
|
499
|
+
mechanisms[mi].name
|
|
500
|
+
} — its floor (grade ${grade(floor)}) is below ${
|
|
501
|
+
mechanisms[mi].name
|
|
502
|
+
}'s (grade ${g}), so its result bounds what ${
|
|
503
|
+
mechanisms[mi].name
|
|
504
|
+
} could win`,
|
|
505
|
+
);
|
|
506
|
+
for (const r of await runOf(j)) {
|
|
507
|
+
// `consider` drops an empty answer, so it bounds nothing.
|
|
508
|
+
if (r.bytes.length === 0) continue;
|
|
509
|
+
bound = Math.min(bound, grade(weigh(r.accounted, r.moves)));
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
};
|
|
513
|
+
for (let mi = 0; mi < mechanisms.length; mi++) {
|
|
514
|
+
const mech = mechanisms[mi];
|
|
515
|
+
if (mi > 0) {
|
|
516
|
+
await runAhead(mi);
|
|
517
|
+
reportRegime();
|
|
518
|
+
}
|
|
519
|
+
const floor = await floorOf(mi, worthDeclared);
|
|
379
520
|
if (floor === null) {
|
|
380
521
|
ctx.trace?.step(
|
|
381
522
|
"skipMechanism",
|
|
@@ -385,6 +526,16 @@ export async function think(
|
|
|
385
526
|
);
|
|
386
527
|
continue;
|
|
387
528
|
}
|
|
529
|
+
if (grade(floor) > bound) {
|
|
530
|
+
if (meter) meter.mechanismsBounded++;
|
|
531
|
+
ctx.trace?.step(
|
|
532
|
+
"skipMechanism",
|
|
533
|
+
[],
|
|
534
|
+
[],
|
|
535
|
+
`${mech.name} skipped — floor ${floor} cannot beat grade ${bound}, already reached by a mechanism run ahead`,
|
|
536
|
+
);
|
|
537
|
+
continue;
|
|
538
|
+
}
|
|
388
539
|
if (!worthRunning(floor)) {
|
|
389
540
|
ctx.trace?.step(
|
|
390
541
|
"skipMechanism",
|
|
@@ -396,10 +547,7 @@ export async function think(
|
|
|
396
547
|
);
|
|
397
548
|
continue;
|
|
398
549
|
}
|
|
399
|
-
|
|
400
|
-
const results = meter
|
|
401
|
-
? await meter.time(`${mech.name}.run`, () => mech.run(ctx, query, pre))
|
|
402
|
-
: await mech.run(ctx, query, pre);
|
|
550
|
+
const results = await runOf(mi);
|
|
403
551
|
for (const r of results) {
|
|
404
552
|
// ONE FORMULA, EVERY CANDIDATE: the chart's derivation reports how many
|
|
405
553
|
// discrete moves it made and which bytes it could not recognise; the
|
|
@@ -544,25 +692,34 @@ export async function think(
|
|
|
544
692
|
// without evidence stays owed, and a later transition pays it only by carrying
|
|
545
693
|
// it (the law reads the window; see derivation.ts). Same reading, one
|
|
546
694
|
// definition — not a second spelling of it here.
|
|
547
|
-
const
|
|
695
|
+
const priced: Array<[number, number]> = [
|
|
548
696
|
...decided.accounted,
|
|
549
697
|
...pre.computed.map((u): [number, number] => [u.i, u.j]),
|
|
550
|
-
]
|
|
698
|
+
];
|
|
699
|
+
const explained = priced.filter(([a, b]) =>
|
|
551
700
|
windowOf([a, b], answer, query, ctx.space.maxGroup) !== null
|
|
552
701
|
);
|
|
553
|
-
//
|
|
554
|
-
//
|
|
555
|
-
// are
|
|
556
|
-
|
|
702
|
+
// THE DERIVATION IS BORN OWING ITS DISCRIMINATIVE MATERIAL. The bytes a
|
|
703
|
+
// corpus-global scaffolding window reaches (traverse.ts, `scaffoldExtents`)
|
|
704
|
+
// are nobody's debt — otherwise a later step could claim to pay them by
|
|
705
|
+
// restating ` is `, which every fact holds, and the law (which measures
|
|
706
|
+
// carrying by any window of what is owed) would admit it; the substitution
|
|
707
|
+
// bridge reads gaps the same way (`explainedSpan`). PRICING is untouched:
|
|
708
|
+
// the ladder still charges every unexplained byte, because for a question
|
|
709
|
+
// made of nothing but scaffolding (`How are you today?`) covering those bytes
|
|
710
|
+
// IS the evidence.
|
|
711
|
+
const scaffold = scaffoldExtents(ctx, query);
|
|
712
|
+
const paid = remainderOf(
|
|
557
713
|
query.length,
|
|
558
|
-
[
|
|
559
|
-
...decided.accounted,
|
|
560
|
-
...pre.computed.map((u): [number, number] => [u.i, u.j]),
|
|
561
|
-
],
|
|
714
|
+
[...explained, ...scaffold],
|
|
562
715
|
ctx.space.maxGroup,
|
|
563
716
|
);
|
|
564
|
-
|
|
717
|
+
// WHAT THE CONSTRUCTION WITHHOLDS, at or above one quantum: the difference between
|
|
718
|
+
// the remainder paid in full and the remainder paid by carrying. Both readings
|
|
719
|
+
// are the law's, so the floor is applied once and in one place — and the
|
|
720
|
+
// paid-in-full reading is computed only when a meter will read it.
|
|
565
721
|
if (ctx.meter) {
|
|
722
|
+
const paidInFull = remainderOf(query.length, priced, ctx.space.maxGroup);
|
|
566
723
|
ctx.meter.groundingWithheldBytes += unaccountedBytes(paid) -
|
|
567
724
|
unaccountedBytes(paidInFull);
|
|
568
725
|
}
|
|
@@ -577,8 +734,31 @@ export async function think(
|
|
|
577
734
|
const uncovered = state.remainder;
|
|
578
735
|
|
|
579
736
|
// ── Post-grounding, gated by the declaration and the remainder ────────
|
|
737
|
+
// WHAT THE GROUNDING SPOKE FOR, when it did not declare it: the forms inside
|
|
738
|
+
// the answer that the ASKER already holds. An answer is the asker's material
|
|
739
|
+
// plus what the corpus added — the fact's own value — and only the former was
|
|
740
|
+
// spoken for: re-entering it walks back to the question. The latter is what a
|
|
741
|
+
// chain continues THROUGH. Consuming every form recognised in the answer
|
|
742
|
+
// consumed that too, so a chain could start only where recognition happened
|
|
743
|
+
// to miss the next entity — measured on 133 held-out 2Wiki compositional
|
|
744
|
+
// questions, 3 pivot steps in all once interior recognition named the entity
|
|
745
|
+
// inside every fact. Witnessed exactly, as `chooseNext`'s exact tier reads the
|
|
746
|
+
// question (evidence.ts); a form below one window cannot be witnessed, and is
|
|
747
|
+
// consumed as before.
|
|
748
|
+
const asked = ctx._edgeAsked;
|
|
580
749
|
const preConsumed = declaredUsed ??
|
|
581
|
-
new Set(
|
|
750
|
+
new Set(
|
|
751
|
+
recognise(ctx, answer).sites
|
|
752
|
+
.filter((s) =>
|
|
753
|
+
asked === null || s.end - s.start < ctx.space.maxGroup ||
|
|
754
|
+
witness(
|
|
755
|
+
offsetCanon(ctx, answer.subarray(s.start, s.end)),
|
|
756
|
+
[asked.index],
|
|
757
|
+
ctx.space.maxGroup,
|
|
758
|
+
).complete
|
|
759
|
+
)
|
|
760
|
+
.map((s) => s.payload),
|
|
761
|
+
);
|
|
582
762
|
// A grounding that DECLARED itself complete is not extended: the answer is
|
|
583
763
|
// already a trained form's own continuation, reached through an identity
|
|
584
764
|
// claim about the query, so a multi-hop pivot could only chain past the
|
|
@@ -607,8 +787,17 @@ export async function think(
|
|
|
607
787
|
// `preConsumed` is derived by re-recognising the answer — "everything in
|
|
608
788
|
// it", not "what it voiced" — and a containment rule over that would
|
|
609
789
|
// suppress every pivot the answer legitimately contains.
|
|
790
|
+
//
|
|
791
|
+
// …and a continuation the ANSWER ITSELF holds was voiced, not withheld. A
|
|
792
|
+
// substitution that answers with its anchor's own continuation (`The director
|
|
793
|
+
// of Beat Girl is Edmond T. Gréville.`) declared that anchor used, so reading
|
|
794
|
+
// its continuations as withheld refused every pivot inside the answer — the
|
|
795
|
+
// chain could never step past the entity the first hop introduced.
|
|
610
796
|
const voiced = declaredUsed === undefined ? [] : [...declaredUsed].flatMap(
|
|
611
|
-
(id) =>
|
|
797
|
+
(id) =>
|
|
798
|
+
ctx.store.nextFirst(id, hubBound(ctx))
|
|
799
|
+
.map((n) => read(ctx, n))
|
|
800
|
+
.filter((v) => indexOf(answer, v, 0) < 0),
|
|
612
801
|
);
|
|
613
802
|
// WHAT THIS BRANCH READ, published where it was read. Post-grounding decides
|
|
614
803
|
// by the DECLARATION (`decided.used`, which becomes `voiced`), by what the
|
|
@@ -664,89 +853,59 @@ export async function think(
|
|
|
664
853
|
meter.postGroundingRemainderSpans += uncovered.length;
|
|
665
854
|
meter.postGroundingRemainderBytes += unaccountedBytes(uncovered);
|
|
666
855
|
}
|
|
667
|
-
// THE
|
|
668
|
-
// real questions that stopped with no note anywhere. They never reached the
|
|
669
|
-
// offer: `decided.complete` says the grounding supplied a fixed point, so the
|
|
670
|
-
// walk is skipped BY DESIGN and the state is the grounding's own. That state
|
|
671
|
-
// carries `fixed: true` (the trace already reports it), and the law's first
|
|
672
|
-
// clause refuses any continuation against it — so there is no `null` here to
|
|
673
|
-
// read as exhaustion, and the `Offer` contract is not in play at all. The
|
|
674
|
-
// silent stop is therefore a NAMED state, not a gap.
|
|
856
|
+
// ── THE CLOSURE ENGINE ───────────────────────────────────────────────
|
|
675
857
|
//
|
|
676
|
-
//
|
|
677
|
-
//
|
|
678
|
-
//
|
|
679
|
-
//
|
|
680
|
-
//
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
//
|
|
690
|
-
//
|
|
691
|
-
//
|
|
692
|
-
//
|
|
693
|
-
//
|
|
694
|
-
//
|
|
695
|
-
//
|
|
696
|
-
//
|
|
697
|
-
//
|
|
698
|
-
//
|
|
699
|
-
//
|
|
700
|
-
//
|
|
701
|
-
//
|
|
702
|
-
// observed: a single space between two fully-computed arithmetic spans
|
|
703
|
-
// ("2+2 3+3") registered as "unaccounted" and pulled in an unrelated
|
|
704
|
-
// corpus fact, corrupting "4 6" into "4 63".
|
|
705
|
-
// THE GATE ASKS THE LAW, and that is an OPTIMISATION, not a tidy-up: the state
|
|
706
|
-
// above ALREADY carries the remainder (`remainderOf`, per-span, with the W
|
|
707
|
-
// floor applied), so asking it costs nothing, while the total this line used to
|
|
708
|
-
// compute (`unaccounted(explained)`) was one more sum over the spans on every
|
|
709
|
-
// response. The two readings are the same condition, not two: the ACCOUNTING
|
|
710
|
-
// applies the same W floor the gate does, so a gap below one quantum never
|
|
711
|
-
// survives into `explained` and the total cannot reach W without some single
|
|
712
|
-
// gap reaching it. Measured over twelve constructions at W = 4 (test/136.3,
|
|
713
|
-
// which pins the equivalence and both sides of it).
|
|
714
|
-
// Whether the winning candidate's entire recognised substance is
|
|
715
|
-
// COMPUTED — every accounted span exactly a pre.computed span, nothing
|
|
716
|
-
// from a genuinely recognised/climbed site. fuseAttention's lone-root
|
|
717
|
-
// shortcut assumes a single point of attention already IS primary's own
|
|
718
|
-
// source; that assumption is exactly backwards for a pure computation
|
|
719
|
-
// (an ALU result has no anchor of its own) — see fuseAttention's
|
|
720
|
-
// `unclimbed` parameter, gated there by Attention.breadth so a
|
|
721
|
-
// coincidental echo (which this flag alone cannot distinguish) is still
|
|
722
|
-
// rejected.
|
|
858
|
+
// The grounding's state is CLOSED under the law by two layers, in order: the
|
|
859
|
+
// multi-hop WALK (`walkLayer`: a forward absorb or a pivot, offered one at a
|
|
860
|
+
// time) and the multi-topic FUSION (`fusionLayer`: one composed transition).
|
|
861
|
+
// Every step either layer offers goes through the same `closure` and the same
|
|
862
|
+
// law; this function no longer sequences them or gates them by hand.
|
|
863
|
+
//
|
|
864
|
+
// WHAT USED TO BE TWO HAND-WRITTEN GATES IS NOW THE LAW'S, OR THE LAYER'S:
|
|
865
|
+
// • a declared-complete grounding (`fixed`) admits no transition — the
|
|
866
|
+
// engine enters no layer for it (the law's first clause), which is the
|
|
867
|
+
// walk-skip and the fusion-skip this branch used to spell separately;
|
|
868
|
+
// • a CLOSED derivation has nothing left for a second topic to account for,
|
|
869
|
+
// so the fusion layer does not ENGAGE — read off the state the walk
|
|
870
|
+
// reached, the one fusion is actually offered against.
|
|
871
|
+
//
|
|
872
|
+
// What the fusion needs from the grounding — whether its substance is purely
|
|
873
|
+
// computed (`unclimbed`) and where it stands in the query (`primarySpans`) —
|
|
874
|
+
// is the grounding's own evidence, resolved here where both readings are in
|
|
875
|
+
// hand.
|
|
876
|
+
//
|
|
877
|
+
// Whether the winning candidate's entire recognised substance is COMPUTED —
|
|
878
|
+
// every accounted span exactly a pre.computed span, nothing from a genuinely
|
|
879
|
+
// recognised/climbed site. fuseAttention's lone-root shortcut assumes a
|
|
880
|
+
// single point of attention already IS primary's own source; that assumption
|
|
881
|
+
// is exactly backwards for a pure computation (an ALU result has no anchor of
|
|
882
|
+
// its own) — gated there by Attention.breadth so a coincidental echo (which
|
|
883
|
+
// this flag alone cannot distinguish) is still rejected.
|
|
723
884
|
const unclimbed = state.accounted.length > 0 &&
|
|
724
885
|
state.accounted.every(([i, j]) =>
|
|
725
886
|
pre.computed.some((u) => u.i === i && u.j === j)
|
|
726
887
|
);
|
|
727
|
-
// Where the winning grounding stands in the query — fusion places primary
|
|
728
|
-
//
|
|
729
|
-
//
|
|
730
|
-
//
|
|
731
|
-
//
|
|
732
|
-
// read here for POSITION instead of for coverage — and resolved here, where
|
|
733
|
-
// both readings are in hand, rather than inside fuseAttention.
|
|
888
|
+
// Where the winning grounding stands in the query — fusion places primary by
|
|
889
|
+
// it. `accounted` is the cost-ladder read and is authoritative when
|
|
890
|
+
// non-empty; when it is empty the grounding is a pure COMPUTATION, whose
|
|
891
|
+
// evidence is its computed span — the cost-ladder-vs-coverage distinction
|
|
892
|
+
// `explained` above draws, read here for POSITION instead of coverage.
|
|
734
893
|
const primarySpans: ReadonlyArray<Span> = state.accounted.length > 0
|
|
735
894
|
? state.accounted
|
|
736
895
|
: pre.computed.map((u): [number, number] => [u.i, u.j]);
|
|
737
|
-
const fused =
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
896
|
+
const fused = await closeOver(
|
|
897
|
+
state,
|
|
898
|
+
query,
|
|
899
|
+
ctx.space.maxGroup,
|
|
900
|
+
[
|
|
901
|
+
walkLayer(ctx, query, preConsumed, pre, voiced),
|
|
902
|
+
{
|
|
903
|
+
...fusionLayer(ctx, query, pre, unclimbed, primarySpans),
|
|
904
|
+
engages: (d: DerivationState) => !closed(d),
|
|
905
|
+
},
|
|
906
|
+
],
|
|
907
|
+
meter ? (name, walk) => meter.time(name, walk) : undefined,
|
|
908
|
+
);
|
|
750
909
|
|
|
751
910
|
done(
|
|
752
911
|
fused.product,
|