@hviana/sema 0.6.0 → 0.7.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.
Files changed (42) hide show
  1. package/.github/workflows/release.yml +80 -0
  2. package/AGENTS.md +53 -9
  3. package/HOW_IT_WORKS.md +17 -16
  4. package/dist/src/meter.d.ts +14 -4
  5. package/dist/src/meter.js +27 -3
  6. package/dist/src/mind/attention.js +22 -20
  7. package/dist/src/mind/graph-search.d.ts +43 -9
  8. package/dist/src/mind/graph-search.js +82 -15
  9. package/dist/src/mind/junction.d.ts +13 -0
  10. package/dist/src/mind/junction.js +26 -1
  11. package/dist/src/mind/mechanisms/cover.js +23 -2
  12. package/dist/src/mind/mechanisms/prefix-completion.d.ts +2 -1
  13. package/dist/src/mind/mechanisms/prefix-completion.js +40 -20
  14. package/dist/src/mind/mechanisms/recall.js +8 -4
  15. package/dist/src/mind/pipeline-mechanism.d.ts +0 -24
  16. package/dist/src/mind/pipeline-mechanism.js +13 -36
  17. package/dist/src/mind/pipeline.d.ts +24 -0
  18. package/dist/src/mind/pipeline.js +71 -5
  19. package/dist/src/mind/recognition.d.ts +15 -1
  20. package/dist/src/mind/recognition.js +15 -1
  21. package/dist/src/mind/resonance.js +54 -12
  22. package/dist/src/store.js +22 -1
  23. package/jsr.json +1 -1
  24. package/package.json +7 -2
  25. package/src/meter.ts +27 -4
  26. package/src/mind/attention.ts +22 -19
  27. package/src/mind/graph-search.ts +93 -16
  28. package/src/mind/junction.ts +25 -1
  29. package/src/mind/mechanisms/cover.ts +23 -4
  30. package/src/mind/mechanisms/prefix-completion.ts +40 -20
  31. package/src/mind/mechanisms/recall.ts +8 -4
  32. package/src/mind/pipeline-mechanism.ts +13 -42
  33. package/src/mind/pipeline.ts +106 -5
  34. package/src/mind/recognition.ts +19 -2
  35. package/src/mind/resonance.ts +84 -49
  36. package/src/store.ts +21 -1
  37. package/test/89-completion-recursion.test.mjs +230 -0
  38. package/test/90-connector-read-cap.test.mjs +130 -0
  39. package/test/91-branch-bytes-cache.test.mjs +152 -0
  40. package/test/93-regime-prediction.test.mjs +148 -0
  41. package/test/94-cross-region-budget.test.mjs +67 -0
  42. package/test/95-wide-resonance-removed.test.mjs +109 -0
