@hviana/sema 0.8.9 → 0.9.1

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 (111) hide show
  1. package/AGENTS.md +7 -7
  2. package/dist/src/alu/src/index.d.ts +1 -1
  3. package/dist/src/alu/src/index.js +1 -1
  4. package/dist/src/alu/src/parser.js +2 -6
  5. package/dist/src/alu/src/resonance.d.ts +13 -0
  6. package/dist/src/alu/src/resonance.js +41 -0
  7. package/dist/src/alu/test/alu.test.js +39 -0
  8. package/dist/src/bytes.d.ts +6 -2
  9. package/dist/src/bytes.js +10 -4
  10. package/dist/src/canon.js +44 -0
  11. package/dist/src/geometry.d.ts +19 -1
  12. package/dist/src/geometry.js +125 -141
  13. package/dist/src/meter.d.ts +27 -0
  14. package/dist/src/meter.js +28 -1
  15. package/dist/src/mind/articulation.js +14 -1
  16. package/dist/src/mind/attention.d.ts +12 -0
  17. package/dist/src/mind/attention.js +44 -16
  18. package/dist/src/mind/bridge.js +3 -3
  19. package/dist/src/mind/derivation.d.ts +40 -0
  20. package/dist/src/mind/derivation.js +34 -0
  21. package/dist/src/mind/graph-search.d.ts +89 -15
  22. package/dist/src/mind/graph-search.js +345 -174
  23. package/dist/src/mind/learning.js +1 -1
  24. package/dist/src/mind/mechanisms/cover.d.ts +19 -3
  25. package/dist/src/mind/mechanisms/cover.js +101 -58
  26. package/dist/src/mind/mechanisms/recall.js +0 -1
  27. package/dist/src/mind/mind.js +2 -2
  28. package/dist/src/mind/pipeline.d.ts +5 -1
  29. package/dist/src/mind/pipeline.js +175 -87
  30. package/dist/src/mind/primitives.d.ts +25 -5
  31. package/dist/src/mind/primitives.js +107 -44
  32. package/dist/src/mind/reasoning.d.ts +18 -4
  33. package/dist/src/mind/reasoning.js +445 -321
  34. package/dist/src/mind/recognition.js +55 -73
  35. package/dist/src/mind/resonance.js +1 -11
  36. package/dist/src/mind/traverse.d.ts +3 -3
  37. package/dist/src/mind/traverse.js +3 -3
  38. package/dist/src/mind/types.d.ts +7 -1
  39. package/dist/src/store-sqlite.d.ts +25 -0
  40. package/dist/src/store-sqlite.js +89 -1
  41. package/dist/src/store.d.ts +48 -4
  42. package/dist/src/store.js +86 -6
  43. package/docs/INDEX.md +18 -18
  44. package/docs/INVARIANTS.md +16 -16
  45. package/docs/architecture/bounded-reads.md +1 -1
  46. package/docs/architecture/caches.md +5 -4
  47. package/docs/architecture/closure.md +45 -5
  48. package/docs/architecture/cost-model.md +16 -0
  49. package/docs/architecture/factored-machinery.md +14 -13
  50. package/docs/architecture/fold-contract.md +51 -1
  51. package/docs/architecture/mechanism-market.md +21 -0
  52. package/docs/architecture/memoization.md +3 -3
  53. package/docs/architecture/meter.md +2 -1
  54. package/docs/architecture/saturation.md +12 -0
  55. package/docs/architecture/store.md +25 -2
  56. package/docs/failures/tempting-but-wrong.md +13 -2
  57. package/docs/harness/gates.md +12 -10
  58. package/docs/mechanisms/cover.md +23 -6
  59. package/jsr.json +1 -1
  60. package/package.json +1 -1
  61. package/src/alu/README.md +10 -2
  62. package/src/alu/src/index.ts +1 -0
  63. package/src/alu/src/parser.ts +6 -6
  64. package/src/alu/src/resonance.ts +42 -0
  65. package/src/alu/test/alu.test.ts +40 -0
  66. package/src/bytes.ts +13 -3
  67. package/src/canon.ts +40 -0
  68. package/src/geometry.ts +183 -154
  69. package/src/meter.ts +28 -1
  70. package/src/mind/articulation.ts +14 -2
  71. package/src/mind/attention.ts +47 -25
  72. package/src/mind/bridge.ts +3 -3
  73. package/src/mind/derivation.ts +77 -0
  74. package/src/mind/graph-search.ts +449 -221
  75. package/src/mind/learning.ts +1 -7
  76. package/src/mind/match.ts +1 -2
  77. package/src/mind/mechanisms/cast.ts +1 -2
  78. package/src/mind/mechanisms/cover.ts +149 -84
  79. package/src/mind/mechanisms/extraction.ts +1 -2
  80. package/src/mind/mechanisms/prefix-completion.ts +1 -1
  81. package/src/mind/mechanisms/recall.ts +1 -3
  82. package/src/mind/mechanisms/reference.ts +1 -1
  83. package/src/mind/mind.ts +5 -30
  84. package/src/mind/pipeline.ts +206 -102
  85. package/src/mind/primitives.ts +119 -43
  86. package/src/mind/reasoning.ts +558 -413
  87. package/src/mind/recognition.ts +49 -65
  88. package/src/mind/resonance.ts +2 -16
  89. package/src/mind/trace.ts +1 -1
  90. package/src/mind/traverse.ts +3 -3
  91. package/src/mind/types.ts +9 -11
  92. package/src/store-sqlite.ts +92 -1
  93. package/src/store.ts +113 -7
  94. package/test/105-derive-through-reports-its-refusal.test.mjs +8 -5
  95. package/test/106-the-join-fires.test.mjs +21 -0
  96. package/test/111-the-cover-assembly-is-counted.test.mjs +8 -5
  97. package/test/128-the-leads-somewhere-pair-agrees.test.mjs +18 -12
  98. package/test/136-the-two-named-limits.test.mjs +3 -2
  99. package/test/137-the-law-lives-once-and-below.test.mjs +21 -0
  100. package/test/148-exact-shortcuts-agree.test.mjs +188 -0
  101. package/test/149-the-closure-engine.test.mjs +138 -0
  102. package/test/150-the-join-is-output-sensitive.test.mjs +66 -0
  103. package/test/151-the-cover-pays-for-what-it-reaches.test.mjs +142 -0
  104. package/test/152-the-read-side-names-as-the-write-side.test.mjs +146 -0
  105. package/test/153-a-cheaper-bound-is-looked-at-first.test.mjs +155 -0
  106. package/test/24-generalization.test.mjs +32 -0
  107. package/test/36-bloom.test.mjs +53 -0
  108. package/test/37-cluster-dispersion-fusion.test.mjs +75 -0
  109. package/test/48-recognise-turn-connective.test.mjs +3 -2
  110. package/test/55-cost-meter.test.mjs +4 -4
  111. package/test/90-connector-read-cap.test.mjs +7 -7
