@hviana/sema 0.8.2 → 0.8.5
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 +38 -37
- package/README.md +17 -38
- package/TRADEMARKS.md +0 -1
- package/dist/example/demo.js +85 -34
- package/dist/src/config.d.ts +11 -0
- package/dist/src/config.js +2 -0
- package/dist/src/geometry.d.ts +21 -10
- package/dist/src/geometry.js +21 -12
- package/dist/src/meter.d.ts +62 -0
- package/dist/src/meter.js +62 -0
- package/dist/src/mind/articulation.js +1 -1
- package/dist/src/mind/attention.d.ts +4 -0
- package/dist/src/mind/attention.js +167 -17
- package/dist/src/mind/canonical.d.ts +16 -0
- package/dist/src/mind/canonical.js +41 -0
- 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 +70 -29
- package/dist/src/mind/match.d.ts +3 -1
- package/dist/src/mind/match.js +7 -3
- 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 +16 -19
- package/dist/src/mind/mechanisms/confluence.d.ts +0 -3
- package/dist/src/mind/mechanisms/confluence.js +27 -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 +40 -13
- package/dist/src/mind/mechanisms/reference.js +3 -4
- package/dist/src/mind/mind.d.ts +4 -2
- package/dist/src/mind/mind.js +5 -4
- package/dist/src/mind/pipeline-mechanism.d.ts +7 -3
- package/dist/src/mind/pipeline.js +136 -44
- package/dist/src/mind/primitives.js +9 -1
- package/dist/src/mind/rationale.d.ts +21 -5
- package/dist/src/mind/rationale.js +16 -21
- package/dist/src/mind/reasoning.d.ts +12 -20
- package/dist/src/mind/reasoning.js +190 -106
- package/dist/src/mind/recognition.js +4 -8
- package/dist/src/mind/resonance.js +20 -1
- package/dist/src/mind/trace.js +1 -0
- package/dist/src/mind/traverse.js +6 -2
- package/dist/src/mind/types.d.ts +36 -13
- 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 +5 -5
- package/docs/architecture/closure.md +65 -0
- package/docs/architecture/commonality.md +29 -20
- package/docs/architecture/cost-model.md +7 -7
- package/docs/architecture/determinism.md +7 -7
- package/docs/architecture/exact-vs-approximate.md +4 -4
- package/docs/architecture/factored-machinery.md +14 -14
- package/docs/architecture/match-project.md +2 -3
- package/docs/architecture/mechanism-market.md +16 -16
- package/docs/architecture/meter.md +10 -11
- package/docs/architecture/store.md +4 -4
- package/docs/architecture/thresholds.md +1 -1
- package/docs/failures/tempting-but-wrong.md +14 -5
- package/docs/harness/gates.md +7 -7
- package/docs/mechanisms/cast.md +2 -2
- package/docs/mechanisms/cover.md +4 -5
- package/docs/mechanisms/extraction.md +7 -7
- package/docs/mechanisms/recall.md +8 -9
- package/example/demo.ts +90 -37
- package/jsr.json +1 -1
- package/package.json +1 -1
- package/src/alu/README.md +11 -12
- package/src/config.ts +13 -0
- package/src/geometry.ts +21 -13
- package/src/meter.ts +62 -0
- package/src/mind/articulation.ts +0 -1
- package/src/mind/attention.ts +169 -17
- package/src/mind/canonical.ts +43 -0
- package/src/mind/derivation.ts +473 -0
- package/src/mind/graph-search.ts +76 -34
- package/src/mind/match.ts +7 -3
- package/src/mind/mechanisms/alu.ts +0 -2
- package/src/mind/mechanisms/cast.ts +20 -22
- package/src/mind/mechanisms/confluence.ts +27 -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 +39 -13
- package/src/mind/mechanisms/reference.ts +2 -3
- package/src/mind/mind.ts +6 -4
- package/src/mind/pipeline-mechanism.ts +7 -3
- package/src/mind/pipeline.ts +160 -52
- package/src/mind/primitives.ts +9 -1
- package/src/mind/rationale.ts +27 -23
- package/src/mind/reasoning.ts +227 -120
- package/src/mind/recognition.ts +4 -8
- package/src/mind/resonance.ts +19 -1
- package/src/mind/trace.ts +1 -0
- package/src/mind/traverse.ts +7 -5
- package/src/mind/types.ts +41 -15
- package/test/105-derive-through-reports-its-refusal.test.mjs +24 -0
- package/test/118-the-join-reaches-a-key-off-the-cut.test.mjs +74 -0
- package/test/119-the-work-does-not-grow-with-the-corpus.test.mjs +122 -0
- package/test/120-composition-is-consequence.test.mjs +132 -0
- package/test/121-the-extension-does-not-grow-with-the-corpus.test.mjs +128 -0
- package/test/122-the-climb-search-does-not-grow-with-the-corpus.test.mjs +117 -0
- package/test/123-the-paired-formulas-agree.test.mjs +90 -0
- package/test/125-the-post-grounding-branch-publishes-its-operand.test.mjs +51 -0
- package/test/126-the-pipeline-does-not-name-mechanisms.test.mjs +42 -0
- package/test/128-the-leads-somewhere-pair-agrees.test.mjs +83 -0
- package/test/129-the-trace-payload-shape.test.mjs +164 -0
- 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/32-confluence.test.mjs +68 -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 +28 -2
- package/test/43-cast-analog-seat.test.mjs +10 -0
- package/test/55-cost-meter.test.mjs +862 -0
|
@@ -14,11 +14,10 @@ import { read } from "../primitives.js";
|
|
|
14
14
|
import { argmaxBy, corpusN, edgeAncestors, hubBound, sharedReachMemo, } from "../traverse.js";
|
|
15
15
|
import { analogyStrength, follow, project, reverseContext, sharedFrameStrengthOf, } from "../match.js";
|
|
16
16
|
import { joinWithBridge } from "../resonance.js";
|
|
17
|
-
import { restatesQuery } from "../reasoning.js";
|
|
18
17
|
import { CONCEPT, STEP } from "../graph-search.js";
|
|
19
18
|
import { indexOf } from "../../bytes.js";
|
|
20
19
|
import { consensusFloor, dominates } from "../../geometry.js";
|
|
21
|
-
import {
|
|
20
|
+
import { restates, unexplainedSpans } from "../derivation.js";
|
|
22
21
|
import { rItem, rNode } from "../trace.js";
|
|
23
22
|
import { dismissedKnownContent } from "../bridge.js";
|
|
24
23
|
import { leafIdRun } from "../canonical.js";
|
|
@@ -89,7 +88,7 @@ const MIN_WEAVE = 2;
|
|
|
89
88
|
* describes id ("...painted by Leonardo da Vinci." contains "Leonardo da
|
|
90
89
|
* Vinci"). An incidental adjacency predecessor never does — it merely
|
|
91
90
|
* preceded id in some unrelated document without ever mentioning it. No
|
|
92
|
-
* new tuned constant: containment is the same primitive `
|
|
91
|
+
* new tuned constant: containment is the same primitive `restates`
|
|
93
92
|
* and `dominates`-style checks already use throughout this codebase.
|
|
94
93
|
*
|
|
95
94
|
* `allowForward` (default true) gates the FORWARD branch specifically —
|
|
@@ -421,7 +420,6 @@ export async function counterfactualTransfer(ctx, query, pre) {
|
|
|
421
420
|
used: used ?? new Set(),
|
|
422
421
|
accounted,
|
|
423
422
|
moves,
|
|
424
|
-
unexplained: unexplainedLabel(query, accounted),
|
|
425
423
|
});
|
|
426
424
|
};
|
|
427
425
|
ctx.trace?.step("alignStructures", [rItem(query, "query")], points.map((p) => rNode(ctx, p.anchor, "structure", p.vote)), "the independent learnt structures the query weaves, by graded alignment");
|
|
@@ -522,7 +520,7 @@ export async function counterfactualTransfer(ctx, query, pre) {
|
|
|
522
520
|
let answer = await joinWithBridge(ctx, filler, tail);
|
|
523
521
|
const fwd = await follow(ctx, proj.anchor, qv);
|
|
524
522
|
if (fwd !== null && indexOf(answer, fwd, 0) < 0 &&
|
|
525
|
-
!
|
|
523
|
+
!restates(query, fwd, 0, { proper: true })) {
|
|
526
524
|
// THROUGH THE SHARED JOINER, not a bare concatenation.
|
|
527
525
|
//
|
|
528
526
|
// `joinWithBridge` is the composition step every out-of-search assembly
|
|
@@ -588,7 +586,7 @@ export async function counterfactualTransfer(ctx, query, pre) {
|
|
|
588
586
|
// cap the test reads "none of the established continuations appears".
|
|
589
587
|
const domNext = ctx.store.nextFirst(dominant.anchor, hubBound(ctx));
|
|
590
588
|
const displaced = domNext
|
|
591
|
-
.every((n) =>
|
|
589
|
+
.every((n) => !restates(query, read(ctx, n), 0));
|
|
592
590
|
// The SUBSTITUTE is what redirection speaks — the answer IS `project(last)`,
|
|
593
591
|
// its own fact — so the same bar applies. The displaced structure is only
|
|
594
592
|
// recognised as the slot being overridden and is never voiced, so it is
|
|
@@ -658,7 +656,7 @@ export async function counterfactualTransfer(ctx, query, pre) {
|
|
|
658
656
|
if (queryScale(p.ctx.length) &&
|
|
659
657
|
indexOf(dominant.ctx, p.ctx, 0) < 0 &&
|
|
660
658
|
indexOf(p.ctx, dominant.ctx, 0) < 0 &&
|
|
661
|
-
|
|
659
|
+
!restates(query, p.ctx, 0)) {
|
|
662
660
|
analogs.push({ anchor: p.anchor, point: p, src: p });
|
|
663
661
|
}
|
|
664
662
|
// Reach through to the point's continuation targets regardless
|
|
@@ -675,7 +673,7 @@ export async function counterfactualTransfer(ctx, query, pre) {
|
|
|
675
673
|
if (!queryScale(nctx.length) ||
|
|
676
674
|
indexOf(dominant.ctx, nctx, 0) >= 0 ||
|
|
677
675
|
indexOf(nctx, dominant.ctx, 0) >= 0 ||
|
|
678
|
-
|
|
676
|
+
restates(query, nctx, 0))
|
|
679
677
|
continue;
|
|
680
678
|
analogs.push({ anchor: nid, point: null, src: p });
|
|
681
679
|
}
|
|
@@ -731,7 +729,7 @@ export async function counterfactualTransfer(ctx, query, pre) {
|
|
|
731
729
|
// grounds") — fine for ORIENTING mechanisms, not for voicing learnt
|
|
732
730
|
// content the query never asked about. Computed once here; both the
|
|
733
731
|
// hub fallback below and the comparison gate consume it.
|
|
734
|
-
const rootTrusted = roots.some((r) => r.
|
|
732
|
+
const rootTrusted = roots.some((r) => r.idfVote >= consensusFloor(corpusN(ctx))); // the IDF sum: the bar's own quantity
|
|
735
733
|
// The context that ESTABLISHES a filler — the same reverse context, under
|
|
736
734
|
// the same naming test, `seatOfNode` uses to VOICE an analog (a predecessor
|
|
737
735
|
// whose bytes CONTAIN the node's: it names or describes it, rather than
|
|
@@ -1132,15 +1130,15 @@ export async function counterfactualTransfer(ctx, query, pre) {
|
|
|
1132
1130
|
// consulting it here is the same fallback `resolve` already makes when an
|
|
1133
1131
|
// exact content lookup misses, and it keeps this mechanism from carrying
|
|
1134
1132
|
// any idea of its own about what a character is.
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1133
|
+
// TWO WITNESSES, ONE LAW: the byte reading, and — when the response carries
|
|
1134
|
+
// one — the same reading under the response's own equivalence. Asked twice
|
|
1135
|
+
// rather than branched on, because the equivalence is a property of the
|
|
1136
|
+
// injected canonicalizer (a substring-monotone function is the usual case,
|
|
1137
|
+
// not a guarantee), and the two readings are OR-ed here exactly as they were
|
|
1138
|
+
// before this became one definition.
|
|
1139
|
+
const echoesQuery = (x) => restates(query, x, 0, { proper: true }) ||
|
|
1140
|
+
(ctx.canon !== null &&
|
|
1141
|
+
restates(query, x, 0, { equate: ctx.canon, proper: true }));
|
|
1144
1142
|
if (echoesQuery(b)) {
|
|
1145
1143
|
const fwd = await follow(ctx, bestAnalog.anchor, qv);
|
|
1146
1144
|
if (fwd !== null && fwd.length > 0 && !echoesQuery(fwd))
|
|
@@ -1240,7 +1238,6 @@ export const castMechanism = {
|
|
|
1240
1238
|
accounted: c.accounted,
|
|
1241
1239
|
moves: c.moves,
|
|
1242
1240
|
used: c.used,
|
|
1243
|
-
unexplained: c.unexplained,
|
|
1244
1241
|
}));
|
|
1245
1242
|
},
|
|
1246
1243
|
};
|
|
@@ -10,9 +10,6 @@ export interface JoinResult {
|
|
|
10
10
|
used: ReadonlySet<number>;
|
|
11
11
|
accounted: Array<[number, number]>;
|
|
12
12
|
moves: number;
|
|
13
|
-
/** A human-readable label for the query bytes the meet left unexplained —
|
|
14
|
-
* purely diagnostic, never priced. */
|
|
15
|
-
unexplained: string;
|
|
16
13
|
}
|
|
17
14
|
/** The main confluence entry point. Given a query, detect whether it weaves
|
|
18
15
|
* two or more INDEPENDENT constraints (ranked anchors supported by disjoint
|
|
@@ -42,7 +42,7 @@ import { read } from "../primitives.js";
|
|
|
42
42
|
import { corpusN, reachOf } from "../traverse.js";
|
|
43
43
|
import { dominates } from "../../geometry.js";
|
|
44
44
|
import { STEP } from "../graph-search.js";
|
|
45
|
-
import {
|
|
45
|
+
import { insideAnsweredTurn } from "../derivation.js";
|
|
46
46
|
import { rItem, rNode } from "../trace.js";
|
|
47
47
|
/** The main confluence entry point. Given a query, detect whether it weaves
|
|
48
48
|
* two or more INDEPENDENT constraints (ranked anchors supported by disjoint
|
|
@@ -75,13 +75,9 @@ export async function confluenceJoin(ctx, query, pre) {
|
|
|
75
75
|
// Recognition and attention still see the full transcript; only this
|
|
76
76
|
// mechanism's constraint population excludes answered spans.
|
|
77
77
|
const queryWin = new Map();
|
|
78
|
-
|
|
78
|
+
const answered = { at: 0 };
|
|
79
79
|
for (const [off, id] of pre.queryWindows) {
|
|
80
|
-
|
|
81
|
-
ctx.answeredSpans[answered][1] <= off)
|
|
82
|
-
answered++;
|
|
83
|
-
const span = ctx.answeredSpans[answered];
|
|
84
|
-
if (span && span[0] <= off && off + W <= span[1])
|
|
80
|
+
if (insideAnsweredTurn(ctx.answeredSpans, answered, off, off + W))
|
|
85
81
|
continue;
|
|
86
82
|
queryWin.set(off, id);
|
|
87
83
|
}
|
|
@@ -98,6 +94,30 @@ export async function confluenceJoin(ctx, query, pre) {
|
|
|
98
94
|
// constraints). Shard-bound streams are no constraints, and their meets
|
|
99
95
|
// are connective debris (". Sure,", "ngul" — observed).
|
|
100
96
|
const bindsAConstituent = (cover) => cover.some(([cs, ce]) => ce - cs >= 2 * W);
|
|
97
|
+
// THE VOTE ENTERS AS ORDER, NEVER AS A BAR. This is the only one of the
|
|
98
|
+
// climb's four consumers (recall, fuseAttention, cast, here) that uses the
|
|
99
|
+
// evidence's MAGNITUDE without a floor, and it is legitimate by construction:
|
|
100
|
+
// `ranked` answers "which anchor is stronger" — a question about votes, so the
|
|
101
|
+
// comparison stays within one dimension — and the vote is otherwise only
|
|
102
|
+
// REPORTED (Stream.vote travels to the rationale's constraint nodes). What
|
|
103
|
+
// actually SELECTS a constraint is byte-structural and never the magnitude: a
|
|
104
|
+
// run of at least 2W (`bindsAConstituent`, with its accidental-sharing
|
|
105
|
+
// counter-examples above), disjoint covers (`disjoint`), and scaffolding never
|
|
106
|
+
// binds at all (`dominates(reachOf(…), N)`). The MEET such a stream may
|
|
107
|
+
// produce is selected the same way: a span shorter than 2W is rejected, and
|
|
108
|
+
// the winner is the one with the smallest `reach` (ties broken by the longer
|
|
109
|
+
// span) — a corpus quantity and bytes, never the vote, which appears only in
|
|
110
|
+
// the trace item.
|
|
111
|
+
// binds at all (`dominates(reachOf(…), N)`). The only cut in this loop is a
|
|
112
|
+
// BUDGET, and it is measured: stopping the scan at 2W anchors saves 50-70% of
|
|
113
|
+
// confluence's cost on non-conjunctive queries while preserving every genuinely
|
|
114
|
+
// conjunctive case, whose top anchors ARE its constraints.
|
|
115
|
+
// MEASURED (this goal, on THIS file's own conjunctive fixture): the two
|
|
116
|
+
// streams appear at ranks 1 and 4 against a budget of 2W = 8, on a query whose
|
|
117
|
+
// `ranked` is 9 — so the cut IS live (it would have returned null at the 8th
|
|
118
|
+
// anchor) and it does NOT prune the case it exists to protect. The other
|
|
119
|
+
// conjunctive fixture (the Leonardo one) finds them at ranks 0 and 1. Scope:
|
|
120
|
+
// these are the repo's conjunctive fixtures, and no more.
|
|
101
121
|
const streams = [];
|
|
102
122
|
const rankedCapped = ranked.length > pre.k ? ranked.slice(0, pre.k) : ranked;
|
|
103
123
|
// CONJUNCTIVITY EARLY-EXIT: a conjunctive query's top-ranked anchors
|
|
@@ -234,7 +254,6 @@ export async function confluenceJoin(ctx, query, pre) {
|
|
|
234
254
|
used: new Set([met.a.anchor, met.b.anchor]),
|
|
235
255
|
accounted,
|
|
236
256
|
moves: 3 * STEP,
|
|
237
|
-
unexplained: unexplainedLabel(query, accounted),
|
|
238
257
|
};
|
|
239
258
|
}
|
|
240
259
|
// ── Pipeline mechanism ──────────────────────────────────────────────────────
|
|
@@ -265,7 +284,6 @@ export const confluenceMechanism = {
|
|
|
265
284
|
accounted: met.accounted,
|
|
266
285
|
moves: met.moves,
|
|
267
286
|
used: met.used,
|
|
268
|
-
unexplained: met.unexplained,
|
|
269
287
|
}];
|
|
270
288
|
},
|
|
271
289
|
};
|
|
@@ -13,8 +13,8 @@ import { guidedFirst, hubBound } from "../traverse.js";
|
|
|
13
13
|
import { conceptHop } from "../match.js";
|
|
14
14
|
import { bridge } from "../resonance.js";
|
|
15
15
|
import { liftAnswer, liftedScaffolding, segRestatesQuery } from "../types.js";
|
|
16
|
-
import { decodeText
|
|
17
|
-
import {
|
|
16
|
+
import { decodeText } from "../rationale.js";
|
|
17
|
+
import { insideAnsweredTurn, restates } from "../derivation.js";
|
|
18
18
|
import { rItem, rNode, traceDerivation } from "../trace.js";
|
|
19
19
|
// ── Concept / connector pre-resolution ──────────────────────────────────────
|
|
20
20
|
export async function resolveConcepts(ctx, sites) {
|
|
@@ -45,16 +45,13 @@ export async function resolveConnectors(ctx, sites, query) {
|
|
|
45
45
|
// discarded — a semantically neutral gate (it removes work whose product
|
|
46
46
|
// liftAnswer throws away), and a cumulative (multi-turn) query is exactly
|
|
47
47
|
// where such already-answered continuations recur.
|
|
48
|
-
|
|
48
|
+
const answered = { at: 0 };
|
|
49
49
|
const ordered = [...sites]
|
|
50
50
|
.sort((a, b) => a.start - b.start)
|
|
51
51
|
.filter((s) => {
|
|
52
|
-
|
|
53
|
-
ctx.answeredSpans[answered][1] <= s.start)
|
|
54
|
-
answered++;
|
|
55
|
-
const span = ctx.answeredSpans[answered];
|
|
56
|
-
if (span && span[0] <= s.start && s.end <= span[1])
|
|
52
|
+
if (insideAnsweredTurn(ctx.answeredSpans, answered, s.start, s.end)) {
|
|
57
53
|
return false;
|
|
54
|
+
}
|
|
58
55
|
if (query === undefined || ctx.answeredSpans.length === 0)
|
|
59
56
|
return true;
|
|
60
57
|
const continuations = ctx.store.nextFirst(s.payload, hubBound(ctx));
|
|
@@ -77,7 +74,11 @@ export async function resolveConnectors(ctx, sites, query) {
|
|
|
77
74
|
// 3 bytes this reads 4 bytes per candidate instead of the ~231 it
|
|
78
75
|
// averaged before.
|
|
79
76
|
const bytes = read(ctx, answer, query.length + 1);
|
|
80
|
-
|
|
77
|
+
// THE CONTENT READING of the same exclusion: the site's own
|
|
78
|
+
// continuation already occurs in the query, so voicing it back adds
|
|
79
|
+
// nothing. It is the restatement law with no `proper` flag — the
|
|
80
|
+
// containment reading that also admits the whole query.
|
|
81
|
+
return restates(query, bytes, 0);
|
|
81
82
|
});
|
|
82
83
|
});
|
|
83
84
|
const bridgePair = async (l, r) => {
|
|
@@ -171,18 +172,11 @@ export const coverMechanism = {
|
|
|
171
172
|
? await ctx.meter.time("cover.resolveConnectors", () => resolveConnectors(ctx, sites, query))
|
|
172
173
|
: await resolveConnectors(ctx, sites, query);
|
|
173
174
|
let splits = rec.splits;
|
|
174
|
-
let starts = rec.starts;
|
|
175
175
|
if (computed.length > 0) {
|
|
176
176
|
splits = new Set(rec.splits);
|
|
177
|
-
starts = new Set(rec.starts);
|
|
178
177
|
for (const u of computed) {
|
|
179
178
|
splits.add(u.i);
|
|
180
179
|
splits.add(u.j);
|
|
181
|
-
// A computation's own boundaries carry the same fold-level evidence
|
|
182
|
-
// a chunk boundary does — "computation always wins" (see the header
|
|
183
|
-
// comment) extends to being trusted ground for cross-leaf recovery.
|
|
184
|
-
starts.add(u.i);
|
|
185
|
-
starts.add(u.j);
|
|
186
180
|
}
|
|
187
181
|
}
|
|
188
182
|
const concepts = ctx.meter
|
|
@@ -208,7 +202,7 @@ export const coverMechanism = {
|
|
|
208
202
|
])),
|
|
209
203
|
...computedResults.map((u) => rItem(u.bytes, "computed")),
|
|
210
204
|
], coverDeps.length ? coverDeps : undefined);
|
|
211
|
-
const solved = ctx.search.cover(query.length, sites, concepts, rec.leaves, splits,
|
|
205
|
+
const solved = ctx.search.cover(query.length, sites, concepts, rec.leaves, splits, undefined, connectors, computedResults, ctx.trace ? (steps) => traceDerivation(ctx, steps) : undefined);
|
|
212
206
|
const segs = solved && solved.segs;
|
|
213
207
|
tCover?.done(segs === null
|
|
214
208
|
? []
|
|
@@ -247,9 +241,12 @@ export const coverMechanism = {
|
|
|
247
241
|
return [{
|
|
248
242
|
bytes: composed,
|
|
249
243
|
accounted,
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
244
|
+
// The derivation's DISCRETE work. The bytes the chart could not
|
|
245
|
+
// recognise are NOT priced here: they are exactly the spans `accounted`
|
|
246
|
+
// leaves uncovered, and the pipeline's one formula charges them at PASS —
|
|
247
|
+
// the same formula that prices every other mechanism's candidate. No
|
|
248
|
+
// mechanism spells a cost of its own.
|
|
249
|
+
moves: solved.moves,
|
|
253
250
|
// How much of the composed answer is the asker's own unexplained words
|
|
254
251
|
// (the spans the liftAnswer trace above labels "scaffolding"). Cover is
|
|
255
252
|
// the mechanism that can carry them, because a PASS span still lands in
|
|
@@ -19,7 +19,6 @@ import type { PipelineMechanism, Precomputed } from "../pipeline-mechanism.js";
|
|
|
19
19
|
export declare function extractBySkill(ctx: MindContext, query: Uint8Array, pre: Precomputed): Promise<{
|
|
20
20
|
bytes: Uint8Array;
|
|
21
21
|
accounted: Array<[number, number]>;
|
|
22
|
-
unexplained: string;
|
|
23
22
|
} | null>;
|
|
24
23
|
/** Decompose an answer into substrings of its surrounding context, in order —
|
|
25
24
|
* the STRONG span-shape reading (see the section note above). Returns null
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// that contains it.
|
|
9
9
|
import { locate } from "../match.js";
|
|
10
10
|
import { concatBytes, indexOf } from "../../bytes.js";
|
|
11
|
-
import { decodeText
|
|
11
|
+
import { decodeText } from "../rationale.js";
|
|
12
12
|
import { CONCEPT, STEP } from "../graph-search.js";
|
|
13
13
|
import { rItem, rNode, traceFail } from "../trace.js";
|
|
14
14
|
// ── Extraction ────────────────────────────────────────────────────────────
|
|
@@ -81,6 +81,12 @@ export async function extractBySkill(ctx, query, pre) {
|
|
|
81
81
|
const searched = ranked.slice(0, pre.k);
|
|
82
82
|
let shapeMisses = 0;
|
|
83
83
|
let subQuantum = 0;
|
|
84
|
+
// A SECOND refusal counter, because the note below used to call an UNANCHORED
|
|
85
|
+
// read "sub-quantum" — which is false, and it is the kind of instrumentation
|
|
86
|
+
// defect AGENTS §6 says to close where it lives: a reader could not tell from
|
|
87
|
+
// the trace which of the two gates refused. Neither counter reaches a
|
|
88
|
+
// decision (meter.ts contract 1); they exist so the refusal is legible.
|
|
89
|
+
let unanchored = 0;
|
|
84
90
|
for (const cand of searched) {
|
|
85
91
|
const exemplar = await pre.spanShapedOf(cand.anchor);
|
|
86
92
|
if (!exemplar) {
|
|
@@ -116,15 +122,16 @@ export async function extractBySkill(ctx, query, pre) {
|
|
|
116
122
|
// Here the field is this mechanism's own output and carries its documented
|
|
117
123
|
// meaning, so the test is sound exactly where the convention does not reach.
|
|
118
124
|
if (built.accounted.length === 0) {
|
|
119
|
-
|
|
125
|
+
unanchored++;
|
|
120
126
|
continue;
|
|
121
127
|
}
|
|
122
|
-
if (shapeMisses > 0 || subQuantum > 0) {
|
|
128
|
+
if (shapeMisses > 0 || subQuantum > 0 || unanchored > 0) {
|
|
123
129
|
ctx.trace?.step("trySkillAnchors", [
|
|
124
|
-
rItem(query.subarray(0, 0), `skipped ${shapeMisses + subQuantum}`),
|
|
130
|
+
rItem(query.subarray(0, 0), `skipped ${shapeMisses + subQuantum + unanchored}`),
|
|
125
131
|
rNode(ctx, cand.anchor, "chosen"),
|
|
126
|
-
], [], `skipped ${shapeMisses} non-exemplar
|
|
127
|
-
|
|
132
|
+
], [], `skipped ${shapeMisses} non-exemplar, ${subQuantum} sub-quantum and ` +
|
|
133
|
+
`${unanchored} unanchored anchor(s) before one yielded a usable ` +
|
|
134
|
+
`extraction`);
|
|
128
135
|
}
|
|
129
136
|
t?.done([rItem(built.bytes, "extracted")], built.pieces === 1
|
|
130
137
|
? `apply a learnt extraction skill — read the analogous span of the query` +
|
|
@@ -134,7 +141,6 @@ export async function extractBySkill(ctx, query, pre) {
|
|
|
134
141
|
return {
|
|
135
142
|
bytes: built.bytes,
|
|
136
143
|
accounted: built.accounted,
|
|
137
|
-
unexplained: unexplainedLabel(query, built.accounted),
|
|
138
144
|
};
|
|
139
145
|
}
|
|
140
146
|
if (shapeMisses === searched.length) {
|
|
@@ -321,7 +327,6 @@ export const extractionMechanism = {
|
|
|
321
327
|
bytes: ex.bytes,
|
|
322
328
|
accounted: ex.accounted,
|
|
323
329
|
moves: CONCEPT + STEP * ex.accounted.length,
|
|
324
|
-
unexplained: ex.unexplained,
|
|
325
330
|
}];
|
|
326
331
|
},
|
|
327
332
|
};
|
|
@@ -255,7 +255,6 @@ export const prefixMechanism = {
|
|
|
255
255
|
// IDENTITY bridge takes.
|
|
256
256
|
accounted: [[0, query.length]],
|
|
257
257
|
moves: STEP,
|
|
258
|
-
unexplained: "",
|
|
259
258
|
// NOT complete: the query is a proper PREFIX, so the form may carry more
|
|
260
259
|
// past the remainder this voiced.
|
|
261
260
|
}];
|
|
@@ -6,7 +6,6 @@ export interface RecallResult {
|
|
|
6
6
|
echoed: boolean;
|
|
7
7
|
accounted: Array<[number, number]>;
|
|
8
8
|
moves: number;
|
|
9
|
-
unexplained: string;
|
|
10
9
|
/** See {@link import("../pipeline-mechanism.js").MechanismResult.complete}
|
|
11
10
|
* — set by the IDENTITY-bridge tier alone. */
|
|
12
11
|
complete?: boolean;
|
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
import { cosine } from "../../vec.js";
|
|
7
7
|
import { consensusFloor, dominates, identityBar, reachThreshold, significanceBar, } from "../../geometry.js";
|
|
8
8
|
import { gistOf, read, resolve } from "../primitives.js";
|
|
9
|
-
import {
|
|
9
|
+
import { indexOf } from "../../bytes.js";
|
|
10
10
|
import { allWindowsAreScaffolding, corpusN, hubBound } from "../traverse.js";
|
|
11
11
|
import { follow, project, reverseContext, voicesDisplacedFiller, } from "../match.js";
|
|
12
12
|
import { CONCEPT, STEP } from "../graph-search.js";
|
|
13
|
-
import {
|
|
13
|
+
import { restates as lawRestates } from "../derivation.js";
|
|
14
14
|
import { rItem, rNode } from "../trace.js";
|
|
15
15
|
import { substitutionBridge } from "../bridge.js";
|
|
16
16
|
/** Recall the answer by resonating the whole query against the content index. */
|
|
@@ -29,7 +29,6 @@ export async function recallByResonance(ctx, query, pre) {
|
|
|
29
29
|
echoed,
|
|
30
30
|
accounted,
|
|
31
31
|
moves,
|
|
32
|
-
unexplained: unexplainedLabel(query, accounted),
|
|
33
32
|
...(complete ? { complete } : {}),
|
|
34
33
|
};
|
|
35
34
|
};
|
|
@@ -103,7 +102,7 @@ export async function recallByResonance(ctx, query, pre) {
|
|
|
103
102
|
// guard the argument's OWN later restatement in the same
|
|
104
103
|
// conversation reads as if it were the next thing to say.
|
|
105
104
|
if (g !== null && g.length > 0 &&
|
|
106
|
-
!(
|
|
105
|
+
!lawRestates(query, g, 0, { proper: true })) {
|
|
107
106
|
return ground(g, "argument binding — the query's sole edge-source constituent, continuation followed", [[arg.start, arg.end]], STEP);
|
|
108
107
|
}
|
|
109
108
|
}
|
|
@@ -130,9 +129,10 @@ export async function recallByResonance(ctx, query, pre) {
|
|
|
130
129
|
// same principle that keeps cast from voicing stored questions), and
|
|
131
130
|
// projecting them forward is reverse recall's containment failure in the
|
|
132
131
|
// other direction — "whatever followed these bytes in some document".
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
132
|
+
// THE EQUALITY READING of the restatement law: this tier rejects an answer
|
|
133
|
+
// that IS the question (an echo), and a proper fragment is handled by the
|
|
134
|
+
// tier's own subspan tests further down — so the law is asked with `whole`.
|
|
135
|
+
const restates = (b) => lawRestates(query, b, 0, { equate: ctx.canon, whole: true });
|
|
136
136
|
const idBar = identityBar(ctx.store.D, ctx.space.maxGroup, query.length);
|
|
137
137
|
if (top.score >= idBar) {
|
|
138
138
|
for (const h of whole) {
|
|
@@ -194,9 +194,36 @@ export async function recallByResonance(ctx, query, pre) {
|
|
|
194
194
|
// consensus", while breadth is the SCALE-INVARIANT reading — "a point whose
|
|
195
195
|
// breadth clears `dominates` (> half the query's regions corroborate it) is
|
|
196
196
|
// real consensus; one that does not is a coincidental single-region echo".
|
|
197
|
-
//
|
|
198
|
-
// comparing a POOLED SUM against a floor that prices ONE region's
|
|
199
|
-
// is a dimensional error.
|
|
197
|
+
// THIS USED TO CLAIM A DIMENSIONAL ERROR, AND THAT CLAIM WAS FALSE.
|
|
198
|
+
// It read: "comparing a POOLED SUM against a floor that prices ONE region's
|
|
199
|
+
// evidence is a dimensional error." `consensusFloor` is not priced for one
|
|
200
|
+
// region: thresholds.md §2 derives it as the POOLED-vote significance floor —
|
|
201
|
+
// "each region contributes at most ln(N/c) <= ln(N); ln(N)+1/2 demands ..." —
|
|
202
|
+
// and attention.ts says the same where it builds the vote ("the scale
|
|
203
|
+
// consensusFloor is derived for"). The comparison is in ONE dimension, and
|
|
204
|
+
// it is so because the climb WEIGHTS BY IDF: `wf` in voteRegions is
|
|
205
|
+
// `direct ? df : combined ? idf + df : idf`, and the engine only ever runs the
|
|
206
|
+
// last one (DFMode's default "inverse", the mode every non-test caller uses —
|
|
207
|
+
// `direct` and `combined` are exercised by test/24 and test/27 only, and
|
|
208
|
+
// test/24 pins that their votes DO differ). In those two the sum would leave
|
|
209
|
+
// the floor's dimension and the floor would need re-deriving.
|
|
210
|
+
//
|
|
211
|
+
// What the OR below is really for is SCALE, not dimension (the paragraph
|
|
212
|
+
// above says it): a vote that clears ln(N)+1/2 means "strong" on a small store
|
|
213
|
+
// and "weak" on a large one for the same genuine consensus, so the
|
|
214
|
+
// scale-invariant breadth reading is added beside it.
|
|
215
|
+
//
|
|
216
|
+
// AND THE PREMISE IS IDF. The deviation in the other two weighting modes is
|
|
217
|
+
// TWO-SIDED and DERIVED: `direct` DEFLATES a region (ln(1+c) < ln(N/c) for
|
|
218
|
+
// small c) and `combined` INFLATES it (ln N + ln(1+1/c)), both by at most
|
|
219
|
+
// `ln 2` — see `geometry.ts`'s `consensusFloor`, where the bound lives.
|
|
220
|
+
// MEASURED on 8 anchors across 5 queries, running the same climb in all
|
|
221
|
+
// three modes: ZERO gate inversions — every anchor's `vote >= floor` verdict
|
|
222
|
+
// is the same in `inverse`, `direct` and `combined`, even where the readings
|
|
223
|
+
// straddle the floor on opposite sides (#148: inverse 3.39, combined 4.71
|
|
224
|
+
// above it, direct 1.31 below). Pinned by test/55's test 20. The bar is not
|
|
225
|
+
// re-derived for those modes because nothing reachable needs it; the premise
|
|
226
|
+
// is IDF, and that is now written where the gate reads it.
|
|
200
227
|
//
|
|
201
228
|
// Measured on the 15.7M-node store (N=325,615, so the old floor was 13.19).
|
|
202
229
|
// The absolute vote cannot separate right from wrong at this scale, and the
|
|
@@ -265,7 +292,7 @@ export async function recallByResonance(ctx, query, pre) {
|
|
|
265
292
|
const minVote = consensusFloor(corpusN(ctx));
|
|
266
293
|
if (forest.length > 0 &&
|
|
267
294
|
!allWindowsAreScaffolding(ctx, query) &&
|
|
268
|
-
(forest[0].
|
|
295
|
+
(forest[0].idfVote >= minVote || // the IDF sum: the bar's own quantity
|
|
269
296
|
(dominates(forest[0].breadth, 1) && forest[0].peak > Math.LN2))) {
|
|
270
297
|
const g = await project(ctx, forest[0].anchor, queryGist);
|
|
271
298
|
// THE ANCHOR'S OCCUPANT IS NOT THE ASKER'S. This tier grounds an anchor
|
|
@@ -288,7 +315,7 @@ export async function recallByResonance(ctx, query, pre) {
|
|
|
288
315
|
// — never an answer (the same principle as `restates` above, extended
|
|
289
316
|
// to fragments). Genuine anchor groundings — longer than the query,
|
|
290
317
|
// or disjoint from it — pass untouched.
|
|
291
|
-
else if (g && !(
|
|
318
|
+
else if (g && !lawRestates(query, g, 0, { proper: true })) {
|
|
292
319
|
return ground(g, "scaffolding-dominated query — ground the consensus-climb anchor", [[forest[0].start, forest[0].end]], CONCEPT);
|
|
293
320
|
}
|
|
294
321
|
}
|
|
@@ -466,8 +493,8 @@ export const recallMechanism = {
|
|
|
466
493
|
bytes: r.bytes,
|
|
467
494
|
accounted: r.accounted,
|
|
468
495
|
moves: r.moves,
|
|
469
|
-
unexplained: r.unexplained,
|
|
470
496
|
provenance: r.echoed ? "recall-echo" : "recall",
|
|
497
|
+
used: new Set(),
|
|
471
498
|
...(r.complete ? { complete: true } : {}),
|
|
472
499
|
}];
|
|
473
500
|
},
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
// made AVAILABLE, never imposed.
|
|
36
36
|
import { carriesFillers, distinct, follow, substituteAll } from "../match.js";
|
|
37
37
|
import { dominates } from "../../geometry.js";
|
|
38
|
-
import { bytesEqual
|
|
39
|
-
import {
|
|
38
|
+
import { bytesEqual } from "../../bytes.js";
|
|
39
|
+
import { restates } from "../derivation.js";
|
|
40
40
|
import { STEP } from "../graph-search.js";
|
|
41
41
|
import { rItem, rNode, traceFail } from "../trace.js";
|
|
42
42
|
/** The minimum number of instances that can establish a frame. One instance
|
|
@@ -196,7 +196,7 @@ export async function bindReference(ctx, query, pre) {
|
|
|
196
196
|
return fail("the binding produced nothing");
|
|
197
197
|
// Answering with the question is not answering — the same restated-fragment
|
|
198
198
|
// guard every recall tier applies.
|
|
199
|
-
if (
|
|
199
|
+
if (restates(query, bytes, 0, { proper: true })) {
|
|
200
200
|
return fail("the binding restates part of the question");
|
|
201
201
|
}
|
|
202
202
|
const carried = !bytesEqual(bytes, first);
|
|
@@ -230,7 +230,6 @@ export async function bindReference(ctx, query, pre) {
|
|
|
230
230
|
// binding claims strictly more than a one-slot binding, so where both are
|
|
231
231
|
// licensed the smaller claim wins.
|
|
232
232
|
moves: STEP * slots.length + STEP,
|
|
233
|
-
unexplained: unexplainedLabel(query, accounted),
|
|
234
233
|
// NOT scaffolding. That field counts answer bytes carried through BECAUSE
|
|
235
234
|
// NOTHING EXPLAINED THEM; a referent is carried because the frame's slot
|
|
236
235
|
// explains it, and it is accounted above. Reporting it would make every
|
package/dist/src/mind/mind.d.ts
CHANGED
|
@@ -75,6 +75,8 @@ export interface MindOptions {
|
|
|
75
75
|
seed?: number;
|
|
76
76
|
recallQueryK?: number;
|
|
77
77
|
haloQueryK?: number;
|
|
78
|
+
/** Branch nodes the pivot sweep may probe — see {@link MindConfig}. */
|
|
79
|
+
pivotProbeK?: number;
|
|
78
80
|
/** Items one rationale step may itemise — see {@link MindConfig}. */
|
|
79
81
|
rationaleSampleK?: number;
|
|
80
82
|
/** Corpus-reading capacities and budgets — see {@link MindConfig}. */
|
|
@@ -202,8 +204,8 @@ export declare class Mind implements MindContext {
|
|
|
202
204
|
* with the most distributional evidence (highest `prevOf` count — the
|
|
203
205
|
* structural manifestation of its halo). When evidence is equal the
|
|
204
206
|
* first-inserted edge wins. */
|
|
205
|
-
/** See {@link GraphSearchHost.
|
|
206
|
-
|
|
207
|
+
/** See {@link GraphSearchHost.contentKeyEnds}. */
|
|
208
|
+
contentKeyEnds(prefix: Uint8Array, tail: Uint8Array): readonly number[];
|
|
207
209
|
chooseNext(node: number): number | undefined;
|
|
208
210
|
constructor(opts?: MindOptions);
|
|
209
211
|
constructor(cfg: MindConfig, store: Store, _fromStore: true);
|
package/dist/src/mind/mind.js
CHANGED
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
import { makeKeyring, rng, setVecConfig } from "../vec.js";
|
|
12
12
|
import { sampleCorpus, searchCorpus } from "./corpus.js";
|
|
13
13
|
import { Alphabet } from "../alphabet.js";
|
|
14
|
-
import {
|
|
14
|
+
import { contentFoldIncremental, reachThreshold, } from "../geometry.js";
|
|
15
|
+
import { keyEnds } from "./canonical.js";
|
|
15
16
|
import { BoundedMap } from "../store.js";
|
|
16
17
|
import { SQliteStore } from "../store-sqlite.js";
|
|
17
18
|
import { resolveConfig } from "../config.js";
|
|
@@ -160,9 +161,9 @@ export class Mind {
|
|
|
160
161
|
* with the most distributional evidence (highest `prevOf` count — the
|
|
161
162
|
* structural manifestation of its halo). When evidence is equal the
|
|
162
163
|
* first-inserted edge wins. */
|
|
163
|
-
/** See {@link GraphSearchHost.
|
|
164
|
-
|
|
165
|
-
return
|
|
164
|
+
/** See {@link GraphSearchHost.contentKeyEnds}. */
|
|
165
|
+
contentKeyEnds(prefix, tail) {
|
|
166
|
+
return keyEnds(this, prefix, tail);
|
|
166
167
|
}
|
|
167
168
|
chooseNext(node) {
|
|
168
169
|
return chooseNext(this, node, this._edgeGuide);
|
|
@@ -151,10 +151,14 @@ export interface MechanismResult {
|
|
|
151
151
|
bytes: Uint8Array;
|
|
152
152
|
accounted: Array<[number, number]>;
|
|
153
153
|
moves: number;
|
|
154
|
+
/** WHAT THIS ANSWER SPEAKS FOR — the anchors it voices, and therefore the
|
|
155
|
+
* content the reasoner must not pivot back through. Declared by the
|
|
156
|
+
* mechanism about its OWN result, exactly like `accounted`/`used`/
|
|
157
|
+
* `complete`: post-grounding honours the property and NEVER ASKS WHICH
|
|
158
|
+
* MECHANISM SET IT, so the market stays uniform. An EMPTY set is a real
|
|
159
|
+
* declaration — "this answer voices nothing" (recall) — and withholds
|
|
160
|
+
* nothing; omit the field and the pipeline re-recognises the answer. */
|
|
154
161
|
used?: ReadonlySet<number>;
|
|
155
|
-
unexplained: string;
|
|
156
|
-
/** Explicit weight override. When absent, weight = moves + PASS·unaccounted. */
|
|
157
|
-
weight?: number;
|
|
158
162
|
/** Bytes of `bytes` that came from spans nothing recognised — the asker's
|
|
159
163
|
* own words carried through verbatim rather than derived (see
|
|
160
164
|
* {@link liftedScaffolding}). Reported, not priced: the ladder prices what
|