@hviana/sema 0.8.3 → 0.8.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 (85) hide show
  1. package/AGENTS.md +11 -10
  2. package/README.md +17 -38
  3. package/dist/example/demo.js +85 -34
  4. package/dist/src/geometry.d.ts +0 -10
  5. package/dist/src/geometry.js +0 -12
  6. package/dist/src/meter.d.ts +11 -0
  7. package/dist/src/meter.js +11 -0
  8. package/dist/src/mind/articulation.js +1 -1
  9. package/dist/src/mind/attention.js +2 -1
  10. package/dist/src/mind/derivation.d.ts +201 -0
  11. package/dist/src/mind/derivation.js +327 -0
  12. package/dist/src/mind/graph-search.d.ts +2 -1
  13. package/dist/src/mind/graph-search.js +37 -15
  14. package/dist/src/mind/match.d.ts +2 -0
  15. package/dist/src/mind/match.js +2 -0
  16. package/dist/src/mind/mechanisms/alu.js +0 -2
  17. package/dist/src/mind/mechanisms/cast.d.ts +1 -5
  18. package/dist/src/mind/mechanisms/cast.js +15 -18
  19. package/dist/src/mind/mechanisms/confluence.d.ts +0 -3
  20. package/dist/src/mind/mechanisms/confluence.js +3 -9
  21. package/dist/src/mind/mechanisms/cover.js +17 -20
  22. package/dist/src/mind/mechanisms/extraction.d.ts +0 -1
  23. package/dist/src/mind/mechanisms/extraction.js +13 -8
  24. package/dist/src/mind/mechanisms/prefix-completion.js +0 -1
  25. package/dist/src/mind/mechanisms/recall.d.ts +0 -1
  26. package/dist/src/mind/mechanisms/recall.js +8 -9
  27. package/dist/src/mind/mechanisms/reference.js +3 -4
  28. package/dist/src/mind/pipeline-mechanism.d.ts +1 -4
  29. package/dist/src/mind/pipeline.js +106 -41
  30. package/dist/src/mind/rationale.d.ts +0 -11
  31. package/dist/src/mind/rationale.js +6 -32
  32. package/dist/src/mind/reasoning.d.ts +4 -30
  33. package/dist/src/mind/reasoning.js +183 -151
  34. package/dist/src/mind/types.js +6 -3
  35. package/docs/INDEX.md +23 -24
  36. package/docs/INVARIANTS.md +16 -17
  37. package/docs/architecture/bounded-reads.md +4 -4
  38. package/docs/architecture/closure.md +65 -0
  39. package/docs/architecture/commonality.md +27 -18
  40. package/docs/architecture/cost-model.md +5 -5
  41. package/docs/architecture/exact-vs-approximate.md +4 -4
  42. package/docs/architecture/factored-machinery.md +14 -14
  43. package/docs/architecture/mechanism-market.md +9 -9
  44. package/docs/architecture/meter.md +4 -5
  45. package/docs/architecture/store.md +2 -2
  46. package/docs/architecture/thresholds.md +1 -1
  47. package/docs/failures/tempting-but-wrong.md +11 -1
  48. package/docs/harness/gates.md +6 -6
  49. package/docs/mechanisms/cover.md +2 -2
  50. package/example/demo.ts +90 -37
  51. package/jsr.json +1 -1
  52. package/package.json +1 -1
  53. package/src/geometry.ts +0 -13
  54. package/src/meter.ts +11 -0
  55. package/src/mind/articulation.ts +0 -1
  56. package/src/mind/attention.ts +2 -1
  57. package/src/mind/derivation.ts +473 -0
  58. package/src/mind/graph-search.ts +37 -20
  59. package/src/mind/match.ts +2 -0
  60. package/src/mind/mechanisms/alu.ts +0 -2
  61. package/src/mind/mechanisms/cast.ts +17 -21
  62. package/src/mind/mechanisms/confluence.ts +3 -13
  63. package/src/mind/mechanisms/cover.ts +17 -20
  64. package/src/mind/mechanisms/extraction.ts +13 -9
  65. package/src/mind/mechanisms/prefix-completion.ts +0 -1
  66. package/src/mind/mechanisms/recall.ts +7 -9
  67. package/src/mind/mechanisms/reference.ts +2 -3
  68. package/src/mind/pipeline-mechanism.ts +1 -4
  69. package/src/mind/pipeline.ts +121 -46
  70. package/src/mind/rationale.ts +6 -36
  71. package/src/mind/reasoning.ts +208 -178
  72. package/src/mind/types.ts +5 -2
  73. package/test/133-the-decision-point-renders-the-state.test.mjs +204 -0
  74. package/test/134-the-law-explains-the-engines-own-refusal.test.mjs +237 -0
  75. package/test/135-one-law-any-producer.test.mjs +289 -0
  76. package/test/136-the-two-named-limits.test.mjs +205 -0
  77. package/test/137-the-law-lives-once-and-below.test.mjs +400 -0
  78. package/test/138-the-remainder-drains-only-what-a-move-declares.test.mjs +62 -0
  79. package/test/139-the-witness-is-engagement-not-explanation.test.mjs +51 -0
  80. package/test/140-irrelevant-supply-does-not-change-an-answer.test.mjs +48 -0
  81. package/test/141-the-question-is-paid-at-construction.test.mjs +98 -0
  82. package/test/36-already-answered-fusion.test.mjs +20 -2
  83. package/test/37-cluster-dispersion-fusion.test.mjs +30 -3
  84. package/test/38-reason-restate-guard.test.mjs +22 -2
  85. package/test/55-cost-meter.test.mjs +4 -1