@@ -5,7 +5,7 @@
5
5
  import { addInto, normalize, zeros } from "../vec.js";
6
6
  import { bindSeat, companySignature, isChunk } from "../sema.js";
7
7
  import { changedNodes } from "./types.js";
8
- import { inputBytes, perceiveDeposit, resolve, } from "./primitives.js";
8
+ import { inputBytes, perceiveDeposit, resolve } from "./primitives.js";
9
9
  import { canonicalWindows, leafIdPrefix } from "./canonical.js";
10
10
  import { rItem, rNode } from "./trace.js";
11
11
  import { hubBound } from "./traverse.js";
@@ -1,6 +1,22 @@
1
1
  import type { MindContext } from "../types.js";
2
- import type { Site } from "../graph-search.js";
2
+ import type { ConceptLicence, ConnectorLicence, Site } from "../graph-search.js";
3
3
  import type { PipelineMechanism } from "../pipeline-mechanism.js";
4
- export declare function resolveConcepts(ctx: MindContext, sites: Site[]): Promise<Map<number, number>>;
5
- export declare function resolveConnectors(ctx: MindContext, sites: ReadonlyArray<Site>, query?: Uint8Array): Promise<Map<string, Uint8Array>>;
4
+ /** The concept hops the cover may take, OFFERED up front and looked up only
5
+ * when the search asks (see {@link Licence}): every recognised form with no
6
+ * continuation of its own may borrow a halo sibling's. */
7
+ export interface CoverConcepts extends ConceptLicence {
8
+ /** Look up the asked forms' concept targets not yet granted. */
9
+ grant(nodes: Iterable<number>): Promise<void>;
10
+ }
11
+ export declare function offerConcepts(ctx: MindContext, sites: ReadonlyArray<Site>): CoverConcepts;
12
+ /** The connectors the cover may splice, OFFERED up front and BRIDGED only when
13
+ * the search asks (see {@link ConnectorLicence}): every pair a learnt whole
14
+ * could run together — two touching sites, each side as itself or as its
15
+ * answer, in both orders — and, when three or more answers are recognised, the
16
+ * first answer to each later one (the N-ary whole). */
17
+ export interface CoverConnectors extends ConnectorLicence {
18
+ /** Bridge the asked pairs not yet granted. */
19
+ grant(keys: Iterable<string>): Promise<void>;
20
+ }
21
+ export declare function offerConnectors(ctx: MindContext, sites: ReadonlyArray<Site>, query?: Uint8Array): CoverConnectors;
6
22
  export declare const coverMechanism: PipelineMechanism;