@@ -0,0 +1,67 @@
1
+ // 94-cross-region-budget.test.mjs — the cross-region junction ladder shares ONE
2
+ // k·W allowance per evidence tier once atoms are hubs, instead of letting each
3
+ // candidate pair spend its own √N·W drift budget (attention.ts crossRegionVotes,
4
+ // §2.17's derived gate = traverse.atomIsHub).
5
+ //
6
+ // This is a PERFORMANCE regression test, not a behaviour test: the shared
7
+ // budget is byte-identical at every scale — a pair whose container is not
8
+ // reached within the allowance falls through to the resonance tier exactly as a
9
+ // per-pair walk that exhausted its own budget would — so the only observable is
10
+ // the meter's junctionPops counter. A ~4.3k-fact fixture is NOT optional:
11
+ // atomIsHub is false in every small-store suite, so a conventional fixture
12
+ // would pass while the per-pair drift (measured: 160k junction pops, 31% of
13
+ // think) is fully present. The atomIsHub assertion below fails loudly if the
14
+ // crossover ever moves, so this suite can never silently stop covering the
15
+ // branch it exists for.
16
+
17
+ import { test } from "node:test";
18
+ import assert from "node:assert/strict";
19
+ import { Mind } from "../dist/src/index.js";
20
+ import { SQliteStore } from "../dist/src/store-sqlite.js";
21
+ import { atomIsHub, corpusN } from "../dist/src/mind/traverse.js";
22
+
23
+ test("crossRegion shares one k·W allowance per tier once atoms are hubs", async () => {
24
+ const m = new Mind({
25
+ seed: 7,
26
+ store: new SQliteStore({ path: ":memory:" }),
27
+ profile: true,
28
+ });
29
+
30
+ // Common windows, each in ≤ √N contexts so the hub guard does NOT abstain —
31
+ // a non-hub cone is exactly the drift the shared budget must bound. Three
32
+ // such windows ("aaaa", "bbbb", "cccc") that never co-occur give the query
33
+ // below three strong regions and three pairs, every one of whose junction
34
+ // walks drifts through both windows' cones and finds no container.
35
+ const per = 60;
36
+ const corpus = [];
37
+ for (const w of ["aaaa", "bbbb", "cccc"]) {
38
+ for (let i = 0; i < per; i++) corpus.push([`${w} ${i}`, `a ${w} ${i}`]);
39
+ }
40
+ // Filler edge sources push N past atomIsHub (N > ~4096 at maxGroup=4).
41
+ for (let i = 0; i < 4300; i++) corpus.push([`filler-${i}`, `f${i}`]);
42
+ await m.ingest(corpus);
43
+
44
+ const N = corpusN(m);
45
+ assert.ok(
46
+ atomIsHub(m, N),
47
+ `fixture must cross atomIsHub (N=${N}); the shared budget is scale-gated ` +
48
+ `and this suite would otherwise assert nothing`,
49
+ );
50
+
51
+ await m.respondText("aaaa bbbb cccc");
52
+
53
+ const c = m.lastCost;
54
+ const crossPops = c.phases["climb.crossRegion"]?.counters.junctionPops ?? 0;
55
+ const k = m.cfg.recallQueryK * 2; // pre.k — the ladder's pair budget breadth
56
+ const W = m.space.maxGroup;
57
+
58
+ assert.ok(crossPops > 0, "the query must actually run cross-region walks");
59
+ assert.ok(
60
+ crossPops <= 2 * k * W,
61
+ `crossRegion junction pops ${crossPops} must stay within the shared ` +
62
+ `2·k·W = ${2 * k * W} allowance (exact + synonym tiers), not the ` +
63
+ `per-pair √N·W drift`,
64
+ );
65
+
66
+ await m.store.close();
67
+ });
@@ -0,0 +1,109 @@
1
+ // 95-wide-resonance-removed.test.mjs — the substitution bridge and prefix
2
+ // completion must propose from BOUNDED sources, never from the exhaustive-√N
3
+ // ANN scan that `Precomputed.wideResonance()` used to run (removed; see
4
+ // pipeline-mechanism.ts's REMOVED note).
5
+ //
6
+ // This is a PERFORMANCE regression test, not a behaviour test: the wide list
7
+ // was a PROPOSAL source whose consumers byte-verify every candidate (§2.3), so
8
+ // removing it is byte-identical wherever the bounded sources supply the same
9
+ // candidate set — and the meter's phase map is the only observable that says
10
+ // whether the exhaustive machinery still exists. Red-on-revert: re-adding
11
+ // wideResonance re-creates the `wideResonance` phase (and, when the query's
12
+ // top hit clears conceptThreshold, a full-index ANN scan inside it), so the
13
+ // phase-absence assertion below fails.
14
+
15
+ import { test } from "node:test";
16
+ import assert from "node:assert/strict";
17
+ import { Mind } from "../dist/src/index.js";
18
+ import { SQliteStore } from "../dist/src/store-sqlite.js";
19
+
20
+ const dec = (b) => new TextDecoder().decode(b).replace(/\0+$/, "");
21
+
22
+ // The test/49 resonance-proposed corpus: the query "what is the capital of
23
+ // france" resonates STRAIGHT to the trained "What is the capital of France?"
24
+ // (nearest whole-query hit, so its top hit clears conceptThreshold — the exact
25
+ // condition that made the old wideResonance go exhaustive) yet falls below the
26
+ // reach bar, so recall refuses and the bridge runs to recover the fact.
27
+ const CORPUS = [
28
+ ["What is the capital of France?", "The capital of France is Paris."],
29
+ ["What is the capital of Spain?", "The capital of Spain is Madrid."],
30
+ ["What is the capital of Italy?", "The capital of Italy is Rome."],
31
+ // Lowercase mid-sentence occurrences attest the case-folded windows the
32
+ // substitution's corroboration gate requires.
33
+ ["He wrote of france and of spain.", "Then he flew home to italy."],
34
+ ["She spoke of france in her diary.", "Her diary told of france."],
35
+ ];
36
+
37
+ test("the bridge's refusal path never descends the exhaustive-√N ANN scan", async () => {
38
+ const m = new Mind({
39
+ seed: 7,
40
+ store: new SQliteStore({ path: ":memory:" }),
41
+ profile: true,
42
+ });
43
+ await m.ingest(CORPUS);
44
+
45
+ const r = await m.respond("what is the capital of france");
46
+ assert.ok(
47
+ dec(r.bytes).includes("Paris"),
48
+ `the bridge must still ground the fact through its bounded proposals, got ${
49
+ JSON.stringify(dec(r.bytes))
50
+ }`,
51
+ );
52
+
53
+ const c = m.lastCost;
54
+ // The fixture actually ran the bridge — without this, a silently-skipped
55
+ // fixture would pass the phase-absence assertion while asserting nothing.
56
+ assert.ok(
57
+ c.phases["substitutionBridge"],
58
+ "the fixture must run the substitution bridge",
59
+ );
60
+ // The exhaustive-√N phase is gone. Its removal is the whole point: the
61
+ // bridge's proposal source is the response's ONE top-k read (memoized), and
62
+ // every proposal is byte-verified downstream, so the full-index scan bought
63
+ // recall at O(index) cost for an O(k) need.
64
+ assert.equal(
65
+ c.phases["wideResonance"],
66
+ undefined,
67
+ "wideResonance (the exhaustive √N scan) must be removed from the response",
68
+ );
69
+ // The bridge phase itself accrues no content-index ANN reads: proposals come
70
+ // from the memoized `resonance()`, never a fresh exhaustive descend.
71
+ const bridgeAnn = c.phases["substitutionBridge"].counters.annVectorReads ?? 0;
72
+ assert.equal(
73
+ bridgeAnn,
74
+ 0,
75
+ "the substitution bridge must not descend the content ANN on its own",
76
+ );
77
+
78
+ await m.store.close();
79
+ });
80
+
81
+ test("prefix completion proposes from the write-side window index, not the ANN", async () => {
82
+ const m = new Mind({
83
+ seed: 7,
84
+ store: new SQliteStore({ path: ":memory:" }),
85
+ profile: true,
86
+ });
87
+ await m.ingest(CORPUS);
88
+
89
+ // A strict byte-prefix of the trained answer form. Its gist cannot rank its
90
+ // own continuation (cos falls below reachThreshold), so the content-addressed
91
+ // window walk is the correct proposal source — and the one prefix-completion
92
+ // now tries FIRST.
93
+ const r = await m.respond("The capital of France is");
94
+ assert.ok(
95
+ dec(r.bytes).includes("Paris"),
96
+ `expected the trained form through the content-addressed prefix supply, got ${
97
+ JSON.stringify(dec(r.bytes))
98
+ }`,
99
+ );
100
+
101
+ const c = m.lastCost;
102
+ assert.equal(
103
+ c.phases["wideResonance"],
104
+ undefined,
105
+ "wideResonance (the exhaustive √N scan) must be removed from the response",
106
+ );
107
+
108
+ await m.store.close();
109
+ });