@@ -1,19 +1,18 @@
1
1
  # INVARIANTS — Laws, Proofs, Derivations
2
2
 
3
- > Law in `docs/architecture/*.md`, proof in `test/*.test.mjs`.
4
-
5
- | # | Law | Where defined (src symbol) | Pins (test/N) | Doc (docs/architecture/*.md) |
6
- | -- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | ---------------------------- |
7
- | 1 | Determinism | `src/config.ts:seed` `src/alphabet.ts:Alphabet` `src/mind/traverse.ts:guidedFirst` | `test/20` `test/42` | `determinism.md` |
8
- | 2 | Derived thresholds | `src/geometry.ts:mergeThreshold,identityBar,reachThreshold,significanceBar,consensusFloor,dominates` | `test/64` `test/40` | `thresholds.md` |
9
- | 3 | Exact decides / approximate proposes | `src/mind/primitives.ts:resolve` `src/mind/match.ts:locate,alignGraded` `src/mind/resonance.ts:bridge` | `test/51` | `exact-vs-approximate.md` |
10
- | 4 | One cost currency | `src/mind/graph-search.ts:MICRO,STEP,CONCEPT,PASS` `src/derive:lightestDerivation` (min,+) `src/mind/attention.ts:poolVotes` (+,+) | `test/55` `test/04` | `cost-model.md` |
11
- | 5 | Bounded reads | `src/store.ts:AbstractStore:nextFirst,parentsFirst,containersSlice,hasNext,bytesPrefix` `src/mind/traverse.ts:hubBound,hubCap` | `test/90` `test/14` | `bounded-reads.md` |
12
- | 6 | Fold contract | `src/geometry.ts:contentLevels` `src/mind/canonical.ts:canonicalWindows,chainReach` `src/canon.ts:canonicalizer` | `test/59` `test/63` | `fold-contract.md` |
13
- | 7 | Mechanism market | `src/mind/pipeline-mechanism.ts:PipelineMechanism,Precomputed` `src/mind/pipeline.ts:think,worthRunning` | `test/01` `test/04` | `mechanism-market.md` |
14
- | 8 | Two commonality measures | `src/mind/traverse.ts:reachOf,dominates,corpusN` (global) `cast.ts:depth[],MIN_WEAVE` (weave-local) | `test/17` `test/34` | `commonality.md` |
15
- | 9 | Memoization idempotence | `src/mind/pipeline-mechanism.ts:Precomputed` `src/mind/mind.ts:beginResponse,endResponse,_resolvedSubtrees` | `test/42` | `memoization.md` |
16
- | 10 | Caches as budgets | `src/store.ts:BoundedMap` `src/config.ts:StoreConfig:bytesCacheMax,recCacheBytes,haloCacheBytes` | `test/96` `test/91` | `caches.md` |
17
- | 11 | Honest degradation | `src/mind/pipeline.ts:weight=moves+PASS*unaccounted` `src/store.ts:BoundedMap:miss→re-derive` | `test/28` `test/84` | `store.md`+`caches.md` |
18
- | 12 | Meter contracts | `src/meter.ts:Meter,PhaseCost,time` `src/mind/pipeline-mechanism.ts:Precomputed.shared` | `test/55` | `meter.md` |
19
- | 13 | Saturation | `traverse.ts:edgeAncestors,types.ts:SaturationReason` `src/mind/junction.ts:junctionContainersFrom` `src/mind/resonance.ts:pivotInto` | `test/27` `test/16` | `saturation.md` |
3
+ | # | Law | Defined in | Pins | Doc |
4
+ | -- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | ------------------------- |
5
+ | 1 | Determinism | `src/config.ts:seed` `src/alphabet.ts:Alphabet` `src/mind/traverse.ts:guidedFirst` | `test/20` `test/42` | `determinism.md` |
6
+ | 2 | Derived thresholds | `src/geometry.ts:mergeThreshold,identityBar,reachThreshold,significanceBar,consensusFloor,dominates` | `test/64` `test/40` | `thresholds.md` |
7
+ | 3 | Exact decides / approximate proposes | `src/mind/primitives.ts:resolve` `src/mind/match.ts:locate,alignGraded` `src/mind/resonance.ts:bridge` | `test/51` | `exact-vs-approximate.md` |
8
+ | 4 | One cost currency | `src/mind/graph-search.ts:MICRO,STEP,CONCEPT,PASS` `src/derive:lightestDerivation` (min,+) `src/mind/attention.ts:poolVotes` (+,+) | `test/55` `test/04` | `cost-model.md` |
9
+ | 5 | Bounded reads | `src/store.ts:AbstractStore:nextFirst,parentsFirst,containersSlice,hasNext,bytesPrefix` `src/mind/traverse.ts:hubBound,hubCap` | `test/90` `test/14` | `bounded-reads.md` |
10
+ | 6 | Fold contract | `src/geometry.ts:contentLevels` `src/mind/canonical.ts:canonicalWindows,chainReach` `src/canon.ts:canonicalizer` | `test/59` `test/63` | `fold-contract.md` |
11
+ | 7 | Mechanism market | `src/mind/pipeline-mechanism.ts:PipelineMechanism,Precomputed` `src/mind/pipeline.ts:think,worthRunning` | `test/01` `test/04` | `mechanism-market.md` |
12
+ | 8 | Two commonality measures | `src/mind/traverse.ts:reachOf,dominates,corpusN` (global) `cast.ts:depth[],MIN_WEAVE` (weave-local) | `test/17` `test/34` | `commonality.md` |
13
+ | 9 | Memoization idempotence | `src/mind/pipeline-mechanism.ts:Precomputed` `src/mind/mind.ts:beginResponse,endResponse,_resolvedSubtrees` | `test/42` | `memoization.md` |
14
+ | 10 | Caches as budgets | `src/store.ts:BoundedMap` `src/config.ts:StoreConfig:bytesCacheMax,recCacheBytes,haloCacheBytes` | `test/96` `test/91` | `caches.md` |
15
+ | 11 | Honest degradation | `src/mind/pipeline.ts:weight=moves+PASS*unaccounted` `src/store.ts:BoundedMap:miss→re-derive` | `test/28` `test/84` | `store.md`+`caches.md` |
16
+ | 12 | Meter contracts | `src/meter.ts:Meter,PhaseCost,time` `src/mind/pipeline-mechanism.ts:Precomputed.shared` | `test/55` | `meter.md` |
17
+ | 13 | Saturation | `traverse.ts:edgeAncestors,types.ts:SaturationReason` `src/mind/junction.ts:junctionContainersFrom` `src/mind/resonance.ts:pivotInto` | `test/27` `test/16` | `saturation.md` |
18
+ | 14 | Closure | `src/mind/derivation.ts:closed,admissible,advance` | `test/133`–`140` | `closure.md` |
@@ -3,10 +3,10 @@
3
3
  > **Law:** the cost of one query is proportional to the query, not to how much