@@ -16,31 +16,38 @@ import { liftAnswer, liftedScaffolding, segRestatesQuery } from "../types.js";
16
16
  import { decodeText } from "../rationale.js";
17
17
  import { insideAnsweredTurn, restates } from "../derivation.js";
18
18
  import { rItem, rNode, traceDerivation } from "../trace.js";
19
- // ── Concept / connector pre-resolution ──────────────────────────────────────
20
- export async function resolveConcepts(ctx, sites) {
21
- const target = new Map();
22
- const visited = new Set();
19
+ export function offerConcepts(ctx, sites) {
20
+ const offered = new Set();
23
21
  for (const { payload: n } of sites) {
24
- if (visited.has(n))
25
- continue;
26
- visited.add(n);
27
- if (ctx.store.hasNext(n))
28
- continue;
29
- const hop = await conceptHop(ctx, n);
30
- if (hop !== null)
31
- target.set(n, hop);
22
+ if (!offered.has(n) && !ctx.store.hasNext(n))
23
+ offered.add(n);
32
24
  }
33
- if (target.size > 0) {
34
- ctx.trace?.step("resolveConcepts", [...target.keys()].map((n) => rNode(ctx, n, "edgeless-form")), [...target.values()].map((h) => rNode(ctx, h, "concept-sibling")), "borrow a synonym's continuation edge for each edge-less form (a concept/halo hop)");
35
- }
36
- return target;
25
+ const granted = new Map();
26
+ return {
27
+ offered,
28
+ granted,
29
+ asked: new Set(),
30
+ async grant(nodes) {
31
+ const found = [];
32
+ for (const n of nodes) {
33
+ if (granted.has(n))
34
+ continue;
35
+ const hop = await conceptHop(ctx, n);
36
+ granted.set(n, hop);
37
+ if (hop !== null)
38
+ found.push([n, hop]);
39
+ }
40
+ if (found.length > 0) {
41
+ ctx.trace?.step("resolveConcepts", found.map(([n]) => rNode(ctx, n, "edgeless-form")), found.map(([, h]) => rNode(ctx, h, "concept-sibling")), "borrow a synonym's continuation edge for each edge-less form the search reached (a concept/halo hop)");
42
+ }
43
+ },
44
+ };
37
45
  }
38
- export async function resolveConnectors(ctx, sites, query) {
39
- const links = new Map();
46
+ export function offerConnectors(ctx, sites, query) {
40
47
  const answerOf = (n) => guidedFirst(ctx, n) ?? n;
41
48
  // A site's continuation already present elsewhere in the query is stale
42
49
  // transcript evidence: cover still needs the site for structural context,
43
- // but liftAnswer will trim that continuation as already answered. Building
50
+ // but liftAnswer will trim that continuation as already answered. Offering
44
51
  // pairwise/n-ary bridges for it can only create connectors that are later
45
52
  // discarded — a semantically neutral gate (it removes work whose product
46
53
  // liftAnswer throws away), and a cumulative (multi-turn) query is exactly
@@ -81,15 +88,7 @@ export async function resolveConnectors(ctx, sites, query) {
81
88
  return restates(query, bytes, 0);
82
89
  });
83
90
  });
