@hviana/sema 0.2.2 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/mind/articulation.js +1 -1
- package/dist/src/mind/attention.d.ts +18 -2
- package/dist/src/mind/attention.js +88 -18
- package/dist/src/mind/bridge.d.ts +30 -0
- package/dist/src/mind/bridge.js +569 -0
- package/dist/src/mind/graph-search.d.ts +16 -1
- package/dist/src/mind/graph-search.js +34 -5
- package/dist/src/mind/match.d.ts +15 -2
- package/dist/src/mind/match.js +3 -8
- package/dist/src/mind/mechanisms/alu.js +8 -1
- package/dist/src/mind/mechanisms/cast.d.ts +54 -0
- package/dist/src/mind/mechanisms/cast.js +303 -48
- package/dist/src/mind/mechanisms/cover.js +24 -32
- package/dist/src/mind/mechanisms/extraction.js +75 -30
- package/dist/src/mind/mechanisms/recall.js +66 -0
- package/dist/src/mind/mind.d.ts +1 -0
- package/dist/src/mind/mind.js +6 -1
- package/dist/src/mind/pipeline.js +34 -2
- package/dist/src/mind/reasoning.d.ts +20 -1
- package/dist/src/mind/reasoning.js +84 -6
- package/dist/src/mind/recognition.js +157 -13
- package/dist/src/mind/traverse.js +16 -0
- package/dist/src/mind/types.d.ts +65 -2
- package/dist/src/mind/types.js +53 -7
- package/dist/src/store.d.ts +12 -3
- package/dist/src/store.js +9 -3
- package/package.json +1 -1
- package/src/mind/articulation.ts +1 -0
- package/src/mind/attention.ts +105 -17
- package/src/mind/bridge.ts +596 -0
- package/src/mind/graph-search.ts +59 -2
- package/src/mind/match.ts +19 -5
- package/src/mind/mechanisms/alu.ts +8 -1
- package/src/mind/mechanisms/cast.ts +336 -46
- package/src/mind/mechanisms/cover.ts +31 -36
- package/src/mind/mechanisms/extraction.ts +101 -40
- package/src/mind/mechanisms/recall.ts +79 -0
- package/src/mind/mind.ts +7 -1
- package/src/mind/pipeline.ts +37 -2
- package/src/mind/reasoning.ts +97 -5
- package/src/mind/recognition.ts +160 -12
- package/src/mind/traverse.ts +17 -0
- package/src/mind/types.ts +110 -6
- package/src/store.ts +19 -5
- package/test/35-attention-confidence.test.mjs +139 -0
- package/test/36-already-answered-fusion.test.mjs +128 -0
- package/test/37-cluster-dispersion-fusion.test.mjs +190 -0
- package/test/38-reason-restate-guard.test.mjs +94 -0
- package/test/39-cast-restate-guard.test.mjs +102 -0
- package/test/40-choosenext-scale-guard.test.mjs +75 -0
- package/test/41-seatofnode-direction.test.mjs +85 -0
- package/test/42-recognise-trace-idempotence.test.mjs +106 -0
- package/test/43-cast-analog-seat.test.mjs +244 -0
- package/test/44-recognise-edge-whitespace.test.mjs +63 -0
- package/test/45-liftanswer-restated-trim.test.mjs +60 -0
- package/test/46-recognise-multibyte-edge.test.mjs +85 -0
- package/test/47-cast-comparison-coverage.test.mjs +134 -0
- package/test/48-recognise-turn-connective.test.mjs +125 -0
- package/test/49-natural-units-synonym-bridge.test.mjs +175 -0
- package/test/50-cast-analog-consensus-floor.test.mjs +179 -0
package/src/mind/graph-search.ts
CHANGED
|
@@ -96,6 +96,18 @@ export type GItem =
|
|
|
96
96
|
cover: boolean;
|
|
97
97
|
rec: boolean;
|
|
98
98
|
node?: number;
|
|
99
|
+
/** Set only for a {@link ComputedResult} axiom (an extension's derived
|
|
100
|
+
* value, e.g. ALU arithmetic) — as opposed to a genuinely RECOGNISED
|
|
101
|
+
* learned form. Both set `rec: true` (a computation bridges the cover
|
|
102
|
+
* exactly like a learned terminal answer), but they mean different
|
|
103
|
+
* things for `i..j`'s WIDTH: a recognised form's query-span width is
|
|
104
|
+
* real evidence of how much of the query's meaning it accounts for
|
|
105
|
+
* (liftAnswer's half-dominance framing decision); a computed span's
|
|
106
|
+
* width is operand digit-count, uncorrelated with meaning ("1000 - 421"
|
|
107
|
+
* is wider than "15 * 7" only because the numbers are bigger, not
|
|
108
|
+
* because subtraction is more "the point" of its query). See
|
|
109
|
+
* {@link liftAnswer}. */
|
|
110
|
+
computed?: boolean;
|
|
99
111
|
};
|
|
100
112
|
type OutItem = Extract<GItem, { kind: "out" }>;
|
|
101
113
|
|
|
@@ -138,6 +150,9 @@ export interface Seg {
|
|
|
138
150
|
bytes: Uint8Array;
|
|
139
151
|
rec: boolean;
|
|
140
152
|
node?: number;
|
|
153
|
+
/** See the `computed` field of the "out" {@link GItem} — set only for an
|
|
154
|
+
* extension's derived value, never a genuinely recognised learned form. */
|
|
155
|
+
computed?: boolean;
|
|
141
156
|
}
|
|
142
157
|
|
|
143
158
|
/** Read the chosen spans back off a derivation: the goal is a chain of bridge
|
|
@@ -155,6 +170,7 @@ function readCover(derivation: Derivation<GItem>): Seg[] {
|
|
|
155
170
|
bytes: out.bytes,
|
|
156
171
|
rec: out.rec,
|
|
157
172
|
node: out.node,
|
|
173
|
+
computed: out.computed,
|
|
158
174
|
});
|
|
159
175
|
}
|
|
160
176
|
node = node.premises[0];
|
|
@@ -356,6 +372,7 @@ export class GraphSearch {
|
|
|
356
372
|
conceptTarget: ReadonlyMap<number, number>,
|
|
357
373
|
leaves: ReadonlyArray<Leaf>,
|
|
358
374
|
splits: ReadonlySet<number>,
|
|
375
|
+
starts: ReadonlySet<number>,
|
|
359
376
|
substitutions?: ReadonlyMap<number, Uint8Array>,
|
|
360
377
|
connectors?: ReadonlyMap<string, Uint8Array>,
|
|
361
378
|
computedResults?: ReadonlyArray<ComputedResult>,
|
|
@@ -377,6 +394,7 @@ export class GraphSearch {
|
|
|
377
394
|
sites,
|
|
378
395
|
leaves,
|
|
379
396
|
splits,
|
|
397
|
+
starts,
|
|
380
398
|
},
|
|
381
399
|
conceptTarget,
|
|
382
400
|
substitutions,
|
|
@@ -405,6 +423,7 @@ export class GraphSearch {
|
|
|
405
423
|
sites: ReadonlyArray<Site>;
|
|
406
424
|
leaves: ReadonlyArray<Leaf>;
|
|
407
425
|
splits: ReadonlySet<number>;
|
|
426
|
+
starts: ReadonlySet<number>;
|
|
408
427
|
},
|
|
409
428
|
conceptTarget: ReadonlyMap<number, number>,
|
|
410
429
|
substitutions?: ReadonlyMap<number, Uint8Array>,
|
|
@@ -418,6 +437,7 @@ export class GraphSearch {
|
|
|
418
437
|
conceptTarget,
|
|
419
438
|
recognition.leaves,
|
|
420
439
|
recognition.splits,
|
|
440
|
+
recognition.starts,
|
|
421
441
|
substitutions,
|
|
422
442
|
connectors,
|
|
423
443
|
computedResults,
|
|
@@ -448,11 +468,22 @@ export class GraphSearch {
|
|
|
448
468
|
conceptTarget: ReadonlyMap<number, number>,
|
|
449
469
|
leaves: ReadonlyArray<Leaf>,
|
|
450
470
|
splits: ReadonlySet<number>,
|
|
471
|
+
starts: ReadonlySet<number>,
|
|
451
472
|
substitutions?: ReadonlyMap<number, Uint8Array>,
|
|
452
473
|
connectors?: ReadonlyMap<string, Uint8Array>,
|
|
453
474
|
computedResults?: ReadonlyArray<ComputedResult>,
|
|
454
475
|
): DeductionSystem<GItem> {
|
|
455
476
|
const W = this.maxGroup; // fusible span ceiling (shortest composite bound)
|
|
477
|
+
// Same corpus-scale hub floor {@link atomIsHub}/{@link atomReach} (traverse.ts)
|
|
478
|
+
// derive for byte atoms — duplicated here rather than imported because this
|
|
479
|
+
// module is deliberately host-based (no MindContext), and both inputs
|
|
480
|
+
// (maxGroup, edgeSourceCount) are already in scope with no ctx needed. If
|
|
481
|
+
// the formula ever changes, it must change in BOTH places (see canonical.ts's
|
|
482
|
+
// header for the same write/read-side duplication convention).
|
|
483
|
+
const atomsAreHubs = Math.max(
|
|
484
|
+
1,
|
|
485
|
+
Math.ceil((this.store.edgeSourceCount() * W) / 256),
|
|
486
|
+
) > Math.ceil(Math.sqrt(Math.max(2, this.store.edgeSourceCount())));
|
|
456
487
|
const nodeBytes = (n: number) => this.store.bytesPrefix(n, ALL);
|
|
457
488
|
// Content-addressed probes over the store's hash-cons maps — the same keys
|
|
458
489
|
// training filled. No byte-by-byte trie walk.
|
|
@@ -550,6 +581,7 @@ export class GraphSearch {
|
|
|
550
581
|
cover: true,
|
|
551
582
|
rec: true,
|
|
552
583
|
node: u.node,
|
|
584
|
+
computed: true,
|
|
553
585
|
},
|
|
554
586
|
cost: STEP,
|
|
555
587
|
};
|
|
@@ -588,6 +620,8 @@ export class GraphSearch {
|
|
|
588
620
|
return this.outRules(it, {
|
|
589
621
|
W,
|
|
590
622
|
splits,
|
|
623
|
+
starts,
|
|
624
|
+
atomsAreHubs,
|
|
591
625
|
coversDone,
|
|
592
626
|
outsByStart,
|
|
593
627
|
outsByEnd,
|
|
@@ -949,6 +983,8 @@ export class GraphSearch {
|
|
|
949
983
|
ctx: {
|
|
950
984
|
W: number;
|
|
951
985
|
splits: ReadonlySet<number>;
|
|
986
|
+
starts: ReadonlySet<number>;
|
|
987
|
+
atomsAreHubs: boolean;
|
|
952
988
|
coversDone: Set<number>;
|
|
953
989
|
outsByStart: Map<number, OutItem[]>;
|
|
954
990
|
outsByEnd: Map<number, OutItem[]>;
|
|
@@ -1095,12 +1131,30 @@ export class GraphSearch {
|
|
|
1095
1131
|
r: OutItem,
|
|
1096
1132
|
ctx: {
|
|
1097
1133
|
W: number;
|
|
1134
|
+
starts: ReadonlySet<number>;
|
|
1135
|
+
atomsAreHubs: boolean;
|
|
1098
1136
|
findLeafU: (b: Uint8Array) => number | undefined;
|
|
1099
1137
|
findBranchU: (k: number[]) => number | undefined;
|
|
1100
1138
|
},
|
|
1101
1139
|
): Iterable<Rule<GItem>> {
|
|
1102
1140
|
const bytes = concat2(l.bytes, r.bytes);
|
|
1103
|
-
|
|
1141
|
+
// A PURE leaf-leaf fuse (neither side already a recognised completion)
|
|
1142
|
+
// is opportunistic cross-leaf recovery exactly like recognition.ts's own
|
|
1143
|
+
// canonical chain — findLeaf/findBranch here have no idea WHY these two
|
|
1144
|
+
// leaves are adjacent, only that their concatenation happens to spell a
|
|
1145
|
+
// trained form ("hi" recovered from "W[hi]ch"). The same corpus-scale
|
|
1146
|
+
// caution recognition.ts's `boundary` gate applies: trust it fully when
|
|
1147
|
+
// `l.i` is a position the query's OWN fold chose as a boundary (real
|
|
1148
|
+
// structural evidence); past the scale where atoms themselves stop
|
|
1149
|
+
// discriminating, an interior offset's opportunistic match is noise, not
|
|
1150
|
+
// a genuine cross-leaf recovery. A completion-involved fuse (l.rec ||
|
|
1151
|
+
// r.rec) is a different, legitimate case — a rewrite growing into its
|
|
1152
|
+
// neighbour — and is exempt, same as recognition.ts's rec-derived sites.
|
|
1153
|
+
const trusted = l.rec || r.rec || ctx.starts.has(l.i) ||
|
|
1154
|
+
!ctx.atomsAreHubs;
|
|
1155
|
+
let node = (trusted && bytes.length <= ctx.W)
|
|
1156
|
+
? ctx.findLeafU(bytes)
|
|
1157
|
+
: undefined;
|
|
1104
1158
|
// Whether this pair ACTUALLY forms a 2-child branch — the hard evidence
|
|
1105
1159
|
// that the fused bytes are a learned form worth keeping alive. Derived
|
|
1106
1160
|
// from the same findBranchU probe that sets `node`; when false, the pair
|
|
@@ -1108,7 +1162,10 @@ export class GraphSearch {
|
|
|
1108
1162
|
// node cannot contribute to any further fusion (findBranch needs two
|
|
1109
1163
|
// nodes, resolve needs a completion, and findLeaf already had its chance).
|
|
1110
1164
|
let pairFormsBranch = false;
|
|
1111
|
-
if (
|
|
1165
|
+
if (
|
|
1166
|
+
trusted && node === undefined && l.node !== undefined &&
|
|
1167
|
+
r.node !== undefined
|
|
1168
|
+
) {
|
|
1112
1169
|
node = ctx.findBranchU([l.node, r.node]);
|
|
1113
1170
|
pairFormsBranch = node !== undefined;
|
|
1114
1171
|
}
|
package/src/mind/match.ts
CHANGED
|
@@ -325,18 +325,32 @@ export async function haloSiblings(
|
|
|
325
325
|
* strength, not a pick. Returns the direct halo cosine, or failing that the
|
|
326
326
|
* highest mutual-halo-sibling min-score (second-order analogy), or failing
|
|
327
327
|
* that the SHARED-FRAME strength (below) — the gate CAST's comparison
|
|
328
|
-
* schema validates genuine analogs with (bar: significanceBar).
|
|
328
|
+
* schema validates genuine analogs with (bar: significanceBar).
|
|
329
|
+
*
|
|
330
|
+
* The result names its TIER alongside the score: `halo: true` means the
|
|
331
|
+
* score cleared a significanceBar-gated HALO tier (direct company cosine
|
|
332
|
+
* or mutual-sibling) — genuine distributional evidence; `halo: false`
|
|
333
|
+
* means only the structural shared-frame fallback matched, a coverage
|
|
334
|
+
* fraction with no bar of its own. CAST's comparison gate treats the two
|
|
335
|
+
* differently (see cast.ts): halo evidence stands alone, frame evidence
|
|
336
|
+
* needs the query to have named the analog or the climb root to be
|
|
337
|
+
* trusted. */
|
|
338
|
+
export interface AnalogyEvidence {
|
|
339
|
+
score: number;
|
|
340
|
+
halo: boolean;
|
|
341
|
+
}
|
|
342
|
+
|
|
329
343
|
export async function analogyStrength(
|
|
330
344
|
ctx: MindContext,
|
|
331
345
|
a: number,
|
|
332
346
|
b: number,
|
|
333
|
-
): Promise<
|
|
347
|
+
): Promise<AnalogyEvidence> {
|
|
334
348
|
const ha = ctx.store.halo(a);
|
|
335
349
|
const hb = ctx.store.halo(b);
|
|
336
350
|
if (ha && hb) {
|
|
337
351
|
const bar = significanceBar(ctx.store.D);
|
|
338
352
|
const direct = cosine(ha, hb);
|
|
339
|
-
if (direct >= bar) return direct;
|
|
353
|
+
if (direct >= bar) return { score: direct, halo: true };
|
|
340
354
|
const sibsA = await haloSiblings(ctx, a, ha, bar);
|
|
341
355
|
const sibsB = await haloSiblings(ctx, b, hb, bar);
|
|
342
356
|
let best = 0;
|
|
@@ -347,9 +361,9 @@ export async function analogyStrength(
|
|
|
347
361
|
best = Math.max(best, Math.min(x.score, y.score));
|
|
348
362
|
}
|
|
349
363
|
}
|
|
350
|
-
if (best > 0) return best;
|
|
364
|
+
if (best > 0) return { score: best, halo: true };
|
|
351
365
|
}
|
|
352
|
-
return sharedFrameStrength(ctx, a, b);
|
|
366
|
+
return { score: sharedFrameStrength(ctx, a, b), halo: false };
|
|
353
367
|
}
|
|
354
368
|
|
|
355
369
|
/** The STRUCTURAL analogy tier: two nodes are analogs when their byte
|
|
@@ -16,7 +16,14 @@ import type { PipelineMechanism } from "../pipeline-mechanism.js";
|
|
|
16
16
|
export function aluToMechanism(alu: Alu): PipelineMechanism {
|
|
17
17
|
return {
|
|
18
18
|
name: "alu",
|
|
19
|
-
|
|
19
|
+
// Not a cover derivation: cover.ts composes an answer by walking
|
|
20
|
+
// recognised query STRUCTURE; the ALU evaluates a recognised expression
|
|
21
|
+
// to its authoritative result and hands the bytes back untouched. It
|
|
22
|
+
// shares cover's near-zero floor (computation always wins, masked into
|
|
23
|
+
// cover's own search — see mechanisms/cover.ts), but the candidate this
|
|
24
|
+
// produces is not one of cover's derivations, so it carries its own
|
|
25
|
+
// honest label, the same way extract/cast/recall each carry theirs.
|
|
26
|
+
provenance: "alu",
|
|
20
27
|
parse: (query) => alu.parse(query),
|
|
21
28
|
async floor(_ctx, _query, pre, _worthRunning) {
|
|
22
29
|
return pre.computed.length > 0 ? 0 : null;
|