4
4
  > was learned. No per-query read may grow with corpus size N.
5
5
 
6
- Every fan-out, walk, and disambiguation is capped at `hubBound` —
7
- `ceil(sqrt(N))` — derived once from `corpusN` and floored at 2 so `sqrt` and
8
- `ln` stay meaningful on a near-empty store. There is no second convention; do
9
- not invent one.
6
+ Every fan-out, walk, and disambiguation reads at most the OLDEST `hubBound` —
7
+ `ceil(sqrt(N))`, floored at 2 for a near-empty store. A better-supported
8
+ candidate beyond that prefix is invisible: a trade, and there is no second
9
+ convention.
10
10
 
11
11
  ## Scale
12
12
 
@@ -0,0 +1,65 @@
1
+ # Closure — One Law, One Unit, Every Transition
2
+
3
+ > **Law:** a step is admitted only when it CLOSES the derivation, or MOVES to
4
+ > structure it has not consumed, or CARRIES material the asker left unaccounted.
5
+
6
+ One unit and one law, asked by every tier that decides whether to continue: the
7
+ chart's frontier, the market's candidates, the post-grounding walk, fusion, and
8
+ the mechanisms' own gates. None re-spells a condition the law owns.
9
+
10
+ ## The unit — `src/mind/derivation.ts`
11
+
12
+ | Field | What it is |
13
+ | ----------- | ----------------------------------------------------- |
14
+ | `product` | the answer bytes so far |
15
+ | `accounted` | the spans of the asker's bytes it explains |
16
+ | `remainder` | what the asker still owes, per span, at the `W` floor |
17
+ | `cost` | the currency's total for the steps taken |
18
+ | `fixed` | a declared fixpoint: no transition is offered |
19
+ | `used` | the anchors the producer speaks for |
20
+
21
+ No identity field (`resolve(product)` is one), no structure field, no frontier
22
+ field, no producer field, and no count of any kind. The witnesses `contains` and
23
+ `moves` are the LAYER's: it holds the structure and hands them in, so the law
24
+ never probes the store.
25
+
26
+ ## The transition
27
+
28
+ `admissible(state, continuation, query, W)` returns the witnesses the step pays
29
+ in, or `null`; `advance(state, continuation, witnesses)` is the only transition.
30
+ The remainder is consumed only by a declared move, and only by the material that
31
+ move CARRIES: `carries` admits by ENGAGEMENT and consumes nothing, a move
32
+ consumes what its window proves. Whole-span draining was refuted by `test/110`,
33
+ the window alone by `test/138`. The state is BORN owing what its product does
34
+ not carry.
35
+
36
+ ## One cost home
37
+
38
+ `moves + PASS · unaccountedBytes` is computed in ONE place (`pipeline.ts`,
39
+ `weigh`). A mechanism reports `moves` and `accounted` — what it did — and never
40
+ a price; `cover` reports its chart derivation's work.
41
+
42
+ ## Two limits, proved and left out
43
+
44
+ 1. **The chart cannot evaluate accounting** — its interface has no parameter for
45
+ it, and carrying it per item was measured and rejected. The chart reads the
46
+ same law off an item: identity is its `key`, continuation the rule's
47
+ existence, progress the frontier advancing, closure the goal test, `fix` is
48
+ `fixed`.
49
+ 2. **Closure by the query's position in the graph is not a term of the unit** —
50
+ `reason`'s echo guards stop with the remainder non-empty, and recall's
51
+ reverse tiers close with an empty accounting. That is a fact about the
52
+ asker's material in the store, available only to the layer holding it.
53
+
54
+ ## Layering
55
+
56
+ Imports `../bytes.js` only, and sits below `graph-search.ts`, `match.ts`,
57
+ `rationale.ts` and `pipeline.ts`. The span algebra lives here too — the law's
58
+ vocabulary, not the tracer's.
59
+
60
+ ## Pins
61
+
62
+ - `test/133`–`137` — the law's home, readings, refusal, limits.
63
+ - `test/138` — a cycle cannot close it; a carried move can.
64
+ - `test/139` — carrying is ENGAGEMENT, not explanation.
65
+ - `test/140` — irrelevant supply changes no answer.
@@ -1,9 +1,9 @@
1
- # Two Measures of Commonality
1
+ # Three Measures of Commonality
2
2
 