84
- const bridgePair = async (l, r) => {
85
- if (l === r || links.has(l + "," + r))
86
- return;
87
- if (ctx.meter)
88
- ctx.meter.coverBridges++;
89
- const link = await bridge(ctx, read(ctx, l), read(ctx, r));
90
- if (link !== null)
91
- links.set(l + "," + r, link);
92
- };
91
+ const pairwise = new Set();
93
92
  for (let i = 0; i + 1 < ordered.length; i++) {
94
93
  if (ordered[i].end !== ordered[i + 1].start)
95
94
  continue;
@@ -97,8 +96,10 @@ export async function resolveConnectors(ctx, sites, query) {
97
96
  const rights = [ordered[i + 1].payload, answerOf(ordered[i + 1].payload)];
98
97
  for (const l of new Set(lefts)) {
99
98
  for (const r of new Set(rights)) {
100
- await bridgePair(l, r);
101
- await bridgePair(r, l);
99
+ if (l === r)
100
+ continue;
101
+ pairwise.add(l + "," + r);
102
+ pairwise.add(r + "," + l);
102
103
  }
103
104
  }
104
105
  }
@@ -111,37 +112,61 @@ export async function resolveConnectors(ctx, sites, query) {
111
112
  seenN.add(node);
112
113
  orderedNodes.push({ node, bytes: read(ctx, node) });
113
114
  }
115
+ const nary = new Map();
114
116
  if (orderedNodes.length >= 3) {
115
117
  const first = orderedNodes[0];
116
118
  const W = ctx.space.maxGroup;
117
119
  let middleBytes = 0; // Σ bytes of the answers BETWEEN first and m-th
118
120
  for (let m = 1; m < orderedNodes.length; m++) {
119
- const key = first.node + "," + orderedNodes[m].node;
120
- if (links.has(key)) {
121
- middleBytes += orderedNodes[m].bytes.length;
122
- continue;
123
- }
124
121
  // The N-ary interior legitimately holds every intermediate answer
125
122
  // plus one W-quantum of glue per joint — pass that allowance so the
126
- // bridge's phrase-scale cap admits the whole learnt run.
127
- const allowance = middleBytes + (m + 1) * W;
128
- if (ctx.meter) {
129
- ctx.meter.coverBridges++;
130
- ctx.meter.coverAllowanceBytes += allowance;
131
- }
132
- const interior = await bridge(ctx, first.bytes, orderedNodes[m].bytes, allowance);
133
- if (interior !== null)
134
- links.set(key, interior);
123
+ // bridge's phrase-scale cap admits the whole learnt run. Asked only
124
+ // when the pairwise bridge of the same key (if offered) found nothing.
125
+ nary.set(first.node + "," + orderedNodes[m].node, {
126
+ left: first.bytes,
127
+ right: orderedNodes[m].bytes,
128
+ allowance: middleBytes + (m + 1) * W,
129
+ });
135
130
  middleBytes += orderedNodes[m].bytes.length;
136
131
  }
137
132
  }
138
- if (links.size > 0) {
139
- ctx.trace?.step("resolveConnectors", ordered.map((s) => rItem(read(ctx, s.payload), "answer", s.payload)), [...links.entries()].map(([pair, bytes]) => ({
140
- text: `${pair}: "${decodeText(bytes)}"`,
141
- role: "connector",
142
- })), "the bytes the graph splices between adjacent answers (asked of the gist space)");
143
- }
144
- return links;
133
+ const granted = new Map();
134
+ return {
135
+ offered: new Set([...pairwise, ...nary.keys()]),
136
+ granted,
137
+ asked: new Set(),
138
+ async grant(keys) {
139
+ const found = [];
140
+ for (const key of keys) {
141
+ if (granted.has(key))
142
+ continue;
143
+ let link = null;
144
+ if (pairwise.has(key)) {
145
+ const comma = key.indexOf(",");
146
+ if (ctx.meter)
147
+ ctx.meter.coverBridges++;
148
+ link = await bridge(ctx, read(ctx, Number(key.slice(0, comma))), read(ctx, Number(key.slice(comma + 1))));
149
+ }
150
+ const whole = nary.get(key);
151
+ if (link === null && whole !== undefined) {
152
+ if (ctx.meter) {
153
+ ctx.meter.coverBridges++;
154
+ ctx.meter.coverAllowanceBytes += whole.allowance;
155
+ }
156
+ link = await bridge(ctx, whole.left, whole.right, whole.allowance);
157
+ }
158
+ granted.set(key, link);
159
+ if (link !== null)
160
+ found.push([key, link]);
161
+ }
162
+ if (found.length > 0) {
163
+ ctx.trace?.step("resolveConnectors", ordered.map((s) => rItem(read(ctx, s.payload), "answer", s.payload)), found.map(([pair, bytes]) => ({
164
+ text: `${pair}: "${decodeText(bytes)}"`,
165
+ role: "connector",
166
+ })), "the bytes the graph splices between adjacent answers the search reached (asked of the gist space)");
167
+ }
168
+ },
169
+ };
145
170
  }
