@hviana/sema 0.2.8 → 0.2.9

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.
@@ -358,6 +358,14 @@ export interface StructuralResonanceProposal {
358
358
  leftSiblingId?: number;
359
359
  rightSiblingId?: number;
360
360
  }
361
+ /** A sibling gist cached in the shared, climb-wide memo alongside the
362
+ * COMPLETE stored byte length it was reconstructed from — the length is
363
+ * required to tell whether a cache hit is still valid under a probe whose
364
+ * `maxSiblingBytes` bound is smaller than the one that first cached it. */
365
+ interface CachedSiblingGist {
366
+ gist: Vec;
367
+ length: number;
368
+ }
361
369
  /** Build, bound and order every mandatory structural variant (§7-8): the
362
370
  * exact/exact composition is always kept; up to `ctx.cfg.haloQueryK`
363
371
  * synonym variants (single- and double-synonym combined, one shared
@@ -366,7 +374,7 @@ export interface StructuralResonanceProposal {
366
374
  * buildStructuralVariantSpecs}); a sibling's bytes are read and perceived
367
375
  * only for specs actually retained, and at most once per sibling id per
368
376
  * climb via `siblingGistMemo`. */
369
- export declare function buildStructuralVariants(ctx: MindContext, ra: Region, rb: Region, sides: JunctionSynonymSides, siblingGistMemo: Map<number, Vec>): {
377
+ export declare function buildStructuralVariants(ctx: MindContext, ra: Region, rb: Region, sides: JunctionSynonymSides, siblingGistMemo: Map<number, CachedSiblingGist>): {
370
378
  variants: StructuralVariant[];
371
379
  exactLeft: StructuralPart;
372
380
  exactRight: StructuralPart;
@@ -375,7 +383,7 @@ export declare function buildStructuralVariants(ctx: MindContext, ra: Region, rb
375
383
  * ANN-query each, merge proposals by candidate id, and validate the winner
376
384
  * through the SAME structural gates every other tier answers to (saturation,
377
385
  * roots, IDF, contrastive margin). Returns null when nothing survives. */
378
- export declare function structuralResonance(ctx: MindContext, query: Uint8Array, ra: Region, rb: Region, sides: JunctionSynonymSides, siblingGistMemo: Map<number, Vec>, k: number, N: number, reachMemo: Map<number, AncestorReach>,
386
+ export declare function structuralResonance(ctx: MindContext, query: Uint8Array, ra: Region, rb: Region, sides: JunctionSynonymSides, siblingGistMemo: Map<number, CachedSiblingGist>, k: number, N: number, reachMemo: Map<number, AncestorReach>,
379
387
  /** Each side's OWN individual climb roots (from voteRegions), when it cast
380
388
  * one — the self-evidence backstop structural-resonance needs and the
381
389
  * exact tier gets for free from literal byte containment (§11's whole
@@ -962,19 +962,24 @@ function buildStructuralVariantSpecs(sides) {
962
962
  /** A halo sibling's structural gist, bounded to `maxBytes` of stored content
963
963
  * and reused across the whole climb. `positiveMemo` (shared across every
964
964
  * probe in the climb, passed in by the caller) remembers only successfully
965
- * reconstructed complete gists a sibling rejected here for being too
966
- * large for THIS pair's phrase-scale bound may still be admissible for a
967
- * larger-spanning pair later, so a rejection is never memoized globally.
968
- * `localMemo` is scoped to one `buildStructuralVariants` call, where every
969
- * variant shares the same bound, so a `null` there is safe to reuse. */
965
+ * reconstructed complete gists together with their complete byte length
966
+ * a sibling rejected here for being too large for THIS pair's phrase-scale
967
+ * bound may still be admissible for a larger-spanning pair later, so a
968
+ * rejection is never memoized globally, and a sibling cached by a LARGER
969
+ * probe is only reused here when its length still fits THIS probe's
970
+ * (possibly smaller) bound — eligibility must never depend on which probe
971
+ * happened to cache the sibling first. `localMemo` is scoped to one
972
+ * `buildStructuralVariants` call, where every variant shares the same
973
+ * bound, so a `null` there is safe to reuse. */
970
974
  function loadBoundedSiblingGist(ctx, id, maxBytes, positiveMemo, localMemo) {
971
975
  if (localMemo.has(id)) {
972
976
  return localMemo.get(id) ?? null;
973
977
  }
974
978
  const cached = positiveMemo.get(id);
975
979
  if (cached !== undefined) {
976
- localMemo.set(id, cached);
977
- return cached;
980
+ const result = cached.length <= maxBytes ? cached.gist : null;
981
+ localMemo.set(id, result);
982
+ return result;
978
983
  }
979
984
  const length = ctx.store.contentLen(id, maxBytes + 1);
980
985
  if (length <= 0 || length > maxBytes) {
@@ -987,7 +992,7 @@ function loadBoundedSiblingGist(ctx, id, maxBytes, positiveMemo, localMemo) {
987
992
  return null;
988
993
  }
989
994
  const gist = gistOf(ctx, bytes);
990
- positiveMemo.set(id, gist);
995
+ positiveMemo.set(id, { gist, length });
991
996
  localMemo.set(id, gist);
992
997
  return gist;
993
998
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hviana/sema",
3
- "version": "0.2.8",
3
+ "version": "0.2.9",
4
4
  "description": "Sema: a non-parametric, instance-based reasoning system.",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",
@@ -1613,19 +1613,32 @@ function buildStructuralVariantSpecs(
1613
1613
  return specs;
1614
1614
  }
1615
1615
 
1616
+ /** A sibling gist cached in the shared, climb-wide memo alongside the
1617
+ * COMPLETE stored byte length it was reconstructed from — the length is
1618
+ * required to tell whether a cache hit is still valid under a probe whose
1619
+ * `maxSiblingBytes` bound is smaller than the one that first cached it. */
1620
+ interface CachedSiblingGist {
1621
+ gist: Vec;
1622
+ length: number;
1623
+ }
1624
+
1616
1625
  /** A halo sibling's structural gist, bounded to `maxBytes` of stored content
1617
1626
  * and reused across the whole climb. `positiveMemo` (shared across every
1618
1627
  * probe in the climb, passed in by the caller) remembers only successfully
1619
- * reconstructed complete gists a sibling rejected here for being too
1620
- * large for THIS pair's phrase-scale bound may still be admissible for a
1621
- * larger-spanning pair later, so a rejection is never memoized globally.
1622
- * `localMemo` is scoped to one `buildStructuralVariants` call, where every
1623
- * variant shares the same bound, so a `null` there is safe to reuse. */
1628
+ * reconstructed complete gists together with their complete byte length
1629
+ * a sibling rejected here for being too large for THIS pair's phrase-scale
1630
+ * bound may still be admissible for a larger-spanning pair later, so a
1631
+ * rejection is never memoized globally, and a sibling cached by a LARGER
1632
+ * probe is only reused here when its length still fits THIS probe's
1633
+ * (possibly smaller) bound — eligibility must never depend on which probe
1634
+ * happened to cache the sibling first. `localMemo` is scoped to one
1635
+ * `buildStructuralVariants` call, where every variant shares the same
1636
+ * bound, so a `null` there is safe to reuse. */
1624
1637
  function loadBoundedSiblingGist(
1625
1638
  ctx: MindContext,
1626
1639
  id: number,
1627
1640
  maxBytes: number,
1628
- positiveMemo: Map<number, Vec>,
1641
+ positiveMemo: Map<number, CachedSiblingGist>,
1629
1642
  localMemo: Map<number, Vec | null>,
1630
1643
  ): Vec | null {
1631
1644
  if (localMemo.has(id)) {
@@ -1634,8 +1647,9 @@ function loadBoundedSiblingGist(
1634
1647
 
1635
1648
  const cached = positiveMemo.get(id);
1636
1649
  if (cached !== undefined) {
1637
- localMemo.set(id, cached);
1638
- return cached;
1650
+ const result = cached.length <= maxBytes ? cached.gist : null;
1651
+ localMemo.set(id, result);
1652
+ return result;
1639
1653
  }
1640
1654
 
1641
1655
  const length = ctx.store.contentLen(id, maxBytes + 1);
@@ -1651,7 +1665,7 @@ function loadBoundedSiblingGist(
1651
1665
  }
1652
1666
 
1653
1667
  const gist = gistOf(ctx, bytes);
1654
- positiveMemo.set(id, gist);
1668
+ positiveMemo.set(id, { gist, length });
1655
1669
  localMemo.set(id, gist);
1656
1670
  return gist;
1657
1671
  }
@@ -1669,7 +1683,7 @@ export function buildStructuralVariants(
1669
1683
  ra: Region,
1670
1684
  rb: Region,
1671
1685
  sides: JunctionSynonymSides,
1672
- siblingGistMemo: Map<number, Vec>,
1686
+ siblingGistMemo: Map<number, CachedSiblingGist>,
1673
1687
  ): {
1674
1688
  variants: StructuralVariant[];
1675
1689
  exactLeft: StructuralPart;
@@ -1778,7 +1792,7 @@ export async function structuralResonance(
1778
1792
  ra: Region,
1779
1793
  rb: Region,
1780
1794
  sides: JunctionSynonymSides,
1781
- siblingGistMemo: Map<number, Vec>,
1795
+ siblingGistMemo: Map<number, CachedSiblingGist>,
1782
1796
  k: number,
1783
1797
  N: number,
1784
1798
  reachMemo: Map<number, AncestorReach>,
@@ -1977,7 +1991,7 @@ async function crossRegionVotes(
1977
1991
  // Shared across every cross-region probe in this climb: a sibling
1978
1992
  // successfully reconstructed while probing one pair must not be read and
1979
1993
  // perceived again while probing another pair in the same climb.
1980
- const siblingGistMemo = new Map<number, Vec>();
1994
+ const siblingGistMemo = new Map<number, CachedSiblingGist>();
1981
1995
  const votedSpans = new Set<string>();
1982
1996
  for (const rv of rvs.votes) votedSpans.add(`${rv.start},${rv.end}`);
1983
1997
  const seen = new Set<string>();