3
- Sema needs "what is shared" in two different populations. One is corpus-global
4
- (how widely a structure is reused), the other is weave-local (what a local
5
- cohort of overlapping forms agrees on). They use different data and different
6
- formulas and must not be conflated.
3
+ Sema needs "what is shared" in three populations: corpus-global (how widely a
4
+ structure is reused), weave-local (what a local cohort of overlapping forms
5
+ agrees on), and container-local (how many containers hold a byte window).
6
+ Different data, different formulas, never conflated.
7
7
 
8
8
  ## Corpus-global — `reachOf` + `dominates`
9
9
 
@@ -11,11 +11,11 @@ _Defined in `src/mind/traverse.ts` + `src/geometry.ts`; used by climb,
11
11
  containment, IDF pooling._
12
12
 
13
13
  For a node id, `reachOf(id, N)` counts how many learnt contexts contain it
14
- (ancestor reach via capped graph walks, memoised per response in
15
- `sharedReachMemo`). `dominates(reach, N)` then asks whether that reach is above
16
- the corpus-determined majority threshold (derived in `geometry.ts` over `N`).
17
- Intuition: minority reach discriminates (a filler), majority reach is
18
- scaffolding. Powers the consensus climb, edge following, and vote pooling.
14
+ (capped graph walks, memoised per response in `sharedReachMemo`).
15
+ `dominates(reach, N)` asks whether that reach is above the corpus-determined
16
+ majority threshold (`geometry.ts`, over `N`). Minority reach discriminates (a
17
+ filler), majority reach is scaffolding. Powers the climb, edge following and
18
+ vote pooling.
19
19
 
20
20
  ## Weave-local — `depth[]` + `MIN_WEAVE` + `dominates`
21
21
 
@@ -23,20 +23,29 @@ _Defined and gated in `src/mind/mechanisms/cast.ts` (`depth[]` from the shared
23
23
  weave, `MIN_WEAVE`); used by CAST._
24
24
 
25
25
  For an alignment weave, `depth[i]` counts how many aligned structures cover byte
26
- `i` of the query. `MIN_WEAVE = 2` requires agreement beyond a pair (pair columns
27
- are ambiguous with insertions/deletions), and `dominates(depth[i], aligned)`
28
- requires agreement by a majority of the aligned cohort:
26
+ `i` of the query; `MIN_WEAVE = 2` requires agreement beyond a pair (pairs are
27
+ ambiguous with insertions), and `dominates(depth[i], aligned)` a majority of the
28
+ cohort:
29
29
 
30
30
  ```
31
31
  frame(i) ⇔ depth[i] > MIN_WEAVE ∧ dominates(depth[i], aligned)
32
32
  ```
33
33
 
34
- This powers CAST's frame gate: what the local cohort shares vs what
35
- differentiates one member. It never consults corpus reach.
34
+ This powers CAST's frame gate — what the cohort shares vs what differentiates
35
+ one member — and never consults corpus reach.
36
36
 
37
- The two measures answer different questions over different populations; CAST's
38
- frame must not be replaced by a reach check and the climb must not be driven by
39
- weave depth.
37
+ The three answer different questions over different populations; CAST's frame
38
+ must not be replaced by a reach check, and the climb must not be driven by weave
39
+ depth.
40
+
41
+ ## Container-local — the window's rarity
42
+
43
+ _Defined in `src/mind/bridge.ts` (`containersSlice(id, 0, bound + 1).length`);
44
+ used by the bridge, and by attention's anchoring._
45
+
46
+ `rarity` counts how many containers hold a byte window: zero anchors nothing,
47
+ two or more marks it REUSED (`winReused`), and the bridge sorts its anchors by
48
+ it, so the rarest leads. Purpose: choosing what to anchor on.
40
49
 
41
50
  ## Pins
42
51
 
@@ -19,17 +19,17 @@ with that order give the same derivations.
19
19
 
20
20
  ## Pipeline weighing (`src/mind/pipeline.ts:think`)
21
21
 
22
- Mechanism candidates are weighed in the same ladder:
22
+ Candidates are weighed in ONE place — a mechanism reports `moves` and
23
+ `accounted`, never a price:
23
24
 
24
25
  ```
25
26
  weight = moves + PASS * unaccounted_bytes
26
27
  grade = floor(weight / STEP)
27
28
  ```
28
29
 
29
- `unaccounted` is the query bytes no `accounted` span covers. Comparison is at
30
- `STEP` resolution: lowest `grade` wins. At equal grade the candidate with fewer
31
- `scaffolding` bytes (answer bytes lifted from unrecognised spans) wins; only
32
- then does mechanism list order decide.
30
+ `unaccounted` is what no `accounted` span covers. Comparison is at `STEP`
31
+ resolution: lowest `grade` wins; at equal grade fewer `scaffolding` bytes
32
+ (answer bytes lifted from unrecognised spans) wins; then list order.
33
33
 
34
34
  ## Two semirings
35
35
 
@@ -2,16 +2,16 @@
2
2
 
3
3
  Vector scores (`resonate` / `resonateHalo`) are RaBitQ **estimates**. They rank
4
4
  candidates and gate broad regions; they never decide identity. Identity is
5
- decided only by content-addressed lookup — `resolve` / `findLeaf` / `findBranch`
6
- / `canonResolve` — and by re-folding bytes to verify.
5
+ content-addressed lookup — `resolve` / `findLeaf` / `findBranch` /
6
+ `canonResolve` — with ONE exception: the store's near-merge (`store.ts`).
7
7
 
8
8
  ## The law
9
9
 