146
171
  // ── Pipeline mechanism ──────────────────────────────────────────────────────
147
172
  export const coverMechanism = {
@@ -169,8 +194,8 @@ export const coverMechanism = {
169
194
  if (sites.length === 0 && computed.length === 0)
170
195
  return [];
171
196
  const connectors = ctx.meter
172
- ? await ctx.meter.time("cover.resolveConnectors", () => resolveConnectors(ctx, sites, query))
173
- : await resolveConnectors(ctx, sites, query);
197
+ ? ctx.meter.timeSync("cover.offerConnectors", () => offerConnectors(ctx, sites, query))
198
+ : offerConnectors(ctx, sites, query);
174
199
  let splits = rec.splits;
175
200
  if (computed.length > 0) {
176
201
  splits = new Set(rec.splits);
@@ -180,13 +205,11 @@ export const coverMechanism = {
180
205
  }
181
206
  }
182
207
  const concepts = ctx.meter
183
- ? await ctx.meter.time("cover.resolveConcepts", () => resolveConcepts(ctx, sites))
184
- : await resolveConcepts(ctx, sites);
208
+ ? ctx.meter.timeSync("cover.offerConcepts", () => offerConcepts(ctx, sites))
209
+ : offerConcepts(ctx, sites);
185
210
  const coverDeps = [
186
211
  ctx.trace?.lastIndex("recognise"),
187
212
  ctx.trace?.lastIndex("computeExtensions"),
188
- ctx.trace?.lastIndex("resolveConcepts"),
189
- ctx.trace?.lastIndex("resolveConnectors"),
190
213
  ].filter((x) => x !== undefined);
191
214
  // Convert ComputedSpan[] to ComputedResult[] for the graph search.
192
215
  const computedResults = computed.map((u) => ({
@@ -202,7 +225,27 @@ export const coverMechanism = {
202
225
  ])),
203
226
  ...computedResults.map((u) => rItem(u.bytes, "computed")),
204
227
  ], coverDeps.length ? coverDeps : undefined);
205
- const solved = ctx.search.cover(query.length, sites, concepts, rec.leaves, splits, undefined, connectors, computedResults, ctx.trace ? (steps) => traceDerivation(ctx, steps) : undefined);
228
+ // COVER, GRANT WHAT IT ASKED, COVER AGAIN — until a cover asks for nothing
229
+ // (see Licence in graph-search.ts). Only the final cover's derivations reach the
230
+ // rationale; a provisional one is superseded, not part of the answer.
231
+ let derivations = [];
232
+ let solved;
233
+ for (;;) {
234
+ derivations = [];
235
+ solved = ctx.search.cover(query.length, sites, concepts, rec.leaves, splits, undefined, connectors, computedResults, ctx.trace ? (steps) => derivations.push(steps) : undefined);
236
+ if (concepts.asked.size === 0 && connectors.asked.size === 0)
237
+ break;
238
+ const grant = async () => {
239
+ await concepts.grant([...concepts.asked]);
240
+ await connectors.grant([...connectors.asked]);
241
+ };
242
+ if (ctx.meter)
243
+ await ctx.meter.time("cover.grant", grant);
244
+ else
245
+ await grant();
246
+ }
247
+ for (const steps of derivations)
248
+ traceDerivation(ctx, steps);
206
249
  const segs = solved && solved.segs;
207
250
  tCover?.done(segs === null
208
251
  ? []
@@ -32,7 +32,6 @@ export async function recallByResonance(ctx, query, pre) {
32
32
  ...(complete ? { complete } : {}),
33
33
  };
34
34
  };
35
- const k = pre.k;
36
35
  const queryGist = pre.guide;
37
36
  // 0. Exact self-match — content-addressed, deterministic.
38
37
  const qId = pre.queryResolved;
@@ -11,14 +11,14 @@
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 { contentFoldIncremental, reachThreshold, } from "../geometry.js";
14
+ import { contentFoldIncremental, reachThreshold } from "../geometry.js";
15
15
  import { keyEnds } from "./canonical.js";
16
16
  import { BoundedMap } from "../store.js";
17
17
  import { SQliteStore } from "../store-sqlite.js";
18
18
  import { resolveConfig } from "../config.js";
19
19
  import { canonHash, textCanon, textEdgeTrim } from "../canon.js";
20
20
  import { bytesEqual, concat2 } from "../bytes.js";
21
- import { GraphSearch, } from "./graph-search.js";
21
+ import { GraphSearch } from "./graph-search.js";
22
22
  import { Alu } from "../alu/src/index.js";
23
23
  import { decodeText, Rationale, } from "./rationale.js";
24
24
  import { canonResolve as canonResolveImpl, gistOf, inputBytes, perceive as perceiveImpl, perceiveKey, resolve as resolveImpl, } from "./primitives.js";
@@ -1,6 +1,6 @@
1
1
  import type { MindContext } from "./types.js";
2
2
  import { type PipelineMechanism } from "./pipeline-mechanism.js";
3
- export { resolveConcepts, resolveConnectors } from "./mechanisms/cover.js";
3
+ export { offerConcepts, offerConnectors } from "./mechanisms/cover.js";
4
4
  export { aluToMechanism } from "./mechanisms/alu.js";
5
5
  export declare const defaultMechanisms: PipelineMechanism[];
6
6
  export type Provenance = "cast" | "join" | "cover" | "extract" | "reference" | "recall" | "recall-echo" | "prefix";
@@ -60,6 +60,10 @@ export interface RegimePredictionData {
60
60
  * CAST's floor) — the bar the incumbent must sit at or below for the
61
61
  * consensus climb to be skipped. */
62
62
  climbFloorGrade: number;
63
+ /** The lowest grade reached by a mechanism run AHEAD of a dearer one (see
64
+ * the grounding loop), when one ran and grounded: a bound below
65
+ * `climbFloorGrade` makes the regime retrieval whatever the incumbent. */
66
+ boundGrade?: number;
63
67
  }
64
68
  /** Think: a single lightest-derivation exploration of the Sema graph.
65
69
  *