@hviana/sema 0.8.3 → 0.8.6
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 +11 -10
- package/README.md +17 -38
- package/dist/example/demo.js +85 -34
- package/dist/src/geometry.d.ts +0 -10
- package/dist/src/geometry.js +0 -12
- package/dist/src/meter.d.ts +31 -5
- package/dist/src/meter.js +31 -5
- package/dist/src/mind/articulation.js +1 -1
- package/dist/src/mind/attention.js +2 -1
- package/dist/src/mind/derivation.d.ts +201 -0
- package/dist/src/mind/derivation.js +327 -0
- package/dist/src/mind/graph-search.d.ts +2 -1
- package/dist/src/mind/graph-search.js +37 -15
- package/dist/src/mind/match.d.ts +2 -0
- package/dist/src/mind/match.js +2 -0
- package/dist/src/mind/mechanisms/alu.js +0 -2
- package/dist/src/mind/mechanisms/cast.d.ts +1 -5
- package/dist/src/mind/mechanisms/cast.js +15 -18
- package/dist/src/mind/mechanisms/confluence.d.ts +0 -3
- package/dist/src/mind/mechanisms/confluence.js +3 -9
- package/dist/src/mind/mechanisms/cover.js +17 -20
- package/dist/src/mind/mechanisms/extraction.d.ts +0 -1
- package/dist/src/mind/mechanisms/extraction.js +13 -8
- package/dist/src/mind/mechanisms/prefix-completion.js +0 -1
- package/dist/src/mind/mechanisms/recall.d.ts +0 -1
- package/dist/src/mind/mechanisms/recall.js +8 -9
- package/dist/src/mind/mechanisms/reference.js +3 -4
- package/dist/src/mind/pipeline-mechanism.d.ts +1 -4
- package/dist/src/mind/pipeline.js +106 -41
- package/dist/src/mind/rationale.d.ts +0 -11
- package/dist/src/mind/rationale.js +6 -32
- package/dist/src/mind/reasoning.d.ts +4 -30
- package/dist/src/mind/reasoning.js +191 -151
- package/dist/src/mind/types.js +6 -3
- package/docs/INDEX.md +23 -24
- package/docs/INVARIANTS.md +16 -17
- package/docs/architecture/bounded-reads.md +4 -4
- package/docs/architecture/closure.md +78 -0
- package/docs/architecture/commonality.md +27 -18
- package/docs/architecture/cost-model.md +5 -5
- package/docs/architecture/exact-vs-approximate.md +4 -4
- package/docs/architecture/factored-machinery.md +14 -14
- package/docs/architecture/mechanism-market.md +9 -9
- package/docs/architecture/meter.md +4 -5
- package/docs/architecture/store.md +2 -2
- package/docs/architecture/thresholds.md +1 -1
- package/docs/failures/tempting-but-wrong.md +11 -1
- package/docs/harness/gates.md +6 -6
- package/docs/mechanisms/cover.md +2 -2
- package/example/demo.ts +90 -37
- package/jsr.json +1 -1
- package/package.json +1 -1
- package/src/geometry.ts +0 -13
- package/src/meter.ts +31 -5
- package/src/mind/articulation.ts +0 -1
- package/src/mind/attention.ts +2 -1
- package/src/mind/derivation.ts +477 -0
- package/src/mind/graph-search.ts +37 -20
- package/src/mind/match.ts +2 -0
- package/src/mind/mechanisms/alu.ts +0 -2
- package/src/mind/mechanisms/cast.ts +17 -21
- package/src/mind/mechanisms/confluence.ts +3 -13
- package/src/mind/mechanisms/cover.ts +17 -20
- package/src/mind/mechanisms/extraction.ts +13 -9
- package/src/mind/mechanisms/prefix-completion.ts +0 -1
- package/src/mind/mechanisms/recall.ts +7 -9
- package/src/mind/mechanisms/reference.ts +2 -3
- package/src/mind/pipeline-mechanism.ts +1 -4
- package/src/mind/pipeline.ts +121 -46
- package/src/mind/rationale.ts +6 -36
- package/src/mind/reasoning.ts +220 -178
- package/src/mind/types.ts +5 -2
- package/test/121-the-extension-does-not-grow-with-the-corpus.test.mjs +3 -3
- package/test/133-the-decision-point-renders-the-state.test.mjs +204 -0
- package/test/134-the-law-explains-the-engines-own-refusal.test.mjs +237 -0
- package/test/135-one-law-any-producer.test.mjs +289 -0
- package/test/136-the-two-named-limits.test.mjs +205 -0
- package/test/137-the-law-lives-once-and-below.test.mjs +400 -0
- package/test/138-the-remainder-drains-only-what-a-move-declares.test.mjs +62 -0
- package/test/139-the-witness-is-engagement-not-explanation.test.mjs +51 -0
- package/test/140-irrelevant-supply-does-not-change-an-answer.test.mjs +48 -0
- package/test/141-the-question-is-paid-at-construction.test.mjs +98 -0
- package/test/142-the-layer-offers-only-what-the-law-admits.test.mjs +93 -0
- package/test/143-cycles-terminate-and-are-not-closure.test.mjs +62 -0
- package/test/36-already-answered-fusion.test.mjs +20 -2
- package/test/37-cluster-dispersion-fusion.test.mjs +30 -3
- package/test/38-reason-restate-guard.test.mjs +22 -2
- package/test/55-cost-meter.test.mjs +6 -3
package/src/mind/graph-search.ts
CHANGED
|
@@ -177,6 +177,30 @@ export interface Seg {
|
|
|
177
177
|
/** Read the chosen spans back off a derivation: the goal is a chain of bridge
|
|
178
178
|
* steps, each whose second premise is the `out` it crossed. Walk the chain to
|
|
179
179
|
* the axiom and reverse into left-to-right order. */
|
|
180
|
+
/** The BYTE TERM of a derivation's cost: how many bytes its bridge rule charged
|
|
181
|
+
* at PASS each — read back off the rule that charged them (`bridgeRule`:
|
|
182
|
+
* `o.rec ? MICRO : PASS * (o.j - o.i)`), so the split exists in ONE place and
|
|
183
|
+
* the engine's generic accumulator is left alone.
|
|
184
|
+
*
|
|
185
|
+
* `derivation.cost - PASS * readBridgedBytes(derivation)` is therefore the
|
|
186
|
+
* derivation's DISCRETE work — the number a mechanism reports as `moves`, which
|
|
187
|
+
* the pipeline's one formula then prices together with `PASS * unaccounted`.
|
|
188
|
+
* The two readings of the byte term coincide by construction: the spans this
|
|
189
|
+
* sums are exactly the ones the chart could not recognise (`rec === false`),
|
|
190
|
+
* which are the spans the candidate leaves unaccounted. */
|
|
191
|
+
function readBridgedBytes(derivation: Derivation<GItem>): number {
|
|
192
|
+
let bytes = 0;
|
|
193
|
+
let node: Derivation<GItem> | undefined = derivation;
|
|
194
|
+
while (node && node.rule) {
|
|
195
|
+
const o = node.premises[1]?.item;
|
|
196
|
+
if (o !== undefined && o.kind === "out" && o.rec === false) {
|
|
197
|
+
bytes += o.j - o.i;
|
|
198
|
+
}
|
|
199
|
+
node = node.premises[0];
|
|
200
|
+
}
|
|
201
|
+
return bytes;
|
|
202
|
+
}
|
|
203
|
+
|
|
180
204
|
function readCover(derivation: Derivation<GItem>): Seg[] {
|
|
181
205
|
const segs: Seg[] = [];
|
|
182
206
|
let node: Derivation<GItem> | undefined = derivation;
|
|
@@ -426,7 +450,6 @@ export class GraphSearch {
|
|
|
426
450
|
conceptTarget: ReadonlyMap<number, number>,
|
|
427
451
|
leaves: ReadonlyArray<Leaf>,
|
|
428
452
|
splits: ReadonlySet<number>,
|
|
429
|
-
starts: ReadonlySet<number>,
|
|
430
453
|
substitutions?: ReadonlyMap<number, Uint8Array>,
|
|
431
454
|
connectors?: ReadonlyMap<string, Uint8Array>,
|
|
432
455
|
computedResults?: ReadonlyArray<ComputedResult>,
|
|
@@ -437,7 +460,7 @@ export class GraphSearch {
|
|
|
437
460
|
* the rationale instead of stopping at the first layer. Off by default, so
|
|
438
461
|
* the search pays nothing when no one inspects. */
|
|
439
462
|
onDerivation?: (steps: DerivationStep[]) => void,
|
|
440
|
-
): { segs: Seg[]; cost: number } | null {
|
|
463
|
+
): { segs: Seg[]; cost: number; moves: number } | null {
|
|
441
464
|
// Top-level entry: reset the per-call recursion state, then run the one
|
|
442
465
|
// {@link solve} routine that both the query and any produced composite go
|
|
443
466
|
// through (completion is cover, recursively — see {@link recompleteNode}).
|
|
@@ -449,12 +472,7 @@ export class GraphSearch {
|
|
|
449
472
|
this.derivationSink = onDerivation;
|
|
450
473
|
const solved = this.solve(
|
|
451
474
|
queryLen,
|
|
452
|
-
{
|
|
453
|
-
sites,
|
|
454
|
-
leaves,
|
|
455
|
-
splits,
|
|
456
|
-
starts,
|
|
457
|
-
},
|
|
475
|
+
{ sites, leaves, splits },
|
|
458
476
|
conceptTarget,
|
|
459
477
|
substitutions,
|
|
460
478
|
connectors,
|
|
@@ -468,9 +486,11 @@ export class GraphSearch {
|
|
|
468
486
|
// continuations instead of following the chain the answer itself licensed.
|
|
469
487
|
// With deepening only at the top, `recompleteNode` walks the accepted chain
|
|
470
488
|
// one link at a time (its own memo and stack), so the work is the answer's.
|
|
471
|
-
return solved === null
|
|
472
|
-
|
|
473
|
-
|
|
489
|
+
return solved === null ? null : {
|
|
490
|
+
segs: this.deepen(solved.segs),
|
|
491
|
+
cost: solved.cost,
|
|
492
|
+
moves: solved.moves,
|
|
493
|
+
};
|
|
474
494
|
}
|
|
475
495
|
/** Build the deduction system for one span and return its lightest cover's
|
|
476
496
|
* chosen spans — the SINGLE routine the query and every produced composite
|
|
@@ -491,21 +511,19 @@ export class GraphSearch {
|
|
|
491
511
|
sites: ReadonlyArray<Site>;
|
|
492
512
|
leaves: ReadonlyArray<Leaf>;
|
|
493
513
|
splits: ReadonlySet<number>;
|
|
494
|
-
starts: ReadonlySet<number>;
|
|
495
514
|
},
|
|
496
515
|
conceptTarget: ReadonlyMap<number, number>,
|
|
497
516
|
substitutions?: ReadonlyMap<number, Uint8Array>,
|
|
498
517
|
connectors?: ReadonlyMap<string, Uint8Array>,
|
|
499
518
|
computedResults?: ReadonlyArray<ComputedResult>,
|
|
500
519
|
onDerivation?: (steps: DerivationStep[]) => void,
|
|
501
|
-
): { segs: Seg[]; cost: number } | null {
|
|
520
|
+
): { segs: Seg[]; cost: number; moves: number } | null {
|
|
502
521
|
const system = this.buildSearch(
|
|
503
522
|
spanLen,
|
|
504
523
|
recognition.sites,
|
|
505
524
|
conceptTarget,
|
|
506
525
|
recognition.leaves,
|
|
507
526
|
recognition.splits,
|
|
508
|
-
recognition.starts,
|
|
509
527
|
substitutions,
|
|
510
528
|
connectors,
|
|
511
529
|
computedResults,
|
|
@@ -528,7 +546,11 @@ export class GraphSearch {
|
|
|
528
546
|
onDerivation(readDerivation(derivation, substitutions !== undefined));
|
|
529
547
|
}
|
|
530
548
|
return derivation
|
|
531
|
-
? {
|
|
549
|
+
? {
|
|
550
|
+
segs: readCover(derivation),
|
|
551
|
+
cost: derivation.cost,
|
|
552
|
+
moves: derivation.cost - PASS * readBridgedBytes(derivation),
|
|
553
|
+
}
|
|
532
554
|
: null;
|
|
533
555
|
}
|
|
534
556
|
|
|
@@ -568,7 +590,6 @@ export class GraphSearch {
|
|
|
568
590
|
conceptTarget: ReadonlyMap<number, number>,
|
|
569
591
|
leaves: ReadonlyArray<Leaf>,
|
|
570
592
|
splits: ReadonlySet<number>,
|
|
571
|
-
starts: ReadonlySet<number>,
|
|
572
593
|
substitutions?: ReadonlyMap<number, Uint8Array>,
|
|
573
594
|
connectors?: ReadonlyMap<string, Uint8Array>,
|
|
574
595
|
computedResults?: ReadonlyArray<ComputedResult>,
|
|
@@ -730,7 +751,6 @@ export class GraphSearch {
|
|
|
730
751
|
return this.outRules(it, {
|
|
731
752
|
W,
|
|
732
753
|
splits,
|
|
733
|
-
starts,
|
|
734
754
|
atomsAreHubs,
|
|
735
755
|
coversDone,
|
|
736
756
|
outsByStart,
|
|
@@ -1190,7 +1210,6 @@ export class GraphSearch {
|
|
|
1190
1210
|
sites: [...recognised, ...structural],
|
|
1191
1211
|
leaves: rec.leaves,
|
|
1192
1212
|
splits: rec.splits,
|
|
1193
|
-
starts: rec.starts,
|
|
1194
1213
|
},
|
|
1195
1214
|
new Map(),
|
|
1196
1215
|
undefined,
|
|
@@ -1484,7 +1503,6 @@ export class GraphSearch {
|
|
|
1484
1503
|
ctx: {
|
|
1485
1504
|
W: number;
|
|
1486
1505
|
splits: ReadonlySet<number>;
|
|
1487
|
-
starts: ReadonlySet<number>;
|
|
1488
1506
|
atomsAreHubs: boolean;
|
|
1489
1507
|
coversDone: Set<number>;
|
|
1490
1508
|
outsByStart: Map<number, OutItem[]>;
|
|
@@ -1647,7 +1665,6 @@ export class GraphSearch {
|
|
|
1647
1665
|
r: OutItem,
|
|
1648
1666
|
ctx: {
|
|
1649
1667
|
W: number;
|
|
1650
|
-
starts: ReadonlySet<number>;
|
|
1651
1668
|
atomsAreHubs: boolean;
|
|
1652
1669
|
findLeafU: (b: Uint8Array) => number | undefined;
|
|
1653
1670
|
findBranchU: (k: number[]) => number | undefined;
|
package/src/mind/match.ts
CHANGED
|
@@ -1004,6 +1004,8 @@ export function spanHalo(
|
|
|
1004
1004
|
return found ? normalize(out) : null;
|
|
1005
1005
|
}
|
|
1006
1006
|
|
|
1007
|
+
/** A TEST SURFACE: exported for the tests that pin the synonym strength ladder
|
|
1008
|
+
* (they are its only consumers); nothing in `src/` calls it. */
|
|
1007
1009
|
/** Distributional synonym evidence between arbitrary byte spans. Whole words
|
|
1008
1010
|
* need not be independently interned: their stored W-window occurrences are
|
|
1009
1011
|
* lifted to episode halos, bundled, and compared. The caller chooses the
|
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
|
|
10
10
|
import type { Alu } from "../../alu/src/alu.js";
|
|
11
11
|
import { STEP } from "../graph-search.js";
|
|
12
|
-
import { unexplainedLabel } from "../rationale.js";
|
|
13
12
|
import type { PipelineMechanism } from "../pipeline-mechanism.js";
|
|
14
13
|
|
|
15
14
|
/** Wrap the ALU as a {@link PipelineMechanism}. */
|
|
@@ -35,7 +34,6 @@ export function aluToMechanism(alu: Alu): PipelineMechanism {
|
|
|
35
34
|
bytes: u.bytes,
|
|
36
35
|
accounted: [[u.i, u.j]],
|
|
37
36
|
moves: STEP,
|
|
38
|
-
unexplained: unexplainedLabel(query, [[u.i, u.j]]),
|
|
39
37
|
}));
|
|
40
38
|
},
|
|
41
39
|
};
|
|
@@ -30,15 +30,11 @@ import {
|
|
|
30
30
|
sharedFrameStrengthOf,
|
|
31
31
|
} from "../match.js";
|
|
32
32
|
import { joinWithBridge } from "../resonance.js";
|
|
33
|
-
import { restatesQuery } from "../reasoning.js";
|
|
34
33
|
import { CONCEPT, STEP } from "../graph-search.js";
|
|
35
34
|
import { concat2, indexOf } from "../../bytes.js";
|
|
36
35
|
import { consensusFloor, dominates } from "../../geometry.js";
|
|
37
|
-
import {
|
|
38
|
-
|
|
39
|
-
unexplainedLabel,
|
|
40
|
-
unexplainedSpans,
|
|
41
|
-
} from "../rationale.js";
|
|
36
|
+
import { decodeText } from "../rationale.js";
|
|
37
|
+
import { restates, unexplainedSpans } from "../derivation.js";
|
|
42
38
|
import { rItem, rNode } from "../trace.js";
|
|
43
39
|
import { dismissedKnownContent } from "../bridge.js";
|
|
44
40
|
import { leafIdRun } from "../canonical.js";
|
|
@@ -92,7 +88,6 @@ export interface CastResult {
|
|
|
92
88
|
/** A human-readable label for the query bytes this schema left
|
|
93
89
|
* unexplained — purely diagnostic, never priced (see the module's
|
|
94
90
|
* Task 2 note in pipeline.ts's Candidate interface). */
|
|
95
|
-
unexplained: string;
|
|
96
91
|
}
|
|
97
92
|
|
|
98
93
|
/** The seat that establishes a node's role in an analogical comparison:
|
|
@@ -129,7 +124,7 @@ export interface CastResult {
|
|
|
129
124
|
* describes id ("...painted by Leonardo da Vinci." contains "Leonardo da
|
|
130
125
|
* Vinci"). An incidental adjacency predecessor never does — it merely
|
|
131
126
|
* preceded id in some unrelated document without ever mentioning it. No
|
|
132
|
-
* new tuned constant: containment is the same primitive `
|
|
127
|
+
* new tuned constant: containment is the same primitive `restates`
|
|
133
128
|
* and `dominates`-style checks already use throughout this codebase.
|
|
134
129
|
*
|
|
135
130
|
* `allowForward` (default true) gates the FORWARD branch specifically —
|
|
@@ -499,7 +494,6 @@ export async function counterfactualTransfer(
|
|
|
499
494
|
used: used ?? new Set(),
|
|
500
495
|
accounted,
|
|
501
496
|
moves,
|
|
502
|
-
unexplained: unexplainedLabel(query, accounted),
|
|
503
497
|
});
|
|
504
498
|
};
|
|
505
499
|
ctx.trace?.step(
|
|
@@ -613,7 +607,7 @@ export async function counterfactualTransfer(
|
|
|
613
607
|
const fwd = await follow(ctx, proj.anchor, qv);
|
|
614
608
|
if (
|
|
615
609
|
fwd !== null && indexOf(answer, fwd, 0) < 0 &&
|
|
616
|
-
!
|
|
610
|
+
!restates(query, fwd, 0, { proper: true })
|
|
617
611
|
) {
|
|
618
612
|
// THROUGH THE SHARED JOINER, not a bare concatenation.
|
|
619
613
|
//
|
|
@@ -695,7 +689,7 @@ export async function counterfactualTransfer(
|
|
|
695
689
|
// cap the test reads "none of the established continuations appears".
|
|
696
690
|
const domNext = ctx.store.nextFirst(dominant.anchor, hubBound(ctx));
|
|
697
691
|
const displaced = domNext
|
|
698
|
-
.every((n) =>
|
|
692
|
+
.every((n) => !restates(query, read(ctx, n), 0));
|
|
699
693
|
// The SUBSTITUTE is what redirection speaks — the answer IS `project(last)`,
|
|
700
694
|
// its own fact — so the same bar applies. The displaced structure is only
|
|
701
695
|
// recognised as the slot being overridden and is never voiced, so it is
|
|
@@ -791,7 +785,7 @@ export async function counterfactualTransfer(
|
|
|
791
785
|
queryScale(p.ctx.length) &&
|
|
792
786
|
indexOf(dominant.ctx, p.ctx, 0) < 0 &&
|
|
793
787
|
indexOf(p.ctx, dominant.ctx, 0) < 0 &&
|
|
794
|
-
|
|
788
|
+
!restates(query, p.ctx, 0)
|
|
795
789
|
) {
|
|
796
790
|
analogs.push({ anchor: p.anchor, point: p, src: p });
|
|
797
791
|
}
|
|
@@ -810,7 +804,7 @@ export async function counterfactualTransfer(
|
|
|
810
804
|
!queryScale(nctx.length) ||
|
|
811
805
|
indexOf(dominant.ctx, nctx, 0) >= 0 ||
|
|
812
806
|
indexOf(nctx, dominant.ctx, 0) >= 0 ||
|
|
813
|
-
|
|
807
|
+
restates(query, nctx, 0)
|
|
814
808
|
) continue;
|
|
815
809
|
analogs.push({ anchor: nid, point: null, src: p });
|
|
816
810
|
}
|
|
@@ -1286,13 +1280,16 @@ export async function counterfactualTransfer(
|
|
|
1286
1280
|
// consulting it here is the same fallback `resolve` already makes when an
|
|
1287
1281
|
// exact content lookup misses, and it keeps this mechanism from carrying
|
|
1288
1282
|
// any idea of its own about what a character is.
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1283
|
+
// TWO WITNESSES, ONE LAW: the byte reading, and — when the response carries
|
|
1284
|
+
// one — the same reading under the response's own equivalence. Asked twice
|
|
1285
|
+
// rather than branched on, because the equivalence is a property of the
|
|
1286
|
+
// injected canonicalizer (a substring-monotone function is the usual case,
|
|
1287
|
+
// not a guarantee), and the two readings are OR-ed here exactly as they were
|
|
1288
|
+
// before this became one definition.
|
|
1289
|
+
const echoesQuery = (x: Uint8Array): boolean =>
|
|
1290
|
+
restates(query, x, 0, { proper: true }) ||
|
|
1291
|
+
(ctx.canon !== null &&
|
|
1292
|
+
restates(query, x, 0, { equate: ctx.canon, proper: true }));
|
|
1296
1293
|
if (echoesQuery(b)) {
|
|
1297
1294
|
const fwd = await follow(ctx, bestAnalog.anchor, qv);
|
|
1298
1295
|
if (fwd !== null && fwd.length > 0 && !echoesQuery(fwd)) b = fwd;
|
|
@@ -1406,7 +1403,6 @@ export const castMechanism: PipelineMechanism = {
|
|
|
1406
1403
|
accounted: c.accounted,
|
|
1407
1404
|
moves: c.moves,
|
|
1408
1405
|
used: c.used,
|
|
1409
|
-
unexplained: c.unexplained,
|
|
1410
1406
|
}));
|
|
1411
1407
|
},
|
|
1412
1408
|
};
|
|
@@ -44,7 +44,7 @@ import { read } from "../primitives.js";
|
|
|
44
44
|
import { corpusN, reachOf } from "../traverse.js";
|
|
45
45
|
import { dominates } from "../../geometry.js";
|
|
46
46
|
import { STEP } from "../graph-search.js";
|
|
47
|
-
import {
|
|
47
|
+
import { insideAnsweredTurn } from "../derivation.js";
|
|
48
48
|
import type { PipelineMechanism, Precomputed } from "../pipeline-mechanism.js";
|
|
49
49
|
import { rItem, rNode } from "../trace.js";
|
|
50
50
|
|
|
@@ -58,9 +58,6 @@ export interface JoinResult {
|
|
|
58
58
|
used: ReadonlySet<number>;
|
|
59
59
|
accounted: Array<[number, number]>;
|
|
60
60
|
moves: number;
|
|
61
|
-
/** A human-readable label for the query bytes the meet left unexplained —
|
|
62
|
-
* purely diagnostic, never priced. */
|
|
63
|
-
unexplained: string;
|
|
64
61
|
}
|
|
65
62
|
|
|
66
63
|
/** The main confluence entry point. Given a query, detect whether it weaves
|
|
@@ -98,14 +95,9 @@ export async function confluenceJoin(
|
|
|
98
95
|
// Recognition and attention still see the full transcript; only this
|
|
99
96
|
// mechanism's constraint population excludes answered spans.
|
|
100
97
|
const queryWin = new Map<number, number>();
|
|
101
|
-
|
|
98
|
+
const answered = { at: 0 };
|
|
102
99
|
for (const [off, id] of pre.queryWindows) {
|
|
103
|
-
|
|
104
|
-
answered < ctx.answeredSpans.length &&
|
|
105
|
-
ctx.answeredSpans[answered][1] <= off
|
|
106
|
-
) answered++;
|
|
107
|
-
const span = ctx.answeredSpans[answered];
|
|
108
|
-
if (span && span[0] <= off && off + W <= span[1]) continue;
|
|
100
|
+
if (insideAnsweredTurn(ctx.answeredSpans, answered, off, off + W)) continue;
|
|
109
101
|
queryWin.set(off, id);
|
|
110
102
|
}
|
|
111
103
|
const queryIds = new Set(queryWin.values());
|
|
@@ -315,7 +307,6 @@ export async function confluenceJoin(
|
|
|
315
307
|
used: new Set([met.a.anchor, met.b.anchor]),
|
|
316
308
|
accounted,
|
|
317
309
|
moves: 3 * STEP,
|
|
318
|
-
unexplained: unexplainedLabel(query, accounted),
|
|
319
310
|
};
|
|
320
311
|
}
|
|
321
312
|
|
|
@@ -344,7 +335,6 @@ export const confluenceMechanism: PipelineMechanism = {
|
|
|
344
335
|
accounted: met.accounted,
|
|
345
336
|
moves: met.moves,
|
|
346
337
|
used: met.used,
|
|
347
|
-
unexplained: met.unexplained,
|
|
348
338
|
}];
|
|
349
339
|
},
|
|
350
340
|
};
|
|
@@ -16,7 +16,8 @@ import { guidedFirst, hubBound } from "../traverse.js";
|
|
|
16
16
|
import { conceptHop } from "../match.js";
|
|
17
17
|
import { bridge } from "../resonance.js";
|
|
18
18
|
import { liftAnswer, liftedScaffolding, segRestatesQuery } from "../types.js";
|
|
19
|
-
import { decodeText
|
|
19
|
+
import { decodeText } from "../rationale.js";
|
|
20
|
+
import { insideAnsweredTurn, restates } from "../derivation.js";
|
|
20
21
|
import { indexOf } from "../../bytes.js";
|
|
21
22
|
import type { RationaleItem } from "../rationale.js";
|
|
22
23
|
import { rItem, rNode, traceDerivation } from "../trace.js";
|
|
@@ -62,16 +63,13 @@ export async function resolveConnectors(
|
|
|
62
63
|
// discarded — a semantically neutral gate (it removes work whose product
|
|
63
64
|
// liftAnswer throws away), and a cumulative (multi-turn) query is exactly
|
|
64
65
|
// where such already-answered continuations recur.
|
|
65
|
-
|
|
66
|
+
const answered = { at: 0 };
|
|
66
67
|
const ordered = [...sites]
|
|
67
68
|
.sort((a, b) => a.start - b.start)
|
|
68
69
|
.filter((s) => {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
) answered++;
|
|
73
|
-
const span = ctx.answeredSpans[answered];
|
|
74
|
-
if (span && span[0] <= s.start && s.end <= span[1]) return false;
|
|
70
|
+
if (insideAnsweredTurn(ctx.answeredSpans, answered, s.start, s.end)) {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
75
73
|
if (query === undefined || ctx.answeredSpans.length === 0) return true;
|
|
76
74
|
const continuations = ctx.store.nextFirst(s.payload, hubBound(ctx));
|
|
77
75
|
return !continuations.some((answer) => {
|
|
@@ -93,7 +91,11 @@ export async function resolveConnectors(
|
|
|
93
91
|
// 3 bytes this reads 4 bytes per candidate instead of the ~231 it
|
|
94
92
|
// averaged before.
|
|
95
93
|
const bytes = read(ctx, answer, query.length + 1);
|
|
96
|
-
|
|
94
|
+
// THE CONTENT READING of the same exclusion: the site's own
|
|
95
|
+
// continuation already occurs in the query, so voicing it back adds
|
|
96
|
+
// nothing. It is the restatement law with no `proper` flag — the
|
|
97
|
+
// containment reading that also admits the whole query.
|
|
98
|
+
return restates(query, bytes, 0);
|
|
97
99
|
});
|
|
98
100
|
});
|
|
99
101
|
const bridgePair = async (l: number, r: number) => {
|
|
@@ -210,18 +212,11 @@ export const coverMechanism: PipelineMechanism = {
|
|
|
210
212
|
)
|
|
211
213
|
: await resolveConnectors(ctx, sites, query);
|
|
212
214
|
let splits = rec.splits;
|
|
213
|
-
let starts = rec.starts;
|
|
214
215
|
if (computed.length > 0) {
|
|
215
216
|
splits = new Set(rec.splits);
|
|
216
|
-
starts = new Set(rec.starts);
|
|
217
217
|
for (const u of computed) {
|
|
218
218
|
splits.add(u.i);
|
|
219
219
|
splits.add(u.j);
|
|
220
|
-
// A computation's own boundaries carry the same fold-level evidence
|
|
221
|
-
// a chunk boundary does — "computation always wins" (see the header
|
|
222
|
-
// comment) extends to being trusted ground for cross-leaf recovery.
|
|
223
|
-
starts.add(u.i);
|
|
224
|
-
starts.add(u.j);
|
|
225
220
|
}
|
|
226
221
|
}
|
|
227
222
|
const concepts = ctx.meter
|
|
@@ -262,7 +257,6 @@ export const coverMechanism: PipelineMechanism = {
|
|
|
262
257
|
concepts,
|
|
263
258
|
rec.leaves,
|
|
264
259
|
splits,
|
|
265
|
-
starts,
|
|
266
260
|
undefined,
|
|
267
261
|
connectors,
|
|
268
262
|
computedResults,
|
|
@@ -330,9 +324,12 @@ export const coverMechanism: PipelineMechanism = {
|
|
|
330
324
|
return [{
|
|
331
325
|
bytes: composed,
|
|
332
326
|
accounted,
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
327
|
+
// The derivation's DISCRETE work. The bytes the chart could not
|
|
328
|
+
// recognise are NOT priced here: they are exactly the spans `accounted`
|
|
329
|
+
// leaves uncovered, and the pipeline's one formula charges them at PASS —
|
|
330
|
+
// the same formula that prices every other mechanism's candidate. No
|
|
331
|
+
// mechanism spells a cost of its own.
|
|
332
|
+
moves: solved!.moves,
|
|
336
333
|
// How much of the composed answer is the asker's own unexplained words
|
|
337
334
|
// (the spans the liftAnswer trace above labels "scaffolding"). Cover is
|
|
338
335
|
// the mechanism that can carry them, because a PASS span still lands in
|
|
@@ -11,7 +11,7 @@ import type { MindContext } from "../types.js";
|
|
|
11
11
|
import { read } from "../primitives.js";
|
|
12
12
|
import { follow, isSpanShaped, locate, skillExemplar } from "../match.js";
|
|
13
13
|
import { concatBytes, indexOf } from "../../bytes.js";
|
|
14
|
-
import { decodeText
|
|
14
|
+
import { decodeText } from "../rationale.js";
|
|
15
15
|
import type {
|
|
16
16
|
PipelineMechanism,
|
|
17
17
|
Precomputed,
|
|
@@ -46,7 +46,6 @@ export async function extractBySkill(
|
|
|
46
46
|
{
|
|
47
47
|
bytes: Uint8Array;
|
|
48
48
|
accounted: Array<[number, number]>;
|
|
49
|
-
unexplained: string;
|
|
50
49
|
} | null
|
|
51
50
|
> {
|
|
52
51
|
const t = ctx.trace?.enter("extractBySkill", [
|
|
@@ -102,6 +101,12 @@ export async function extractBySkill(
|
|
|
102
101
|
const searched = ranked.slice(0, pre.k);
|
|
103
102
|
let shapeMisses = 0;
|
|
104
103
|
let subQuantum = 0;
|
|
104
|
+
// A SECOND refusal counter, because the note below used to call an UNANCHORED
|
|
105
|
+
// read "sub-quantum" — which is false, and it is the kind of instrumentation
|
|
106
|
+
// defect AGENTS §6 says to close where it lives: a reader could not tell from
|
|
107
|
+
// the trace which of the two gates refused. Neither counter reaches a
|
|
108
|
+
// decision (meter.ts contract 1); they exist so the refusal is legible.
|
|
109
|
+
let unanchored = 0;
|
|
105
110
|
for (const cand of searched) {
|
|
106
111
|
const exemplar = await pre.spanShapedOf(cand.anchor);
|
|
107
112
|
if (!exemplar) {
|
|
@@ -137,22 +142,23 @@ export async function extractBySkill(
|
|
|
137
142
|
// Here the field is this mechanism's own output and carries its documented
|
|
138
143
|
// meaning, so the test is sound exactly where the convention does not reach.
|
|
139
144
|
if (built.accounted.length === 0) {
|
|
140
|
-
|
|
145
|
+
unanchored++;
|
|
141
146
|
continue;
|
|
142
147
|
}
|
|
143
|
-
if (shapeMisses > 0 || subQuantum > 0) {
|
|
148
|
+
if (shapeMisses > 0 || subQuantum > 0 || unanchored > 0) {
|
|
144
149
|
ctx.trace?.step(
|
|
145
150
|
"trySkillAnchors",
|
|
146
151
|
[
|
|
147
152
|
rItem(
|
|
148
153
|
query.subarray(0, 0),
|
|
149
|
-
`skipped ${shapeMisses + subQuantum}`,
|
|
154
|
+
`skipped ${shapeMisses + subQuantum + unanchored}`,
|
|
150
155
|
),
|
|
151
156
|
rNode(ctx, cand.anchor, "chosen"),
|
|
152
157
|
],
|
|
153
158
|
[],
|
|
154
|
-
`skipped ${shapeMisses} non-exemplar
|
|
155
|
-
|
|
159
|
+
`skipped ${shapeMisses} non-exemplar, ${subQuantum} sub-quantum and ` +
|
|
160
|
+
`${unanchored} unanchored anchor(s) before one yielded a usable ` +
|
|
161
|
+
`extraction`,
|
|
156
162
|
);
|
|
157
163
|
}
|
|
158
164
|
t?.done(
|
|
@@ -170,7 +176,6 @@ export async function extractBySkill(
|
|
|
170
176
|
return {
|
|
171
177
|
bytes: built.bytes,
|
|
172
178
|
accounted: built.accounted,
|
|
173
|
-
unexplained: unexplainedLabel(query, built.accounted),
|
|
174
179
|
};
|
|
175
180
|
}
|
|
176
181
|
if (shapeMisses === searched.length) {
|
|
@@ -403,7 +408,6 @@ export const extractionMechanism: PipelineMechanism = {
|
|
|
403
408
|
bytes: ex.bytes,
|
|
404
409
|
accounted: ex.accounted,
|
|
405
410
|
moves: CONCEPT + STEP * ex.accounted.length,
|
|
406
|
-
unexplained: ex.unexplained,
|
|
407
411
|
}];
|
|
408
412
|
},
|
|
409
413
|
};
|
|
@@ -300,7 +300,6 @@ export const prefixMechanism: PipelineMechanism = {
|
|
|
300
300
|
// IDENTITY bridge takes.
|
|
301
301
|
accounted: [[0, query.length]],
|
|
302
302
|
moves: STEP,
|
|
303
|
-
unexplained: "",
|
|
304
303
|
// NOT complete: the query is a proper PREFIX, so the form may carry more
|
|
305
304
|
// past the remainder this voiced.
|
|
306
305
|
}];
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
voicesDisplacedFiller,
|
|
25
25
|
} from "../match.js";
|
|
26
26
|
import { CONCEPT, STEP } from "../graph-search.js";
|
|
27
|
-
import {
|
|
27
|
+
import { restates as lawRestates } from "../derivation.js";
|
|
28
28
|
import type { PipelineMechanism, Precomputed } from "../pipeline-mechanism.js";
|
|
29
29
|
import { rItem, rNode } from "../trace.js";
|
|
30
30
|
import { substitutionBridge } from "../bridge.js";
|
|
@@ -35,7 +35,6 @@ export interface RecallResult {
|
|
|
35
35
|
echoed: boolean;
|
|
36
36
|
accounted: Array<[number, number]>;
|
|
37
37
|
moves: number;
|
|
38
|
-
unexplained: string;
|
|
39
38
|
/** See {@link import("../pipeline-mechanism.js").MechanismResult.complete}
|
|
40
39
|
* — set by the IDENTITY-bridge tier alone. */
|
|
41
40
|
complete?: boolean;
|
|
@@ -71,7 +70,6 @@ export async function recallByResonance(
|
|
|
71
70
|
echoed,
|
|
72
71
|
accounted,
|
|
73
72
|
moves,
|
|
74
|
-
unexplained: unexplainedLabel(query, accounted),
|
|
75
73
|
...(complete ? { complete } : {}),
|
|
76
74
|
};
|
|
77
75
|
};
|
|
@@ -156,7 +154,7 @@ export async function recallByResonance(
|
|
|
156
154
|
// conversation reads as if it were the next thing to say.
|
|
157
155
|
if (
|
|
158
156
|
g !== null && g.length > 0 &&
|
|
159
|
-
!(
|
|
157
|
+
!lawRestates(query, g, 0, { proper: true })
|
|
160
158
|
) {
|
|
161
159
|
return ground(
|
|
162
160
|
g,
|
|
@@ -196,10 +194,11 @@ export async function recallByResonance(
|
|
|
196
194
|
// same principle that keeps cast from voicing stored questions), and
|
|
197
195
|
// projecting them forward is reverse recall's containment failure in the
|
|
198
196
|
// other direction — "whatever followed these bytes in some document".
|
|
199
|
-
|
|
197
|
+
// THE EQUALITY READING of the restatement law: this tier rejects an answer
|
|
198
|
+
// that IS the question (an echo), and a proper fragment is handled by the
|
|
199
|
+
// tier's own subspan tests further down — so the law is asked with `whole`.
|
|
200
200
|
const restates = (b: Uint8Array): boolean =>
|
|
201
|
-
|
|
202
|
-
(ctx.canon !== null && bytesEqual(ctx.canon(b), qKey));
|
|
201
|
+
lawRestates(query, b, 0, { equate: ctx.canon, whole: true });
|
|
203
202
|
const idBar = identityBar(ctx.store.D, ctx.space.maxGroup, query.length);
|
|
204
203
|
if (top.score >= idBar) {
|
|
205
204
|
for (const h of whole) {
|
|
@@ -408,7 +407,7 @@ export async function recallByResonance(
|
|
|
408
407
|
// — never an answer (the same principle as `restates` above, extended
|
|
409
408
|
// to fragments). Genuine anchor groundings — longer than the query,
|
|
410
409
|
// or disjoint from it — pass untouched.
|
|
411
|
-
else if (g && !(
|
|
410
|
+
else if (g && !lawRestates(query, g, 0, { proper: true })) {
|
|
412
411
|
return ground(
|
|
413
412
|
g,
|
|
414
413
|
"scaffolding-dominated query — ground the consensus-climb anchor",
|
|
@@ -627,7 +626,6 @@ export const recallMechanism: PipelineMechanism = {
|
|
|
627
626
|
bytes: r.bytes,
|
|
628
627
|
accounted: r.accounted,
|
|
629
628
|
moves: r.moves,
|
|
630
|
-
unexplained: r.unexplained,
|
|
631
629
|
provenance: r.echoed ? "recall-echo" : "recall",
|
|
632
630
|
used: new Set<number>(),
|
|
633
631
|
...(r.complete ? { complete: true } : {}),
|
|
@@ -39,7 +39,7 @@ import type { FrameInstance } from "../match.js";
|
|
|
39
39
|
import { carriesFillers, distinct, follow, substituteAll } from "../match.js";
|
|
40
40
|
import { dominates } from "../../geometry.js";
|
|
41
41
|
import { bytesEqual, indexOf } from "../../bytes.js";
|
|
42
|
-
import {
|
|
42
|
+
import { restates } from "../derivation.js";
|
|
43
43
|
import { STEP } from "../graph-search.js";
|
|
44
44
|
import type {
|
|
45
45
|
MechanismResult,
|
|
@@ -231,7 +231,7 @@ export async function bindReference(
|
|
|
231
231
|
if (bytes.length === 0) return fail("the binding produced nothing");
|
|
232
232
|
// Answering with the question is not answering — the same restated-fragment
|
|
233
233
|
// guard every recall tier applies.
|
|
234
|
-
if (
|
|
234
|
+
if (restates(query, bytes, 0, { proper: true })) {
|
|
235
235
|
return fail("the binding restates part of the question");
|
|
236
236
|
}
|
|
237
237
|
const carried = !bytesEqual(bytes, first);
|
|
@@ -278,7 +278,6 @@ export async function bindReference(
|
|
|
278
278
|
// binding claims strictly more than a one-slot binding, so where both are
|
|
279
279
|
// licensed the smaller claim wins.
|
|
280
280
|
moves: STEP * slots.length + STEP,
|
|
281
|
-
unexplained: unexplainedLabel(query, accounted),
|
|
282
281
|
// NOT scaffolding. That field counts answer bytes carried through BECAUSE
|
|
283
282
|
// NOTHING EXPLAINED THEM; a referent is carried because the frame's slot
|
|
284
283
|
// explains it, and it is accounted above. Reporting it would make every
|
|
@@ -677,15 +677,12 @@ export interface MechanismResult {
|
|
|
677
677
|
moves: number;
|
|
678
678
|
/** WHAT THIS ANSWER SPEAKS FOR — the anchors it voices, and therefore the
|
|
679
679
|
* content the reasoner must not pivot back through. Declared by the
|
|
680
|
-
* mechanism about its OWN result, exactly like `accounted`/`
|
|
680
|
+
* mechanism about its OWN result, exactly like `accounted`/`used`/
|
|
681
681
|
* `complete`: post-grounding honours the property and NEVER ASKS WHICH
|
|
682
682
|
* MECHANISM SET IT, so the market stays uniform. An EMPTY set is a real
|
|
683
683
|
* declaration — "this answer voices nothing" (recall) — and withholds
|
|
684
684
|
* nothing; omit the field and the pipeline re-recognises the answer. */
|
|
685
685
|
used?: ReadonlySet<number>;
|
|
686
|
-
unexplained: string;
|
|
687
|
-
/** Explicit weight override. When absent, weight = moves + PASS·unaccounted. */
|
|
688
|
-
weight?: number;
|
|
689
686
|
/** Bytes of `bytes` that came from spans nothing recognised — the asker's
|
|
690
687
|
* own words carried through verbatim rather than derived (see
|
|
691
688
|
* {@link liftedScaffolding}). Reported, not priced: the ladder prices what
|