10
10
  > Scores propose, bytes dispose.
11
11
 
12
12
  Even recall's echo decision re-folds the top hit's bytes rather than trusting
13
- the estimate it already has. No `score >= threshold` path may mint an identity
14
- claim; thresholds derived in `geometry.ts` gate search breadth, not truth.
13
+ the estimate. No OTHER `score >= threshold` path may mint an identity;
14
+ thresholds gate breadth, not truth.
15
15
 
16
16
  ## Graded evidence ladders
17
17
 
@@ -3,23 +3,23 @@
3
3
  Every shared operation is defined once and imported many times. Duplicating it
4
4
  forks the corpus contract; moving it hides who owns the gate.
5
5
 
6
- For the match → project → gate family see `match-project.md`; for the two
7
- commonality measures see `commonality.md`; for work accounting see `meter.md`.
6
+ Siblings: `match-project.md`, `commonality.md`, `meter.md`.
8
7
 
9
8
  ## Single-definition contracts
10
9
 
11
- | Symbol | Defined in | One fact |
12
- | ------------------------------------------------------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
13
- | `contentLevels` | `src/geometry.ts` | Single boundary rule: cuts + levels from one rolling hash pass; every segmentation reads it. |
14
- | `canonicalWindows` / `chainReach` / `leafIdRun` / `windowIds` | `src/mind/canonical.ts` | Write/read contract: training interns `W-1,W` windows, reading chains to `W²` and probes `W`-windows — drift silences recognition. |
15
- | `junction.ts` + `WalkCache` | `src/mind/junction.ts` | Shared junction ascent (parents + containers) with bounded `√N·W` walk; `WalkCache` memoizes capped reads/parents/containers per response; bridge and attention share it. |
16
- | `joinWithBridge` | `src/mind/resonance.ts` | One out-of-search assembly: `bridge(left,right)` or bare concat with `bridgeMiss` trace. |
17
- | `dismissedKnownContent` | `src/mind/bridge.ts` | Pure attestation: any unaccounted `W`-window that resolves as known content — shared gap guard for substitution and CAST. |
18
- | `sharedReachMemo` | `src/mind/traverse.ts` | One response-scoped `AncestorReach` memo (cleared on write and for traces); every `reachOf`/`edgeAncestors` consumer shares it. |
19
- | `guidedFirst` | `src/mind/traverse.ts` | Guided-or-first answer bytes: `guidedNext` else first-inserted edge (`LIMIT 1`). |
20
- | `leadsSomewhere` | `src/mind/traverse.ts` | Admission predicate: `hasNext` (cached) or `hasHalo`; sites that lead nowhere contribute no derivation. |
21
- | `isChunk` | `src/sema.ts` | `kids !== null && kids.every(k=>k.kids===null)` — smallest grouped unit; governs regions, seams, indexing. |
22
- | `twoEndedSeat` | `src/sema.ts` | One seat algebra: first half low seats, second half high seats; shared by perception, `fold`, and canonical folds. |
10
+ | Symbol | Defined in | One fact |
11
+ | ------------------------------------------------------------- | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
12
+ | `contentLevels` | `src/geometry.ts` | Single boundary rule: cuts + levels from one rolling hash pass; every segmentation reads it. |
13
+ | `canonicalWindows` / `chainReach` / `leafIdRun` / `windowIds` | `src/mind/canonical.ts` | Write/read contract: training interns `W-1,W` windows, reading chains to `W²` and probes `W`-windows — drift silences recognition. |
14
+ | `junction.ts` + `WalkCache` | `src/mind/junction.ts` | Shared junction ascent (parents + containers) with bounded `√N·W` walk; `WalkCache` memoizes capped reads/parents/containers per response; bridge and attention share it. |
15
+ | `joinWithBridge` | `src/mind/resonance.ts` | One out-of-search assembly: `bridge(left,right)` or bare concat with `bridgeMiss` trace. |
16
+ | `dismissedKnownContent` | `src/mind/bridge.ts` | Pure attestation: any unaccounted `W`-window that resolves as known content — shared gap guard for substitution and CAST. |
17
+ | `sharedReachMemo` | `src/mind/traverse.ts` | One response-scoped `AncestorReach` memo (cleared on write and for traces); every `reachOf`/`edgeAncestors` consumer shares it. |
18
+ | `guidedFirst` | `src/mind/traverse.ts` | Guided-or-first answer bytes: `guidedNext` else first-inserted edge (`LIMIT 1`). |
19
+ | `leadsSomewhere` | `src/mind/traverse.ts` | Admission predicate: `hasNext` (cached) or `hasHalo`; sites that lead nowhere contribute no derivation. |
20
+ | `isChunk` | `src/sema.ts` | `kids !== null && kids.every(k=>k.kids===null)` — smallest grouped unit; governs regions, seams, indexing. |
21
+ | `twoEndedSeat` | `src/sema.ts` | One seat algebra: first half low seats, second half high seats; shared by perception, `fold`, and canonical folds. |
22
+ | `closed`/`admissible`/`advance` | `src/mind/derivation.ts` | One admission for every derivation step and the readings every tier asks. |
23
23
 
24
24
  ## Pins
25
25
 
@@ -14,12 +14,12 @@ interface PipelineMechanism {
14
14
  }
15
15
  interface MechanismResult {
16
16
  bytes: Uint8Array;
17
- accounted: [number, number][];
17
+ accounted: Array<[number, number]>;
18
18
  moves: number;
19
- unexplained: string;
19
+ used?: ReadonlySet<number>;
20
20
  scaffolding?: number;
21
+ provenance?: string;
21
22
  complete?: boolean;
22
- used?: ReadonlySet<number>;
23
23
  }
