@hviana/sema 0.7.2 → 0.7.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.
Files changed (43) hide show
  1. package/AGENTS.md +95 -843
  2. package/README.md +11 -11
  3. package/dist/src/mind/mind.js +14 -0
  4. package/dist/src/store-sqlite.js +17 -0
  5. package/dist/src/store.d.ts +51 -4
  6. package/dist/src/store.js +81 -14
  7. package/docs/INDEX.md +71 -0
  8. package/docs/INVARIANTS.md +19 -0
  9. package/docs/architecture/bounded-reads.md +85 -0
  10. package/docs/architecture/caches.md +89 -0
  11. package/docs/architecture/commonality.md +45 -0
  12. package/docs/architecture/cost-model.md +71 -0
  13. package/docs/architecture/determinism.md +73 -0
  14. package/docs/architecture/exact-vs-approximate.md +47 -0
  15. package/docs/architecture/factored-machinery.md +28 -0
  16. package/docs/architecture/fold-contract.md +87 -0
  17. package/docs/architecture/halo-sketch.md +99 -0
  18. package/docs/architecture/match-project.md +62 -0
  19. package/docs/architecture/mechanism-market.md +95 -0
  20. package/docs/architecture/memoization.md +96 -0
  21. package/docs/architecture/meter.md +55 -0
  22. package/docs/architecture/saturation.md +92 -0
  23. package/docs/architecture/store.md +79 -0
  24. package/docs/architecture/thresholds.md +79 -0
  25. package/docs/failures/tempting-but-wrong.md +144 -0
  26. package/docs/harness/gates.md +56 -0
  27. package/docs/mechanisms/alu.md +75 -0
  28. package/docs/mechanisms/cast.md +75 -0
  29. package/docs/mechanisms/confluence.md +36 -0
  30. package/docs/mechanisms/cover.md +54 -0
  31. package/docs/mechanisms/extraction.md +53 -0
  32. package/docs/mechanisms/prefix-completion.md +54 -0
  33. package/docs/mechanisms/recall.md +69 -0
  34. package/docs/mechanisms/reference.md +58 -0
  35. package/jsr.json +1 -1
  36. package/package.json +1 -1
  37. package/src/mind/mind.ts +14 -0
  38. package/src/store-sqlite.ts +19 -0
  39. package/src/store.ts +92 -16
  40. package/test/89-completion-recursion.test.mjs +30 -10
  41. package/test/96-bytes-walk-termination.test.mjs +115 -0
  42. package/test/97-store-seed.test.mjs +105 -0
  43. package/HOW_IT_WORKS.md +0 -5836