24
24
  ```
25
25
 
@@ -53,11 +53,11 @@ Weight is one currency: `weight = moves + PASS · unaccountedBytes` where
53
53
  `√N` via `hubBound`/`hubCap` and `k = 2·recallQueryK` (`Precomputed.k`).
54
54
  Enforced at the store.
55
55
  4. **Evidence travels** — every candidate carries `accounted` (query spans
56
- explained), `moves` (priced on `MICRO/STEP/CONCEPT/PASS`), `unexplained`
57
- (diagnostic label); optionally `scaffolding` (answer bytes from unrecognised
58
- spans — equal-grade tie-break) and `complete` (trained-form continuation
59
- reached via identity; post-grounding must not extend). The decider honours
60
- all three without knowing who set them.
56
+ explained) and `moves` (priced on `MICRO/STEP/CONCEPT/PASS`); optionally
57
+ `scaffolding` (answer bytes from unrecognised spans — equal-grade tie-break),
58
+ `complete` (trained-form continuation reached via identity; post-grounding
59
+ must not extend) and `provenance`. The decider honours them without knowing
60
+ who set them.
61
61
 
62
62
  ## Two disciplines
63
63
 
@@ -86,7 +86,7 @@ Weight is one currency: `weight = moves + PASS · unaccountedBytes` where
86
86
  same act is charged twice (`PASS`/byte dominates).
87
87
 
88
88
  `accounted` is a cost-ladder quantity; `cover.ts` leaves masked computed spans
89
- out so `PASS`-bridged bytes are still charged. `unexplained`, `narrowDecision`,
89
+ out so `PASS`-bridged bytes are still charged. `narrowDecision` and
90
90
  `thinGrounding` are observational only.
91
91
 
92
92
  ## Pins
@@ -11,11 +11,10 @@ it. Harness: `bench/profile-inference.mjs`.
11
11
  an ordering. Determinism survives only because the meter is observed, never
12
12
  consulted. Every call site is `meter?.x++` on a nullable field.
13
13
 
14
- 2. **Counters vs hints.** Counters are deterministic and diffable between runs;
15
- the same query on the same store meters identically, so a regression is
16
- visible in a diff. Millisecond fields (`elapsedMs`, per-phase `ms`) are
17
- non-deterministic hints reported separately — never use them to gate
18
- behaviour.
14
+ 2. **Counters vs hints.** Counters are exact and diffable: a regression shows in
15
+ a diff of two COLD runs; a repeated query meters less, as memos warm.
16
+ Millisecond fields (`elapsedMs`, per-phase `ms`) are non-deterministic hints
17
+ reported separately — never use them to gate behaviour.
19
18
 
20
19
  3. **Phases nest, they do not partition.** Each phase is charged by the layer
21
20
  doing the work (`recognise`, the climb's two, the bridge), and a mechanism's
@@ -37,8 +37,8 @@ root never costs a full walk.
37
37
  ## Gist, halo, dedup
38
38
 
39
39
  On `put*`, content dedup (`hashOf`→probe→mint) gates first. Short keys are
40
- cached (`DEDUP_KEY_MAX` bypass). Near-dedup merges by `mergeThreshold(D)` on
41
- unit gist cosine. Gists sit in `_pendingGist` (byte-budgeted `BoundedMap`);
40
+ cached (`DEDUP_KEY_MAX` bypass). Near-dedup: `identityBar(D, W, len)`, one
41
+ window apart. Gists sit in `_pendingGist` (byte-budgeted `BoundedMap`);
42
42
  `indexSubtree` & `pourHalo` promote via `_vecContentUpsert`/`_vecHaloUpsert` in
43
43
  `batchSize` batches. Buffers flush on cadence, `commit()`, and close. Halo mass
44
44
  re-indexes geometrically (`mass<=4 || powerOfTwo`) and encodes 2-bit quantized.
@@ -17,7 +17,7 @@ perception window), or `N` (corpus size). No threshold is tuned or added to
17
17
 
18
18
  | Symbol | Definition | Formula |
19
19
  | ----------------------- | ---------------------------------------------------------------------------- | ----------------------------------- |
20
- | `mergeThreshold(D)` | Store identity bar — cosine at which `intern` treats two gists as same node | `1 - 1/√D` |
20
+ | `mergeThreshold(D)` | Cosine below which two gists are near enough to consider merging | `1 - 1/√D` |
21
21
  | `identityBar(D,W,len)` | Scale-aware whole-span identity claim | `max(mergeThreshold(D), 1 - W/len)` |
22
22
  | `reachThreshold(W)` | Recall confidence floor — half a river quantum | `1 - 1/(2·W)` |
23
23
  | `estimatorNoise(D)` | RaBitQ noise floor — 1σ of random cosine | `1/√D` |
@@ -1,7 +1,17 @@
1
1
  # Tempting but Wrong — 13 Traps
2
2
 
3
3
  Thirteen shortcuts that look plausible and break an invariant. Each states what
4
- not to do, why it fails, and what to do instead.
4
+ not to do, why it fails, and what to do instead. **Some things are universal:
5
+ discovering bugs:**
6
+
7
+ - A bug must be pinned by a test that shows it.
8
+ - This test cannot be accidental; it is subtle and requires deep analysis. That
9
+ is, it is not the test itself that reveals the bug, but rather the class of
10
+ errors to which the bug belongs.
11
+ - This is difficult to do because the suite's small synthetic corpus easily
12
+ leads to accidental bugs, and real-world corpus must not be compromised.
13
+ - Something that happens due to deduplication, a tie-breaking rule, etc., isn't
14
+ a bug—and that’s a subtle point.
5
15
 
6
16
  ### 1. `score >= threshold` decides identity
7
17
 
@@ -12,9 +12,9 @@ npm test
12
12
  Guards honest silence, determinism, and every pinned contract. Silence:
13
13
  unrelated queries ground to nothing (`test/28`, `50`, `56`, `67`, `76`, `84`).
14
14
  Determinism: same seed + deposit order + query gives byte-identical answer
15
- (`test/20`). Every invariant is pinned — a simplification that fails a test is
16
- wrong until the test is shown wrong. §14–25 (pipeline), §64 (derived
17
- thresholds), AGENTS.md §2 invariants 1–5.
15
+ (`test/20`). Every invariant is pinned, the closure law included
16
+ (`test/133`–`140`). §14–25 (pipeline), §64 (derived thresholds), AGENTS.md §2
17
+ invariants 1–5.
18
18
 
19
19
  ## 2 — Work accounting (profiler)
20
20
 
@@ -23,9 +23,9 @@ node bench/profile-inference.mjs # add [n] to limit probes
23
23
  node bench/profile-inference.mjs --trace # trace is a debugging aid, not product
24
24
  ```
25
25
 
26
- Guards without trace: counters deterministic and diffable between runs; phases
27
- nest (not disjoint — each phase is charged by its own layer); shared analyses
28
- charged to themselves, not to the first toucher; millisecond fields are
26
+ Guards without trace: counters exact and diffable between COLD runs; phases nest
27
+ (not disjoint — each phase is charged by its own layer); shared analyses charged
28
+ to themselves, not to the first toucher; millisecond fields are
29
29
  non-deterministic hints only. With `--trace`, recognition idempotence still
30
30
  holds (`test/42`). `src/meter.ts`, `docs/architecture/meter.md`, §55,
31
31
  `AGENTS.md` §6.
@@ -33,8 +33,8 @@ and are filtered during recognition.
33
33
  | `PASS` | 1000 / byte | each unaccounted byte |
34
34
  | `MICRO` | 1e-3 | per-byte A* heuristic (`h = (len-right)*MICRO`) |
35
35
 
36
- Mechanism weight is `moves + PASS * unaccounted_bytes`; comparison is at `STEP`
37
- grade, then by `scaffolding` bytes, then list order.
36
+ The cover reports `moves` (its derivation's discrete work) and `accounted`; the
37
+ ladder prices both.
38
38
 
39
39
  ## Pre-resolution (`src/mind/mechanisms/cover.ts`)
40
40
 
package/example/demo.ts CHANGED
@@ -1,44 +1,97 @@
1
- // demo.ts — one short session that drives the WHOLE pipeline from one memory.
1
+ // demo.ts — a corpus goes in, and the memory is read back out.
2
2
  //
3
- // We give Sema a handful of plain notes, then ask things that no single note
4
- // answers. The headline query is the third one: from three worked examples Sema
5
- // learns the shape of "X was painted by Y", lifts the painter out of a sentence
6
- // it has NEVER seen, and then — in the same pass — reasons forward to a separate
7
- // fact about that painter. The reply contains no word from the question. That is
8
- // retrieval, generalization, and reasoning composing as a single act, with every
9
- // step traceable back to the notes behind it.
3
+ // Sema is given a small corpus of plain notes, each one the shape every deposit
4
+ // has: a context, and what follows it. Then the memory is read two ways — what
5
+ // it HOLDS (`sampleCorpus`), and which of its notes a question REACHES
6
+ // (`searchCorpusText`). Both run through the same content-addressed machinery an
7
+ // answer uses (src/mind/corpus.ts); nothing is indexed and nothing is written.
8
+ //
9
+ // The search addresses content EXACTLY, not by keyword: a question reaches a
10
+ // note when it shares chunk-aligned content with it, so a question with no such
11
+ // overlap is reported as exactly that — a STATE, rendered by the text layer
12
+ // (`CorpusTextResult.note`), never as prose the engine invented.
13
+ //
14
+ // The last act is two ordinary answers, each with its derivation streamed as it
15
+ // unfolds, the PROVENANCE that names the route it grounded on, and the work it
16
+ // cost read off the meter: the rationale and the meter ARE the explanation
17
+ // surface (AGENTS.md §6).
18
+
19
+ import { decodeText, formatReport, Mind, SQliteStore } from "../src/index.js";
20
+
21
+ // One relation shown three times — a pattern taught purely by example — plus a
22
+ // stray fact keyed on a name none of the examples mention.
23
+ const CORPUS: Array<[string, string]> = [
24
+ ["The Mona Lisa was painted by Leonardo da Vinci.", "Leonardo da Vinci"],
25
+ ["The Starry Night was painted by Vincent van Gogh.", "Vincent van Gogh"],
26
+ [
27
+ "The Night Watch was painted by Rembrandt van Rijn.",
28
+ "Rembrandt van Rijn",
29
+ ],
30
+ ["Pablo Picasso", "Pablo Picasso co-founded the Cubist movement"],
31
+ ["The Weeping Woman was painted by Pablo Picasso.", "Pablo Picasso"],
32
+ ];
10
33
 
11
- import { Mind } from "../src/index.js";
12
- import { SQliteStore } from "../src/store-sqlite.js";
34
+ // Questions the corpus can address, and one it cannot — the honest miss.
35
+ const QUERIES = [
36
+ "The Mona Lisa was painted by Leonardo da Vinci.",
37
+ "Pablo Picasso",
38
+ "xylophone",
39
+ ];
40
+
41
+ // One question answered by composing across the notes, and one answered by
42
+ // computing: the two routes the corpus search does not take.
43
+ const ASKS = [
44
+ "The Weeping Woman was painted by Pablo Picasso.",
45
+ "a museum charges 12*4 for a family ticket",
46
+ ];
13
47
 
14
48
  async function main(): Promise<void> {
15
- const mind = new Mind({ store: new SQliteStore({ path: ":memory:" }) });
16
- const ask = async (q: string) => (await mind.respondText(q)).trim();
17
-
18
- // ── Jot down what we know. Each line is just (context → what follows). ──
19
- await mind.ingest([
20
- // One relation, shown three times — a pattern taught purely by example:
21
- ["The Mona Lisa was painted by Leonardo da Vinci.", "Leonardo da Vinci"],
22
- ["The Starry Night was painted by Vincent van Gogh.", "Vincent van Gogh"],
23
- [
24
- "The Night Watch was painted by Rembrandt van Rijn.",
25
- "Rembrandt van Rijn",
26
- ],
27
- // One stray fact, keyed on a name none of the examples mention:
28
- ["Pablo Picasso", "Pablo Picasso co-founded the Cubist movement"],
29
- ]);
30
-
31
- // 1) GENERALIZE — apply the learned pattern to an unseen sentence and read out
32
- // the painter. "Pablo Picasso" was never given as an answer; Sema locates it
33
- // by analogy to the three examples.
34
- console.log(await ask("The Weeping Woman was painted by Pablo Picasso."));
35
- // → "Pablo Picasso co-founded the Cubist movement"
36
- // …and, having found the painter, it KEEPS GOING: the name bridges into the
37
- // one fact it holds about him. The answer appears in no word of the question.
38
-
39
- // 2) COMPUTE — exact arithmetic, grounded right where the notes go silent.
40
- console.log(await ask("a museum charges 12*4 for a family ticket"));
41
- // → "48"
49
+ const mind = new Mind({
50
+ store: new SQliteStore({ path: ":memory:" }),
51
+ profile: true,
52
+ });
53
+ await mind.ingest(CORPUS);
54
+
55
+ // 1) WHAT THE MEMORY HOLDS — real pairs, browsed, no query and no random draw.
56
+ console.log("— the corpus, as the memory holds it —");
57
+ for (const p of mind.sampleCorpus(4).pairs) {
58
+ console.log(` ${decodeText(p.context)} → ${decodeText(p.continuation)}`);
59
+ }
60
+
61
+ // 2) SEARCH — which stored notes does a question reach? A question that
62
+ // addresses the corpus answers with pairs; one that shares nothing with it
63
+ // answers with a note saying so.
64
+ for (const q of QUERIES) {
65
+ const r = mind.searchCorpusText(q, 3);
66
+ console.log(`\n— "${q}" — ${r.resolved} resolved / ${r.reached} reached`);
67
+ if (r.note !== undefined) console.log(` ${r.note}`);
68
+ for (const p of r.pairs) {
69
+ console.log(
70
+ ` ${p.context} → ${p.continuation} (${p.matchedBytes} matched)`,
71
+ );
72
+ }
73
+ }
74
+
75
+ // 3) ANSWERS, WITH THEIR DERIVATION — the same pipeline, read as data. Steps
76
+ // repeat (recognise re-enters under every mechanism that needs it), so each
77
+ // distinct mechanism-and-note is printed once, in the order it first ran.
78
+ for (const q of ASKS) {
79
+ const seen = new Set<string>();
80
+ const trace: string[] = [];
81
+ const r = await mind.respond(q, (s) => {
82
+ const line = `${s.mechanism.join(" › ")}${s.note ? ` — ${s.note}` : ""}`;
83
+ if (seen.has(line)) return;
84
+ seen.add(line);
85
+ trace.push(`${" ".repeat(Math.max(0, s.mechanism.length - 1))}${line}`);
86
+ });
87
+ console.log(`\n— "${q}" — ${r.provenance ?? "no answer"}`);
88
+ console.log(` ${decodeText(r.bytes).trim()}`);
89
+ console.log("— how —");
90
+ for (const s of trace) console.log(s);
91
+ if (mind.lastCost !== null) {
92
+ console.log(`— what it cost —\n${formatReport(mind.lastCost)}`);
93
+ }
94
+ }
42
95
 
43
96
  await mind.store.close();
44
97
  }
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.8.3",
4
+ "version": "0.8.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.8.3",
3
+ "version": "0.8.5",
4
4
  "description": "Sema: a non-parametric, instance-based reasoning system.",
5
5
  "repository": {
6
6
  "type": "git",
package/src/geometry.ts CHANGED
@@ -180,19 +180,6 @@ export function consensusFloor(N: number): number {
180
180
  return Math.log(N) + 1 / 2;
181
181
  }
182
182
 
183
- /** The coverage bar for the reach (interior) index, when vector-similarity
184
- * gating is used. Returns the concept threshold — the structural midpoint
185
- * (~0.5 at D=1024) where two forms are "more similar than not."
186
- *
187
- * Currently UNUSED in the hot training path: interior nodes are indexed
188
- * unconditionally (hash-cons dedup bounds the index naturally).
189
- * Post-hoc structural compaction ({@link Store.compactContentIndex})
190
- * replaces runtime coverage gating with a batch pass that removes
191
- * structurally-isolated entries. Derived, never tuned. */
192
- export function coverageBar(_maxGroup: number, D: number): number {
193
- return conceptThreshold(D);
194
- }
195
-
196
183
  // ---- types ----
197
184
 
198
185
  export interface Folded {