@@ -0,0 +1,75 @@
1
+ # ALU — Computation as an Extension
2
+
3
+ The ALU is a self-contained sublibrary (`src/alu/`) that knows nothing about the
4
+ pipeline. `aluToMechanism` (`src/mind/mechanisms/alu.ts`) wraps it as an
5
+ ordinary `PipelineMechanism`; cover owns masking.
6
+
7
+ ## How it joins search
8
+
9
+ Every mechanism may implement `parse(query) → ComputedSpan[]` (`{i,j,bytes}`).
10
+ `think` (`src/mind/pipeline.ts`) collects all parses before the grounding loop.
11
+ `pre.computed` holds the authoritative spans. Each becomes a candidate at `STEP`
12
+ (1) with `accounted: [[i,j]]`:
13
+
14
+ ```ts
15
+ // src/mind/mechanisms/alu.ts — run()
16
+ { bytes: u.bytes, accounted: [[u.i, u.j]], moves: STEP }
17
+ ```
18
+
19
+ `floor` returns `0` when `pre.computed` is non-empty, else `null`.
20
+
21
+ ## Masking — computation always wins
22
+
23
+ `cover` (`src/mind/mechanisms/cover.ts`) masks any recognised site whose bytes
24
+ overlap a computed span. A learned `2+2 → 5` is dropped; the computed `4` is the
25
+ sole cover there. Masking is the only precedence — a computed span and a learned
26
+ edge both cost `STEP`.
27
+
28
+ A computed span and an unrelated rewrite still compose (`"ice 2+2" → "cold 4"`).
29
+
30
+ ## Registry — `derive` composes ops
31
+
32
+ `OperationRegistry` (`src/alu/src/operation.ts`) holds every op indexed by
33
+ canonical name and surface form. `prim` registers irreducible roots; `derive`
34
+ registers a rewrite over existing ops via `ctx.apply`:
35
+
36
+ ```ts
37
+ registry.derive(
38
+ "hypot",
39
+ 2,
40
+ ["hypot"],
41
+ (args, ctx) =>
42
+ ctx.apply("sqrt", [ctx.apply("add", [
43
+ ctx.apply("multiply", [args[0], args[0]]),
44
+ ctx.apply("multiply", [args[1], args[1]]),
45
+ ])]),
46
+ );
47
+ ```
48
+
49
+ `derive(name, arity, surfaceForms, body)` — name it, list forms, write the body
50
+ in terms of existing ops. No kernel or graph-search edit.
51
+
52
+ ## Broadcast — scalar ops over n-d
53
+
54
+ One place (`OperationRegistry.context`): a non-structural op applied to `nd`
55
+ lists lifts element-wise, recursing into nested `nd`. Structural ops (`nd`,
56
+ `length`, `at`, `reduce`, …) are broadcast-exempt — they consume the list whole.
57
+ So `add([1,2,3], 10) = [11,12,13]` without matrix code.
58
+
59
+ ## Resonance — meaning pre-resolved
60
+
61
+ Operand meanings are pre-resolved before the synchronous kernel runs
62
+ (`AluResonance` / `prefetchResonance` in `src/alu/src/resonance.ts`):
63
+ `recogniseOp` maps a span to its operation concept, `opposite` finds the
64
+ resonant inverse of a symbol for the polymorphic `inverse`. Literal surface
65
+ forms need no host; meaning-based paths do.
66
+
67
+ ## Provenance
68
+
69
+ Grounded ALU answers carry `alu`; `computeExtensions`/`evalComputation` trace
70
+ the expression and result.
71
+
72
+ ## Pins
73
+
74
+ - `test/18-alu.test.mjs` — arithmetic, masking, and resonance-gated ops
75
+ - `test/19-nd.test.mjs` — `nd` lists, broadcast, and higher-order ops
@@ -0,0 +1,75 @@
1
+ # CAST — Counterfactual Transfer via Weave
2
+
3
+ Counterfactual transfer over the query's **weave**: when byte-string evidence
4
+ from multiple independently-learnt structures aligns to genuinely different
5
+ query spans, CAST transfers structure between them (substitution, redirection,
6
+ analogical comparison). One `alignGraded` weave, multiple schemas; each firing
7
+ schema yields its own candidate and `think`'s single weight comparison picks.
8
+
9
+ ## Matcher
10
+
11
+ `alignGraded` over the current query bytes: literal W-gram runs first, then
12
+ halo-matched `pre.rec.sites`. The product is `pre.weave()` — `points[]` (each
13
+ with graded `runs[]`) and a per-query-byte `depth[]` (how many structures cover
14
+ that byte). CAST's single-vs-multi test is measured from those runs: a second
15
+ point must add ≥ one perception quantum of coverage the widest point does not.
16
+
17
+ ## Gate — weave-local discriminative frame
18
+
19
+ Two derived components, both from the weave itself (no tuned threshold):
20
+
21
+ 1. **MIN_WEAVE = 2** — CAST needs ≥ 2 points to form a weave. Frame requires
22
+ _more_ than the minimum: `depth[i] > MIN_WEAVE`, i.e. ≥ 3 structures agree on
23
+ the byte. With only the minimum pair no byte is frame.
24
+
25
+ 2. **Half-dominance** — `dominates(n, total)` (> half scaffolding no longer
26
+ discriminates). Per byte:
27
+ `frame(i) ⇔ depth[i] > MIN_WEAVE ∧ dominates(depth[i], aligned)`. Per run:
28
+ `usable(r) ⇔ ¬dominates(framedCount(qs,qe), runLen)`.
29
+
30
+ `depth` counts **distinct structures**, not accumulated weight — a byte covered
31
+ by the same structure twice still has depth 1. Counting weight instead lets
32
+ shared frame (" describe it", "the importance of") survive as content and makes
33
+ substitution fire on reordered single-fact queries. The split is 29/42 vs 6/42
34
+ when wrong.
35
+
36
+ This frame gate is **weave-local** ("what the aligned structures share among
37
+ themselves"), not corpus-local (`reachOf` + `dominates` IDF). A phrase common to
38
+ the aligned exemplars is frame here even when it reaches a corpus minority. Do
39
+ not replace it with the structural IDF — refuted on the `test/17` reorder probe.
40
+ The gate does not use `frameSlots` and therefore **does not consume frame
41
+ slots** — it is not the cohort-local `frameSlots` voice gate.
42
+
43
+ Other admission gates (query ≥ 2 quanta, ≥ 2 ranked anchors, weave touches a
44
+ committed attention root, genuinely woven — not every run restating a recognised
45
+ site) are structural competence checks; see `cast.ts`.
46
+
47
+ ## Cost
48
+
49
+ **2·STEP** (`STEP + STEP`): one projection per transfer act that the taken
50
+ branch performs (halo-mediated analogy adds `CONCEPT`). Weight is
51
+ `moves + PASS·unaccountedBytes` as usual; `accounted` is schema-specific — only
52
+ the two points that schema actually transferred between.
53
+
54
+ ## Investment discipline
55
+
56
+ Floor is `2·STEP`. Before touching the shared expensive analyses
57
+ (`pre.attention()` climb, `pre.weave()`), check `worthRunning(2*STEP)` and
58
+ return the uninvested bound when it already loses. Never compute a shared
59
+ analysis just to discard it.
60
+
61
+ ## Pins
62
+
63
+ - **test/17 intelligence** — reordered single-fact must not trigger
64
+ substitution; the weave-local frame (depth as distinct-structure count +
65
+ half-dominance) is what suppresses it.
66
+ - **test/29 counterfactual** — B/C families pin substitution / redirection /
67
+ comparison and their seat displacements.
68
+ - **test/43 seat** — `seatOfNode` direction (establishing reverse vs forward vs
69
+ fallback) that the schemas displace through.
70
+
71
+ ## Source
72
+
73
+ `src/mind/mechanisms/cast.ts` (`counterfactualTransfer`, `seatOfNode`,
74
+ `MIN_WEAVE`), `src/mind/match.ts` (`alignGraded`, `project`, `depth`),
75
+ `src/geometry.ts` (`dominates`), `src/mind/graph-search.ts` (`STEP`).
@@ -0,0 +1,36 @@
1
+ # Confluence — Multi-Condition Meeting Point
2
+
3
+ Conjunctive queries whose answer lives in no single fact, only where independent
4
+ evidence streams intersect. Each condition reaches its own exemplar set; the
5
+ entity satisfying all lives at their meeting point.
6
+
7
+ Source: `src/mind/mechanisms/confluence.ts` (`confluenceJoin`,
8
+ `confluenceMechanism`).
9
+
10
+ ## Matcher
11
+
12
+ `crossRegionVotes` tiers over the consensus climb (`pre.attention()` ranked
13
+ anchors). Streams are anchors bound by identity to disjoint discriminative query
14
+ spans; two streams are independent when their `cover` spans are disjoint. The
15
+ meet is set intersection by content-addressed identity (`windowsOf` /
16
+ `findBranch` window ids): present in both anchors, absent from the query.
17
+
18
+ ## Gate
19
+
20
+ Corpus-global IDF, not weave-local. A window's `reachOf(ctx, wid, N, memo)`
21
+ (`edgeAncestors` contexts-reached via `sharedReachMemo`) is gated by
22
+ `dominates(reach, N)` (`geometry.ts` half-dominance, `reach*2 > N`). Majority
23
+ reach is scaffolding and never binds a constraint nor survives the meet;
24
+ minority reach is filler/entity. Single-window meets and sub-`2W` spans are
25
+ refused.
26
+
27
+ ## Cost
28
+
29
+ One currency (`mind/graph-search.ts`): `STEP=1`, `CONCEPT=10`, `PASS=1000`/byte.
30
+ `moves = STEP·slots + CONCEPT` (floor `3·STEP`: two constraints + meet). Weight
31
+ `moves + PASS·unaccounted` compared at `STEP` grade (`pipeline.ts:think`).
32
+
33
+ ## Pins
34
+
35
+ `test/32-confluence.test.mjs` — two-constraint intersection, order invariance,
36
+ empty-intersection honesty, cross-domain relational joins.
@@ -0,0 +1,54 @@
1
+ # Cover — Lightest Derivation over the Query
2
+
3
+ Cover is graph search. Its axioms are the query's own decomposition and its goal
4
+ is the cheapest cover of the query's bytes. It runs first so a computed-backed
5
+ cover becomes a near-zero-cost incumbent.
6
+
7
+ ## Matcher — `locate` / recognition sites (`src/mind/recognition.ts`)
8
+
9
+ Sites are spans of the query that name a node already in the store. Cover
10
+ consumes them directly; any site whose bytes overlap a computed span is masked
11
+ (computation always wins).
12
+
13
+ ## Projection — edges + conceptHop (`src/mind/match.ts`, `src/mind/graph-search.ts`)
14
+
15
+ - `formRules` follow continuation edges (`GraphSearch.formRules`): each hop
16
+ costs `STEP` (1). Forks across all continuations up to the hub bound;
17
+ disambiguation is distributional, not heuristic.
18
+ - Edge-less forms may hop via a halo sibling (`conceptHop` / `resolveConcepts`
19
+ in `src/mind/mechanisms/cover.ts`) at `CONCEPT` (10), borrowing a synonym's
20
+ continuation.
21
+
22
+ ## Gate — `leadsSomewhere` (`src/mind/traverse.ts`)
23
+
24
+ A site participates only if it leads somewhere: it bears an edge (`hasNext`) or
25
+ a halo (`hasHalo`). Forms that lead nowhere contribute nothing to any derivation
26
+ and are filtered during recognition.
27
+
28
+ ## Cost (`src/mind/graph-search.ts`)
29
+
30
+ | Symbol | Value | Rule |
31
+ | --------- | ----------- | ----------------------------------------------- |
32
+ | `STEP` | 1 | per edge hop |
33
+ | `CONCEPT` | 10 | abandoning a chain / synonym hop |
34
+ | `PASS` | 1000 / byte | each unaccounted byte |
35
+ | `MICRO` | 1e-3 | per-byte A* heuristic (`h = (len-right)*MICRO`) |
36
+
37
+ Mechanism weight is `moves + PASS * unaccounted_bytes`; comparison is at `STEP`
38
+ grade, then by `scaffolding` bytes, then list order.
39
+
40
+ ## Pre-resolution (`src/mind/mechanisms/cover.ts`)
41
+
42
+ `resolveConcepts` and `resolveConnectors` pre-resolve the async maps the
43
+ synchronous search cannot gather: concept targets and learnt connectors, keyed
44
+ by node pair. Bridges (`bridge`) splice connectors between rewrites.
45
+
46
+ ## Provenance
47
+
48
+ `cover` for the query's own cover; `join` when fusing fragments into a deeper
49
+ learned form.
50
+
51
+ ## Pins
52
+
53
+ - `test/09-edges.test.mjs` — edge following and hop semantics
54
+ - `test/19-nd.test.mjs` — form rules and multi-hop chains
@@ -0,0 +1,53 @@
1
+ # Extraction — Skill-Framed Span Read-out
2
+
3
+ Extraction transfers a learnt span-in-context skill to an unseen query. A skill
4
+ exemplar is a stored fact whose answer is a span of its context (or of its
5
+ pieces); extraction locates the exemplar's framing bytes in the query and reads
6
+ what sits between them.
7
+
8
+ ## Matcher — `skillExemplar` / `isSpanShaped` / `containsSpan` (`src/mind/match.ts`)
9
+
10
+ An exemplar is span-shaped when its answer is an in-order embedding of its
11
+ context. `isSpanShaped` is the open reading (sparse subsequence, any gaps) used
12
+ to accept candidates; `answerRunsInContext` is the strong reading (greedy
13
+ longest contiguous runs) used to decompose the answer for projection. Candidates
14
+ are ranked anchors from `climbAttentionAll` (`Precomputed.spanShapedOf`), tried
15
+ in order up to `pre.k`; sub-quantum (`< W = maxGroup`) or unanchored results are
16
+ skipped.
17
+
18
+ ## Projection — read between located frames (`src/mind/mechanisms/extraction.ts`)
19
+
20
+ `answerRunsInContext` splits the exemplar answer into pieces within its context.
21
+ For each piece, the `W`-bounded pre-frame (and post-frame or next-piece
22
+ pre-frame) is `locate`d in the query at recognition sites. Located frames define
23
+ `start`/`end`; the bytes `query[start:end]` are read out. Multi-piece skills
24
+ concatenate reads in order.
25
+
26
+ ## Gate — both borders located to account (`src/mind/mechanisms/extraction.ts`)
27
+
28
+ Frames are evidence only when `locate` succeeds. An unanchored read (no frame
29
+ located, `accounted === []`) is discarded — not an extraction. An open-ended
30
+ read (only one border located) stays unaccounted.
31
+
32
+ ## Cost (`src/mind/graph-search.ts`)
33
+
34
+ Mechanism weight is `moves + PASS * unaccounted_bytes` with
35
+ `moves = CONCEPT + STEP * accounted.length`. Comparison is at `STEP` grade, then
36
+ scaffolding, then list order.
37
+
38
+ ## Selective accounting
39
+
40
+ Frames are always accounted when located. The read span between them is
41
+ accounted only when bounded on both sides (`preBounded && postBounded`);
42
+ otherwise it is PASS-priced like uncovered bytes, so a correct bounded
43
+ extraction can outweigh an echoing juxtaposition.
44
+
45
+ ## Provenance
46
+
47
+ `extract` (single-piece) or synthesised multi-piece read.
48
+
49
+ ## Pins
50
+
51
+ - `test/00-extract.test.mjs` — skill transfer across values and relations
52
+ - `test/68-extraction-unanchored.test.mjs` — unanchored gate (empty accounted is
53
+ silence)
@@ -0,0 +1,54 @@
1
+ # Prefix Completion — Literal Opening of One Trained Form
2
+
3
+ The query is a proper prefix of exactly one trained form. That form is voiced
4
+ whole; nothing is invented.
5
+
6
+ ## Gate — exactly one opener
7
+
8
+ A candidate is a form whose bytes literally open with the query (every query
9
+ byte matched in order from offset zero). Grounding requires **exactly one
10
+ distinct continuation** over the candidate set:
11
+
12
+ - **Candidates** = `formsOpenedBy` (content-addressed window index) ∪ memoised
13
+ `resonance` top-k — evaluated as one union so an exact-index ambiguity cannot
14
+ be hidden by the approximate tier.
15
+ - **Distinctness** is by continuation bytes, not form id.
16
+ - **Zero or ≥2 distinct continuations → refuse** (the prefix trap).
17
+
18
+ ## Cost (`src/mind/graph-search.ts`)
19
+
20
+ | Symbol | Value | Rule |
21
+ | ------ | ----- | ------------------------------------------------- |
22
+ | `STEP` | 1 | maximal claim: every query byte literally matched |
23
+
24
+ `floor` returns `STEP`; `run` returns one candidate with `moves = STEP`,
25
+ `accounted = [[0, query.length]]`, `bytes = form`.
26
+
27
+ ## `complete` flag
28
+
29
+ The result carries `complete` semantics: the grounded bytes are a trained form
30
+ reached by identity. Post-grounding (`reason` → `fuse`) must not extend them.
31
+
32
+ ## Guards (from `src/mind/mechanisms/prefix-completion.ts`)
33
+
34
+ 1. **Unreadable veto** — a saturating `bytesPrefix` read is a standing
35
+ disagreement; if any candidate saturates, none is licensed.
36
+ 2. **One grouping window** — continuation must be ≥ `W` (`maxGroup`);
37
+ sub-quantum tails are unvoiceable and also count as disagreement.
38
+ 3. **Uniqueness** — as above.
39
+
40
+ Structural pre-check (`floor`): `query.length * W < query.length + W` → `null`
41
+ (no room for a perceivable continuation).
42
+
43
+ ## Where it runs
44
+
45
+ Last grounding mechanism in `defaultMechanisms` (`mind/pipeline.ts`); registered
46
+ after recall so an exact self-match (`IDENTITY`) wins ties. Shares
47
+ `formsOpenedBy` (`mind/traverse.ts`) and `Precomputed.resonance()`.
48
+
49
+ ## Pins
50
+
51
+ - `test/70-prefix-completion.test.mjs` — literal prefix, ambiguity, sub-quantum,
52
+ saturating-read veto, determinism.
53
+ - `test/72-prefix-candidate-supply.test.mjs` — `formsOpenedBy` ∪ `resonance`
54
+ union supply; resonance alone cannot rank a proper prefix.
@@ -0,0 +1,69 @@
1
+ # Recall — Nearest Stored Form
2
+
3
+ Recall resonates the whole query's gist against the content index and grounds
4
+ the nearest learned form. Resonance proposes; bytes decide.
5
+
6
+ ## Gist and budget
7
+
8
+ Query gist is `pre.guide`; the single top-k read is `pre.resonance()` shared
9
+ across the response. `Precomputed.k = 2·recallQueryK` tiers 0b/1/2/3 through it;
10
+ the last tier re-folds bytes.
11
+
12
+ ## Tiers (degrading)
13
+
14
+ | Tier | Name | Gate | Action |
15
+ | ---- | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
16
+ | 0 | Exact identity | `pre.queryResolved` exists | Reverse-recall (`reverseContext`) to best-resonating predecessor at `STEP` |
17
+ | 0b | RC8 argument binding | One maximal `≥2W` edge-source constituent, no substantial `≥2W` form outside it | `follow` its continuation; refuses if result is a subspan of the query |
18
+ | 1 | Clean resonance | `score ≥ identityBar(D,W,len)` per hit | `project` hit; restating hits (bytes or `canon`-equivalent) only via reverse-recall |
19
+ | 2 | Scaffolding-dominated | `score ≥ significanceBar(D)` and consensus-climb anchor clears `consensusFloor(N)` or `dominates(breadth,1) && peak>ln2`, and query is not all-scaffolding | `project` anchor at `CONCEPT`; refuses if continuation voices the anchor's displaced filler or is a query subspan |
20
+ | 3 | Last resort + bridge | Query-relative fraction `max(0,cos−sig)·√(lenG/lenQ) ≥ reachThreshold(W)` | Best grounded `project` hit at `STEP` |
21
+
22
+ W = `maxGroup` (river window); bars from `src/geometry.ts`.
23
+
24
+ ## Echo — the refusing tail
25
+
26
+ If no tier grounded, the exact cosine of the top hit is re-folded (`gistOf` on
27
+ its bytes). Decision uses that exact value in the same query-relative,
28
+ chance-corrected fraction — never the RaBitQ estimate. Below `reach` → silence;
29
+ restating → silence; otherwise the hit's own bytes are returned as an ungrounded
30
+ echo.
31
+
32
+ ## Provenance
33
+
34
+ Grounded answers carry `recall`; the echo carries `recall-echo` (`echoed: true`
35
+ on `RecallResult`). Consumers distinguish a continuation through learned edges
36
+ from a near-identity echo.
37
+
38
+ ## Substitution bridge — refusal-path only (`src/mind/bridge.ts`)
39
+
40
+ Runs only after every gist tier failed, reusing the same top-k proposals (the
41
+ bridge's cap is `2·recallQueryK`; every proposal is byte-verified). A candidate
42
+ context is byte-aligned around the rarest stored W-windows. A mismatch becomes a
43
+ corroborated substitution only when its query span is corpus-attested (every
44
+ W-window stored, one reused ≥2 containers), its geometry clears
45
+ `conceptThreshold(D)` or its halo clears `significanceBar(D)`, its frame is
46
+ unanimous, and the raw gap is length-balanced. Coverage must dominate the query
47
+ and no dismissed gap may hide known content (`dismissedKnownContent` gate). Cost
48
+ is `CONCEPT` per substitution plus `STEP`; accounted spans include matched and
49
+ substituted ranges (so a 28/29-byte paraphrase is not charged `PASS` per
50
+ substituted byte — observed double-charge that let `cast` outbid the bridge).
51
+ Zero-substitution identity bridges carry `complete: true` (the whole read-out);
52
+ substituted bridges do not.
53
+
54
+ Scaffolding-only queries abstain: when every stored window that could anchor is
55
+ saturated (corpus-global scaffolding, `allWindowsAreScaffolding`), the bridge
56
+ returns nothing — a single substituted word cannot carry the semantic load.
57
+
58
+ ## Cost
59
+
60
+ Tiers 0/1/3 price `STEP` (one hop); tier 2 and the bridge price `CONCEPT` per
61
+ substitution/scaffold step. Mechanism `floor` is `STEP`; weight is
62
+ `moves + PASS·unaccounted`.
63
+
64
+ ## Pins
65
+
66
+ - `test/03-recall.test.mjs` — exact identity and reverse-recall
67
+ - `test/16-bridge.test.mjs` — corroborated substitutions
68
+ - `test/73-scaffolding-only-bridge-abstains.test.mjs` — scaffolding-only queries
69
+ stay silent
@@ -0,0 +1,58 @@
1
+ # Reference — Voicing a Slot with the Asker's Bytes
2
+
3
+ Reference voices a slot of a learned frame with the bytes the asker supplied in
4
+ that position — asserting _position_, not equivalence. The bytes are the
5
+ asker's, so voicing them cannot fabricate corpus knowledge; the fabricable claim
6
+ is the _relation_ about them, which the licence withholds.
7
+
8
+ ## Matcher — `frameSlots` inventory
9
+
10
+ The shared matcher is `frameSlots` (`src/mind/match.ts`) via
11
+ `Precomputed.frames()`.
12
+
13
+ - Seeded at origin `(0,0)`, `alignAround` finds common runs (seed `W`) then
14
+ sweeps both directions; each gap is contracted by `contractGap` to its varying
15
+ core (shared prefix/suffix stripped) and tagged
16
+ `substitution | insertion | deletion`.
17
+ - `frameSlots` **reports, never judges**: every gap (any kind, any size), sorted
18
+ by `qs`, plus `covered` (shared bytes) and `matched` spans. No gate is applied
19
+ there.
20
+
21
+ ## Gate — reference elects and licences; matcher does not
22
+
23
+ All voicing gates belong to the **consumer**
24
+ (`src/mind/mechanisms/reference.ts`), not the matcher. A shared layer that
25
+ refused on their behalf would be reference-shaped and hide most real pairings.
26
+
27
+ - **Election:** `electFrame` groups inventory by full slot signature
28
+ (`qs:qe,...`) and keeps the modal group — one frame, not one slot.
29
+ - **Carriage licence:** `carriesFillers` —
30
+ `substituteAll(contA, fillersA→fillersB) == contB` byte-exact, all slots
31
+ simultaneously (longest needle first). Constant continuations pass vacuously;
32
+ filler-dependent content is refused.
33
+ - **Four voicing gates** (in `voiceable` + caller):
34
+ 1. frame `dominates` query (`covered > |query|/2`);
35
+ 2. every slot reaches one window `W` on _both_ sides;
36
+ 3. no insertion/deletion (substitutions only);
37
+ 4. fillers pairwise distinct. Additional: referents pairwise distinct and no
38
+ slot inside `answeredSpans`.
39
+
40
+ Matched frame + every slot is `accounted`; `complete: true`.
41
+
42
+ ## Cost
43
+
44
+ `moves = STEP·slots + STEP` (one binding per slot + one edge follow). Not
45
+ `CONCEPT` — byte identity, not halo. `scaffolding` is never reported; a referent
46
+ is explained, not carried for lack of explanation.
47
+
48
+ `floor` is `STEP+STEP`, investment-disciplined before touching `frames()`.
49
+
50
+ ## Provenance
51
+
52
+ `provenance: "reference"` with trace steps `bindReferent` / `referenceLicence`.
53
+
54
+ ## Pins
55
+
56
+ - `test/76-reference-binding` — inventory vs gate split, carried/absorbed/
57
+ refused, multi-slot licence, `complete` and answered-span guard.
58
+ - `test/76-type-level-company` — type-level halo company underpinning.
package/jsr.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://jsr.io/schema/config-file.v1.json",
3
3
  "name": "@hviana/sema",
4
- "version": "0.7.2",
4
+ "version": "0.7.5",
5
5
  "exports": "./src/index.ts"
6
6
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hviana/sema",
3
- "version": "0.7.2",
3
+ "version": "0.7.5",
4
4
  "description": "Sema: a non-parametric, instance-based reasoning system.",
5
5
  "repository": {
6
6
  "type": "git",
package/src/mind/mind.ts CHANGED
@@ -398,10 +398,24 @@ export class Mind implements MindContext {
398
398
  } = (optsOrCfg ?? {}) as MindOptions;
399
399
  this._canonOpt = optsCanon ?? null;
400
400
  this._profile = optsProfile === true;
401
+ // `explicitSeed` is read BEFORE resolveConfig folds the default in, so
402
+ // the store can be consulted only when the caller did not choose.
403
+ const explicitSeed = (rest as Partial<MindConfig>).seed;
401
404
  this.cfg = resolveConfig(rest as Partial<MindConfig>);
402
405
  this.store = optsStore ?? new SQliteStore({
403
406
  maxGroup: this.cfg.geometry.maxGroup,
404
407
  });
408
+ // THE ARTIFACT'S SEED GOVERNS. `train.seed` is recovered by the store at
409
+ // open, exactly like `train.D` and `geometry.maxGroup`. The seed feeds
410
+ // `makeKeyring`, `Space.rand` and the `Alphabet` below, so folding a
411
+ // query under config.ts's default (42) against a store trained with
412
+ // another seed (e.g. 7) lands in a DIFFERENT vector space than the one
413
+ // the artifact's nodes were folded into: recognition and resonance then
414
+ // read the wrong space and every answer degrades silently. An explicit
415
+ // caller seed still wins — this only replaces the unconfigured default.
416
+ if (explicitSeed === undefined && this.store.trainSeed !== null) {
417
+ this.cfg.seed = this.store.trainSeed;
418
+ }
405
419
  userMechanisms = userMechs ?? [];
406
420
  userFactories = userFacts ?? [];
407
421
  }
@@ -401,6 +401,25 @@ export class SQliteStore extends AbstractStore implements Store {
401
401
  }
402
402
  }
403
403
 
404
+ // Recover the TRAINING seed exactly as D and maxGroup are recovered. The
405
+ // seed seeds the alphabet and the seat keyring (mind.ts), so a Mind that
406
+ // folds a query under any other seed lands in a different vector space
407
+ // than the one this artifact's nodes were folded into — recognition,
408
+ // resonance and every mechanism downstream then read the wrong space. The
409
+ // trainer persists `train.seed` and refuses to resume against a store
410
+ // trained with a different one (example/train_base/main.ts), so the value
411
+ // is authoritative for this artifact. Absent on a store that was never
412
+ // trained, where the caller's configured seed stands.
413
+ {
414
+ const row = this.sqlite.prepare(
415
+ "SELECT val FROM meta WHERE key = 'train.seed'",
416
+ ).get() as { val: string } | undefined;
417
+ if (row) {
418
+ const s = Number(row.val);
419
+ if (Number.isInteger(s) && s >= 0) this._trainSeed = s;
420
+ }
421
+ }
422
+
404
423
  // Persist maxGroup to meta when opening a FRESH store (no rows yet) so
405
424
  // indexSubtree always sees the training-time value even when the store is
406
425
  // accessed without a Mind / full snapshot.