@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.
- package/AGENTS.md +7 -7
- package/dist/src/alu/src/index.d.ts +1 -1
- package/dist/src/alu/src/index.js +1 -1
- package/dist/src/alu/src/parser.js +2 -6
- package/dist/src/alu/src/resonance.d.ts +13 -0
- package/dist/src/alu/src/resonance.js +41 -0
- package/dist/src/alu/test/alu.test.js +39 -0
- package/dist/src/bytes.d.ts +6 -2
- package/dist/src/bytes.js +10 -4
- package/dist/src/canon.js +44 -0
- package/dist/src/geometry.d.ts +19 -1
- package/dist/src/geometry.js +125 -141
- package/dist/src/meter.d.ts +27 -0
- package/dist/src/meter.js +28 -1
- package/dist/src/mind/articulation.js +14 -1
- package/dist/src/mind/attention.d.ts +12 -0
- package/dist/src/mind/attention.js +44 -16
- package/dist/src/mind/bridge.js +3 -3
- package/dist/src/mind/derivation.d.ts +40 -0
- package/dist/src/mind/derivation.js +34 -0
- package/dist/src/mind/graph-search.d.ts +89 -15
- package/dist/src/mind/graph-search.js +345 -174
- package/dist/src/mind/learning.js +1 -1
- package/dist/src/mind/mechanisms/cover.d.ts +19 -3
- package/dist/src/mind/mechanisms/cover.js +101 -58
- package/dist/src/mind/mechanisms/recall.js +0 -1
- package/dist/src/mind/mind.js +2 -2
- package/dist/src/mind/pipeline.d.ts +5 -1
- package/dist/src/mind/pipeline.js +175 -87
- package/dist/src/mind/primitives.d.ts +25 -5
- package/dist/src/mind/primitives.js +107 -44
- package/dist/src/mind/reasoning.d.ts +18 -4
- package/dist/src/mind/reasoning.js +445 -321
- package/dist/src/mind/recognition.js +55 -73
- package/dist/src/mind/resonance.js +1 -11
- package/dist/src/mind/traverse.d.ts +3 -3
- package/dist/src/mind/traverse.js +3 -3
- package/dist/src/mind/types.d.ts +7 -1
- package/dist/src/store-sqlite.d.ts +25 -0
- package/dist/src/store-sqlite.js +89 -1
- package/dist/src/store.d.ts +48 -4
- package/dist/src/store.js +86 -6
- package/docs/INDEX.md +18 -18
- package/docs/INVARIANTS.md +16 -16
- package/docs/architecture/bounded-reads.md +1 -1
- package/docs/architecture/caches.md +5 -4
- package/docs/architecture/closure.md +45 -5
- package/docs/architecture/cost-model.md +16 -0
- package/docs/architecture/factored-machinery.md +14 -13
- package/docs/architecture/fold-contract.md +51 -1
- package/docs/architecture/mechanism-market.md +21 -0
- package/docs/architecture/memoization.md +3 -3
- package/docs/architecture/meter.md +2 -1
- package/docs/architecture/saturation.md +12 -0
- package/docs/architecture/store.md +25 -2
- package/docs/failures/tempting-but-wrong.md +13 -2
- package/docs/harness/gates.md +12 -10
- package/docs/mechanisms/cover.md +23 -6
- package/jsr.json +1 -1
- package/package.json +1 -1
- package/src/alu/README.md +10 -2
- package/src/alu/src/index.ts +1 -0
- package/src/alu/src/parser.ts +6 -6
- package/src/alu/src/resonance.ts +42 -0
- package/src/alu/test/alu.test.ts +40 -0
- package/src/bytes.ts +13 -3
- package/src/canon.ts +40 -0
- package/src/geometry.ts +183 -154
- package/src/meter.ts +28 -1
- package/src/mind/articulation.ts +14 -2
- package/src/mind/attention.ts +47 -25
- package/src/mind/bridge.ts +3 -3
- package/src/mind/derivation.ts +77 -0
- package/src/mind/graph-search.ts +449 -221
- package/src/mind/learning.ts +1 -7
- package/src/mind/match.ts +1 -2
- package/src/mind/mechanisms/cast.ts +1 -2
- package/src/mind/mechanisms/cover.ts +149 -84
- package/src/mind/mechanisms/extraction.ts +1 -2
- package/src/mind/mechanisms/prefix-completion.ts +1 -1
- package/src/mind/mechanisms/recall.ts +1 -3
- package/src/mind/mechanisms/reference.ts +1 -1
- package/src/mind/mind.ts +5 -30
- package/src/mind/pipeline.ts +206 -102
- package/src/mind/primitives.ts +119 -43
- package/src/mind/reasoning.ts +558 -413
- package/src/mind/recognition.ts +49 -65
- package/src/mind/resonance.ts +2 -16
- package/src/mind/trace.ts +1 -1
- package/src/mind/traverse.ts +3 -3
- package/src/mind/types.ts +9 -11
- package/src/store-sqlite.ts +92 -1
- package/src/store.ts +113 -7
- package/test/105-derive-through-reports-its-refusal.test.mjs +8 -5
- package/test/106-the-join-fires.test.mjs +21 -0
- package/test/111-the-cover-assembly-is-counted.test.mjs +8 -5
- package/test/128-the-leads-somewhere-pair-agrees.test.mjs +18 -12
- package/test/136-the-two-named-limits.test.mjs +3 -2
- package/test/137-the-law-lives-once-and-below.test.mjs +21 -0
- package/test/148-exact-shortcuts-agree.test.mjs +188 -0
- package/test/149-the-closure-engine.test.mjs +138 -0
- package/test/150-the-join-is-output-sensitive.test.mjs +66 -0
- package/test/151-the-cover-pays-for-what-it-reaches.test.mjs +142 -0
- package/test/152-the-read-side-names-as-the-write-side.test.mjs +146 -0
- package/test/153-a-cheaper-bound-is-looked-at-first.test.mjs +155 -0
- package/test/24-generalization.test.mjs +32 -0
- package/test/36-bloom.test.mjs +53 -0
- package/test/37-cluster-dispersion-fusion.test.mjs +75 -0
- package/test/48-recognise-turn-connective.test.mjs +3 -2
- package/test/55-cost-meter.test.mjs +4 -4
- package/test/90-connector-read-cap.test.mjs +7 -7
package/dist/src/store.js
CHANGED
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
// essentials required for SQLite + VectorDatabase communication.
|
|
30
30
|
import { addInto, copy, dot, normalize } from "./vec.js";
|
|
31
31
|
import { identityBar } from "./geometry.js";
|
|
32
|
+
import { latin1 } from "./bytes.js";
|
|
32
33
|
/** Entry cap for the two ANN read caches ({@link AbstractStore._resonateCache}
|
|
33
34
|
* / `_resonateHaloCache`). They are only dropped on index writes, so a long
|
|
34
35
|
* query-only session otherwise grows them without bound — a slow memory/GC
|
|
@@ -335,11 +336,13 @@ export function unpackKids(blob) {
|
|
|
335
336
|
}
|
|
336
337
|
/** 32-bit FNV-1a of a byte blob — the integer content hash `idx_node_h` keys
|
|
337
338
|
* on. Collisions are resolved by verifying the stored blob, never trusted. */
|
|
339
|
+
const FNV_OFFSET = 0x811c9dc5 >>> 0;
|
|
340
|
+
const FNV_PRIME = 0x01000193;
|
|
338
341
|
function hashOf(bytes) {
|
|
339
|
-
let h =
|
|
342
|
+
let h = FNV_OFFSET;
|
|
340
343
|
for (let i = 0; i < bytes.length; i++) {
|
|
341
344
|
h ^= bytes[i];
|
|
342
|
-
h = Math.imul(h,
|
|
345
|
+
h = Math.imul(h, FNV_PRIME) >>> 0;
|
|
343
346
|
}
|
|
344
347
|
return h >>> 0;
|
|
345
348
|
}
|
|
@@ -458,6 +461,9 @@ export class AbstractStore {
|
|
|
458
461
|
/** Exact-content dedup: content-key → node id. Intrinsic compression. */
|
|
459
462
|
_leafKey;
|
|
460
463
|
_branchKey;
|
|
464
|
+
/** {@link findFlatBranch}'s hits, keyed by the bytes themselves (latin1 —
|
|
465
|
+
* exact, unlike the hash keys above). */
|
|
466
|
+
_flatKey;
|
|
461
467
|
/** Reconstructed-bytes read cache (regenerable), keyed by node id. */
|
|
462
468
|
_bytesCache;
|
|
463
469
|
/** contentLen memo — content is immutable, so entries never invalidate. */
|
|
@@ -542,6 +548,7 @@ export class AbstractStore {
|
|
|
542
548
|
this.compactEveryNWrites = config.compactEveryNWrites;
|
|
543
549
|
this._leafKey = new BoundedMap(config.dedupCacheMax);
|
|
544
550
|
this._branchKey = new BoundedMap(config.dedupCacheMax);
|
|
551
|
+
this._flatKey = new BoundedMap(config.dedupCacheMax, undefined, "lru", "clock");
|
|
545
552
|
this._bytesCache = new BoundedMap(config.bytesCacheMax, (v) => v.byteLength, "smallest", "clock");
|
|
546
553
|
this._lenCache = new BoundedMap(config.bytesCacheMax, () => 16);
|
|
547
554
|
this._recCache = new BoundedMap(config.recCacheBytes, (r) => (r.leaf?.byteLength ?? 0) + (r.kids?.length ?? 0) * 4 + 12, "lru", "clock");
|
|
@@ -848,13 +855,82 @@ export class AbstractStore {
|
|
|
848
855
|
* answers most of those with no I/O at all, so the allocations dominated.
|
|
849
856
|
*
|
|
850
857
|
* Pass a subarray: it is a view, so a caller scanning spans of a query
|
|
851
|
-
* allocates nothing per probe.
|
|
852
|
-
*
|
|
853
|
-
*
|
|
858
|
+
* allocates nothing per probe that misses. HITS ARE MEMOIZED, MISSES ARE
|
|
859
|
+
* NOT: the negative filter answers first, so a span that is not stored
|
|
860
|
+
* builds no key; one that may be pays a key and then usually skips the
|
|
861
|
+
* lookup — the spans the identity fold names are segments, a few bytes
|
|
862
|
+
* each, asked over and over by every span that contains them. A node, once
|
|
863
|
+
* minted, keeps its bytes and its id, so a cached hit never goes stale. */
|
|
854
864
|
findFlatBranch(bytes) {
|
|
865
|
+
return this._findFlatHashed(hashOf(bytes), bytes);
|
|
866
|
+
}
|
|
867
|
+
/** {@link Store.flatSpans}. Each start keeps the hash of the span it was
|
|
868
|
+
* last probed to, plus the hash one byte short of it; a probe ending at or
|
|
869
|
+
* past that end extends it, one ending one byte short of it reuses the
|
|
870
|
+
* second, and any other probe hashes from the start. `hashOf` is FNV-1a,
|
|
871
|
+
* a left fold over the bytes, so an extended hash IS the span's hash —
|
|
872
|
+
* same key, same filter answer, same lookup. */
|
|
873
|
+
flatSpans(bytes) {
|
|
874
|
+
const n = bytes.length;
|
|
875
|
+
const runEnd = new Int32Array(n + 1).fill(-1);
|
|
876
|
+
const runH = new Uint32Array(n + 1);
|
|
877
|
+
const shortH = new Uint32Array(n + 1);
|
|
878
|
+
return (start, end) => {
|
|
879
|
+
let h;
|
|
880
|
+
let from;
|
|
881
|
+
const e0 = runEnd[start];
|
|
882
|
+
if (e0 >= 0 && e0 <= end) {
|
|
883
|
+
h = runH[start];
|
|
884
|
+
from = e0;
|
|
885
|
+
}
|
|
886
|
+
else if (e0 >= 0 && e0 - 1 === end && end > start) {
|
|
887
|
+
h = shortH[start];
|
|
888
|
+
from = end;
|
|
889
|
+
}
|
|
890
|
+
else {
|
|
891
|
+
h = FNV_OFFSET;
|
|
892
|
+
from = start;
|
|
893
|
+
}
|
|
894
|
+
let prev = h;
|
|
895
|
+
for (let i = from; i < end; i++) {
|
|
896
|
+
prev = h;
|
|
897
|
+
h = Math.imul(h ^ bytes[i], FNV_PRIME) >>> 0;
|
|
898
|
+
}
|
|
899
|
+
if (from < end) {
|
|
900
|
+
runEnd[start] = end;
|
|
901
|
+
runH[start] = h;
|
|
902
|
+
shortH[start] = prev;
|
|
903
|
+
}
|
|
904
|
+
return this._findFlatHashed(h, bytes.subarray(start, end));
|
|
905
|
+
};
|
|
906
|
+
}
|
|
907
|
+
/** {@link findFlatBranch} past the hash: `h` must be `hashOf(bytes)`. */
|
|
908
|
+
_findFlatHashed(h, bytes) {
|
|
855
909
|
if (this.meter)
|
|
856
910
|
this.meter.branchLookups++;
|
|
857
|
-
|
|
911
|
+
if (!this._dbFlatMayExist(h, bytes))
|
|
912
|
+
return null;
|
|
913
|
+
const key = bytes.length <= DEDUP_KEY_MAX ? latin1(bytes) : null;
|
|
914
|
+
if (key !== null) {
|
|
915
|
+
const hit = this._flatKey.get(key);
|
|
916
|
+
if (hit !== undefined)
|
|
917
|
+
return hit;
|
|
918
|
+
}
|
|
919
|
+
const id = this._dbFindBranchByLeaf(h, bytes);
|
|
920
|
+
if (id !== null && key !== null)
|
|
921
|
+
this._flatKey.set(key, id);
|
|
922
|
+
return id;
|
|
923
|
+
}
|
|
924
|
+
/** {@link Store.flatBranchMayExist} — the backend's negative filter when it
|
|
925
|
+
* keeps one ({@link _dbFlatMayExist}), else the lookup itself. */
|
|
926
|
+
flatBranchMayExist(bytes) {
|
|
927
|
+
return this._dbFlatMayExist(hashOf(bytes), bytes);
|
|
928
|
+
}
|
|
929
|
+
/** Default: no filter, so anything MAY exist and the lookup decides. A
|
|
930
|
+
* backend with a negative filter over node hashes overrides this to answer
|
|
931
|
+
* from the filter alone. */
|
|
932
|
+
_dbFlatMayExist(_h, _bytes) {
|
|
933
|
+
return true;
|
|
858
934
|
}
|
|
859
935
|
findBranch(kids) {
|
|
860
936
|
if (this.meter)
|
|
@@ -1731,6 +1807,10 @@ export class AbstractStore {
|
|
|
1731
1807
|
const r = this._dbGetHalo(id);
|
|
1732
1808
|
return r !== null && r.mass >= this.minHaloMass;
|
|
1733
1809
|
}
|
|
1810
|
+
/** {@link Store.leadsSomewhere} — edge first (the cheaper, commoner probe). */
|
|
1811
|
+
leadsSomewhere(id) {
|
|
1812
|
+
return this.hasNext(id) || this.hasHalo(id);
|
|
1813
|
+
}
|
|
1734
1814
|
async pourHalo(id, add) {
|
|
1735
1815
|
await this._ensureReady();
|
|
1736
1816
|
// A node with a halo is a genuine resonance target — the consensus climb
|
package/docs/INDEX.md
CHANGED
|
@@ -21,22 +21,22 @@ proof in `test/` (pins that fail when the law is broken).
|
|
|
21
21
|
|
|
22
22
|
## Architecture laws (14)
|
|
23
23
|
|
|
24
|
-
| Law | File | Summary
|
|
25
|
-
| --- | ------------------------------------------- |
|
|
26
|
-
| 1 | `docs/architecture/determinism.md` | No `Math.random`/`Date.now` in behaviour; seed-derived randomness; corpus-determined tie-breaks
|
|
27
|
-
| 2 | `docs/architecture/thresholds.md` | Every decision cutoff derived in `geometry.ts` over D/W/N; no tunable knobs
|
|
28
|
-
| 3 | `docs/architecture/exact-vs-approximate.md` | Vector scores rank only; identity via content-addressed lookup; five graded ladders
|
|
29
|
-
| 4 | `docs/architecture/cost-model.md` | Single ladder `MICRO`/`STEP`/`CONCEPT`/`PASS`; weight `moves + PASS·unaccounted`; `STEP`-grade compare
|
|
30
|
-
| 5 | `docs/architecture/match-project.md` | Shared `match.ts` family (`locate`/`alignGraded`/`frameSlots`/`project`); voicing gates belong to consumers
|
|
31
|
-
| 6 | `docs/architecture/mechanism-market.md` | `PipelineMechanism` (`floor`/`run`/`parse`); admissible-floor pruning
|
|
32
|
-
| 7 | `docs/architecture/commonality.md` | Three: global (`reachOf`+`dominates`), weave-local (`depth[]`), window rarity
|
|
33
|
-
| 8 | `docs/architecture/bounded-reads.md` | No per-query read grows with N; `hubBound=√N` enforced at store via LIMIT/probe/prefix caps
|
|
34
|
-
| 9 | `docs/architecture/store.md` | `AbstractStore` owns dedup/indexing/batch; `store-sqlite.ts` is thin wrappers; canon index optional
|
|
35
|
-
| 10 | `docs/architecture/fold-contract.md` | `perceiveDeposit` and `perceive` agree; `contentLevels` is single boundary rule; no W/offset dependence
|
|
36
|
-
| 11 | `docs/architecture/memoization.md` | `Precomputed` is per-response lazy cache (promise-cached async); `beginResponse`/`endResponse` lifecycle
|
|
37
|
-
| 12 | `docs/architecture/saturation.md` | Every walk names a deciding saturation beside its cap; cap is safety net, not decision
|
|
38
|
-
| 13 | `docs/architecture/meter.md` | `meter.ts` is write-only work accounting; counts are exact, phases nest
|
|
39
|
-
| 14 | `docs/architecture/closure.md` | A derivation is closed when its structure accounts for the question's remainder; every transition asks that law | `test/133`–`
|
|
24
|
+
| Law | File | Summary | Pins |
|
|
25
|
+
| --- | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------- |
|
|
26
|
+
| 1 | `docs/architecture/determinism.md` | No `Math.random`/`Date.now` in behaviour; seed-derived randomness; corpus-determined tie-breaks | `test/20` |
|
|
27
|
+
| 2 | `docs/architecture/thresholds.md` | Every decision cutoff derived in `geometry.ts` over D/W/N; no tunable knobs | `test/40`, `test/64` |
|
|
28
|
+
| 3 | `docs/architecture/exact-vs-approximate.md` | Vector scores rank only; identity via content-addressed lookup; five graded ladders | `test/51` |
|
|
29
|
+
| 4 | `docs/architecture/cost-model.md` | Single ladder `MICRO`/`STEP`/`CONCEPT`/`PASS`; weight `moves + PASS·unaccounted`; `STEP`-grade compare | `test/04`, `test/55` |
|
|
30
|
+
| 5 | `docs/architecture/match-project.md` | Shared `match.ts` family (`locate`/`alignGraded`/`frameSlots`/`project`); voicing gates belong to consumers | `test/24`, `test/76` |
|
|
31
|
+
| 6 | `docs/architecture/mechanism-market.md` | `PipelineMechanism` (`floor`/`run`/`parse`); admissible-floor pruning, investment discipline, run-ahead bounds | `test/01`, `test/04`, `test/153` |
|
|
32
|
+
| 7 | `docs/architecture/commonality.md` | Three: global (`reachOf`+`dominates`), weave-local (`depth[]`), window rarity | `test/17`, `test/34` |
|
|
33
|
+
| 8 | `docs/architecture/bounded-reads.md` | No per-query read grows with N; `hubBound=√N` enforced at store via LIMIT/probe/prefix caps | `test/77`, `test/90` |
|
|
34
|
+
| 9 | `docs/architecture/store.md` | `AbstractStore` owns dedup/indexing/batch; `store-sqlite.ts` is thin wrappers; canon index optional | `test/08` |
|
|
35
|
+
| 10 | `docs/architecture/fold-contract.md` | `perceiveDeposit` and `perceive` agree; the read side names a branch as `intern` does; `contentLevels` is single boundary rule; no W/offset dependence | `test/59`, `test/63`, `test/148`, `test/152` |
|
|
36
|
+
| 11 | `docs/architecture/memoization.md` | `Precomputed` is per-response lazy cache (promise-cached async); `beginResponse`/`endResponse` lifecycle | `test/42` |
|
|
37
|
+
| 12 | `docs/architecture/saturation.md` | Every walk names a deciding saturation beside its cap; cap is safety net, not decision | `test/27`, `test/16` |
|
|
38
|
+
| 13 | `docs/architecture/meter.md` | `meter.ts` is write-only work accounting; counts are exact, phases nest | `test/55` |
|
|
39
|
+
| 14 | `docs/architecture/closure.md` | A derivation is closed when its structure accounts for the question's remainder; every transition asks that law, one engine walks the layers | `test/133`–`151` |
|
|
40
40
|
|
|
41
41
|
## Mechanisms (8)
|
|
42
42
|
|
|
@@ -65,6 +65,6 @@ proof in `test/` (pins that fail when the law is broken).
|
|
|
65
65
|
exact-decides, one cost currency, bounded reads) with file-level routing.
|
|
66
66
|
- `docs/failures/tempting-but-wrong.md` — refuted simplifications that passed
|
|
67
67
|
review but failed pins.
|
|
68
|
-
- `docs/harness/gates.md` — how `AGENTS.md` recipes,
|
|
69
|
-
`
|
|
68
|
+
- `docs/harness/gates.md` — how `AGENTS.md` recipes, the meter's public path
|
|
69
|
+
(`profile: true` → `mind.lastCost`), and `test/*.test.mjs` enforce the laws.
|
|
70
70
|
- `docs/architecture/` — per-law derivation: each file says why, not how.
|
package/docs/INVARIANTS.md
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
# INVARIANTS — Laws, Proofs, Derivations
|
|
2
2
|
|
|
3
|
-
| # | Law | Defined in
|
|
4
|
-
| -- | ------------------------------------ |
|
|
5
|
-
| 1 | Determinism | `src/config.ts:seed` `src/alphabet.ts:Alphabet` `src/mind/traverse.ts:guidedFirst`
|
|
6
|
-
| 2 | Derived thresholds | `src/geometry.ts:mergeThreshold,identityBar,reachThreshold,significanceBar,consensusFloor,dominates`
|
|
7
|
-
| 3 | Exact decides / approximate proposes | `src/mind/primitives.ts:resolve` `src/mind/match.ts:locate,alignGraded` `src/mind/resonance.ts:bridge`
|
|
8
|
-
| 4 | One cost currency | `src/mind/graph-search.ts:MICRO,STEP,CONCEPT,PASS` `src/derive:lightestDerivation` (min,+) `src/mind/attention.ts:poolVotes` (+,+)
|
|
9
|
-
| 5 | Bounded reads | `src/store.ts:AbstractStore:nextFirst,parentsFirst,containersSlice,hasNext,bytesPrefix` `src/mind/traverse.ts:hubBound,hubCap`
|
|
10
|
-
| 6 | Fold contract | `src/geometry.ts:contentLevels` `src/mind/canonical.ts:canonicalWindows,chainReach` `src/canon.ts:canonicalizer`
|
|
11
|
-
| 7 | Mechanism market | `src/mind/pipeline-mechanism.ts:PipelineMechanism,Precomputed` `src/mind/pipeline.ts:think,worthRunning`
|
|
12
|
-
| 8 | Two commonality measures | `src/mind/traverse.ts:reachOf,dominates,corpusN` (global) `cast.ts:depth[],MIN_WEAVE` (weave-local)
|
|
13
|
-
| 9 | Memoization idempotence | `src/mind/pipeline-mechanism.ts:Precomputed` `src/mind/mind.ts:beginResponse,endResponse,_resolvedSubtrees`
|
|
14
|
-
| 10 | Caches as budgets | `src/store.ts:BoundedMap` `src/config.ts:StoreConfig:bytesCacheMax,recCacheBytes,haloCacheBytes`
|
|
15
|
-
| 11 | Honest degradation | `src/mind/pipeline.ts:weight=moves+PASS*unaccounted` `src/store.ts:BoundedMap:miss→re-derive`
|
|
16
|
-
| 12 | Meter contracts | `src/meter.ts:Meter,PhaseCost,time` `src/mind/pipeline-mechanism.ts:Precomputed.shared`
|
|
17
|
-
| 13 | Saturation | `traverse.ts:edgeAncestors,types.ts:SaturationReason` `src/mind/junction.ts:junctionContainersFrom` `src/mind/resonance.ts:pivotInto`
|
|
18
|
-
| 14 | Closure | `src/mind/derivation.ts:
|
|
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,contentIdentity` `src/mind/primitives.ts:branchNaming` `src/mind/canonical.ts:canonicalWindows,chainReach` `src/canon.ts:canonicalizer` | `test/59` `test/63` `test/152` | `fold-contract.md` |
|
|
11
|
+
| 7 | Mechanism market | `src/mind/pipeline-mechanism.ts:PipelineMechanism,Precomputed` `src/mind/pipeline.ts:think,worthRunning` | `test/01` `test/04` `test/153` | `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:admissible,advance,closeOver` | `test/133`–`151` | `closure.md` |
|
|
@@ -81,5 +81,5 @@ net); a walk with only a cap drifts to the cap.
|
|
|
81
81
|
length; training throughput floor; exact recall at scale.
|
|
82
82
|
- `test/89` — completion recursion stays output-sensitive (nested searches/pops
|
|
83
83
|
sublinear); guards the count of reads, not just per-read size.
|
|
84
|
-
- `test/90` — connector probe (`
|
|
84
|
+
- `test/90` — connector probe (`offerConnectors`) reads by the query length
|
|
85
85
|
(`QUERY.length + 1`), not by the learnt continuation; per-read size bound.
|
|
@@ -31,6 +31,7 @@ candidate window for `"smallest"` never rescans from front.
|
|
|
31
31
|
| Cache | Field | Budget | `sizeOf` | Eviction |
|
|
32
32
|
| ------------------- | -------------------------- | ---------------------------- | ------------------- | -------------- |
|
|
33
33
|
| dedup leaf/branch | `_leafKey` / `_branchKey` | `dedupCacheMax` 1M entries | 1 | lru |
|
|
34
|
+
| flat-branch hits | `_flatKey` | `dedupCacheMax` 1M entries | 1 | lru+clock |
|
|
34
35
|
| reconstructed bytes | `_bytesCache` | `bytesCacheMax` 20 MB | `byteLength` | smallest+clock |
|
|
35
36
|
| content length | `_lenCache` | `bytesCacheMax` | 16 | lru |
|
|
36
37
|
| node records | `_recCache` | `recCacheBytes` 10 MB | leaf+4·kids+12 | lru+clock |
|
|
@@ -76,10 +77,10 @@ must discharge it.
|
|
|
76
77
|
`contentFoldIncremental` segments bit-identically.
|
|
77
78
|
- Wrong: mismatched `prev` reused by offset produced wrong tree (336 vs 400
|
|
78
79
|
bytes) — a coincidental prefix length aliased unrelated content.
|
|
79
|
-
- Now: `perceiveDeposit` keys by `
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
80
|
+
- Now: `perceiveDeposit` keys by `latin1(bytes.subarray(0,L))` (prefix bytes),
|
|
81
|
+
probes longest cached proper prefix first; `_depositTrees` populated only for
|
|
82
|
+
conversational deposits (budget discipline), otherwise cold path always
|
|
83
|
+
correct.
|
|
83
84
|
|
|
84
85
|
## Pins
|
|
85
86
|
|
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
> **Law:** a step is admitted only when it CLOSES the derivation, or MOVES to
|
|
4
4
|
> structure it has not consumed, or CARRIES material the asker left unaccounted.
|
|
5
5
|
|
|
6
|
-
One unit and one
|
|
7
|
-
chart's frontier, the market's candidates, the post-grounding
|
|
8
|
-
the mechanisms' own gates. None re-spells a condition the law
|
|
6
|
+
One unit, one law and one engine, asked by every tier that decides whether to
|
|
7
|
+
continue: the chart's frontier, the market's candidates, the post-grounding
|
|
8
|
+
walk, fusion, and the mechanisms' own gates. None re-spells a condition the law
|
|
9
|
+
owns.
|
|
9
10
|
|
|
10
11
|
## The unit — `src/mind/derivation.ts`
|
|
11
12
|
|
|
@@ -43,7 +44,35 @@ not carry.
|
|
|
43
44
|
|
|
44
45
|
The walk ends when the layer stops offering or the law refuses; owning no
|
|
45
46
|
search, the law cannot prevent a cycle — that is the layer's, over the structure
|
|
46
|
-
it holds.
|
|
47
|
+
it holds. A transition is only ever `advance`: a fusion the law refuses is not
|
|
48
|
+
taken (there is no hand-built fallback).
|
|
49
|
+
|
|
50
|
+
## The engine — `closeOver`
|
|
51
|
+
|
|
52
|
+
`closeOver(state, query, W, layers, enter?)` closes a derivation under the law,
|
|
53
|
+
layer by layer. A layer (`ClosureLayer`) is a named `Offer` with its own
|
|
54
|
+
instrumentation hooks; each is walked by `closure` to its own end, and the state
|
|
55
|
+
it reaches is the state the next layer is offered against. Layers are PHASES, in
|
|
56
|
+
order, never revisited.
|
|
57
|
+
|
|
58
|
+
- **¬FIXED is the engine's.** A fixed state admits no transition, so no layer is
|
|
59
|
+
entered for it — the walk-skip and fusion-skip a caller used to spell by hand
|
|
60
|
+
are the law's first clause, taken before any layer pays.
|
|
61
|
+
- **Engagement is the layer's.** A layer that has nothing to offer a state
|
|
62
|
+
(`engages`) is not entered: no offer, no meter phase.
|
|
63
|
+
- **The pipeline's post-grounding stage IS the engine**, with two layers: the
|
|
64
|
+
walk (`walkLayer` — forward absorb or pivot) and the fusion (`fusionLayer` —
|
|
65
|
+
one composed transition, engaged only while the derivation is open). There is
|
|
66
|
+
no hand-built state anywhere outside `advance` (`test/137.7`).
|
|
67
|
+
|
|
68
|
+
## The four quantities (trap 13), and where each stands
|
|
69
|
+
|
|
70
|
+
| Quantity | Status |
|
|
71
|
+
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
72
|
+
| offer of a hop | Consequence. Chart: the corpus's continuations under the READ cap, each a MOVE priced STEP, the search decides (`test/112`). Walk: absorb/pivot, the law admits. |
|
|
73
|
+
| depth of a join | Consequence. The join consumes the shortest tail prefix naming a learnt key that leads — CONTAINS (resolves) ∧ MOVES (leads) — and chains until the tail is consumed; no count (`test/108`). It is priced for the facts a lightest derivation STANDS ON, round by round (`solve`'s join license), never for every fact the exploration reaches — the `deepen` cure for the `recompleteNode` trap. |
|
|
74
|
+
| scope of a gap | Consequence for alignment (`alignAround` walks outward, no cap). NOT for recognition's interior pass: its reach `W⁴ + 2r` bounds an exhaustive embedded-form probe; exact unbounded reach needs a whole-stream index the store does not have. |
|
|
75
|
+
| scope of a substitution | Consequence: the gap between two aligned anchors (`unexplainedSpans`), gated as scaffolding by the global commonality reading. The filler-unanimity window (`chainReach`) is a derived decision scale, not an explosion cap. |
|
|
47
76
|
|
|
48
77
|
## One cost home
|
|
49
78
|
|
|
@@ -51,7 +80,7 @@ it holds.
|
|
|
51
80
|
`weigh`). A mechanism reports `moves` and `accounted` — what it did — and never
|
|
52
81
|
a price; `cover` reports its chart derivation's work.
|
|
53
82
|
|
|
54
|
-
##
|
|
83
|
+
## Three limits, proved and left out
|
|
55
84
|
|
|
56
85
|
1. **The chart cannot evaluate accounting** — its interface has no parameter for
|
|
57
86
|
it, and carrying it per item was measured and rejected. The chart reads the
|
|
@@ -62,6 +91,9 @@ a price; `cover` reports its chart derivation's work.
|
|
|
62
91
|
`reason`'s echo guards stop with the remainder non-empty, and recall's
|
|
63
92
|
reverse tiers close with an empty accounting. That is a fact about the
|
|
64
93
|
asker's material in the store, available only to the layer holding it.
|
|
94
|
+
3. **The extension is not priced into the market** (`test/136.2`): the engine
|
|
95
|
+
closes the WINNER only; pricing each candidate's closure would run the walk
|
|
96
|
+
for every candidate, and that comparison has not been measured.
|
|
65
97
|
|
|
66
98
|
## Layering
|
|
67
99
|
|
|
@@ -78,3 +110,11 @@ vocabulary, not the tracer's.
|
|
|
78
110
|
- `test/142`, `test/143` — the offer's contract, and the cycles.
|
|
79
111
|
- `test/144`, `test/146`, `test/147` — identity is content, the `contains` gate,
|
|
80
112
|
the witness ladder.
|
|
113
|
+
- `test/137.7` — no transition is built by hand outside the law.
|
|
114
|
+
- `test/149` — the engine: ¬FIXED first, layers as phases, engagement, a refusal
|
|
115
|
+
ends one layer, and the pipeline sequences no layer by hand.
|
|
116
|
+
- `test/150` — the join prices the facts a derivation stands on, not every fact
|
|
117
|
+
the exploration reaches (a hub's degree changes nothing).
|
|
118
|
+
- `test/151` — the cover's other async premises (connectors, concept hops) are
|
|
119
|
+
resolved where the search reaches them; a span's cheapest completion
|
|
120
|
+
dominates; a grounding on the whole query pays no fusion climb.
|
|
@@ -56,6 +56,21 @@ minimum per-byte cost in the ladder (every real per-byte cost is `>= MICRO`,
|
|
|
56
56
|
including `PASS`), and only the suffix past `right` is counted, so `h` never
|
|
57
57
|
exceeds the true remaining cost.
|
|
58
58
|
|
|
59
|
+
## Dominance — why `PASS ≫ STEP` does not flood the chart
|
|
60
|
+
|
|
61
|
+
The heuristic charges `MICRO` for a byte the goal will pay `PASS` for, so a
|
|
62
|
+
cover that leaves bytes unexplained lets the search spend up to `PASS / STEP`
|
|
63
|
+
hops looking for one more explained byte. Coverage itself cannot use them: every
|
|
64
|
+
recognised completion of `[i, j)` advances the cover from `i` to `j` at the same
|
|
65
|
+
`MICRO`. So a form or completion of `[i, j)` whose cost has reached that of a
|
|
66
|
+
completion of `[i, j)` already yielded is DOMINATED and fires no rule
|
|
67
|
+
(`buildSearch`, metered as `searchDominated`): every completion it could lead to
|
|
68
|
+
costs at least as much, and a tie goes to the one yielded first. What a
|
|
69
|
+
completion's BYTES could still do — fuse, splice, join — fires from the
|
|
70
|
+
completion the search would stand on for that span, the same cure the join
|
|
71
|
+
license and `deepen` apply. The first hop's stop-here (`STEP + CONCEPT`) is then
|
|
72
|
+
a real horizon: no chain deeper than it is expanded.
|
|
73
|
+
|
|
59
74
|
## Policy is not cost
|
|
60
75
|
|
|
61
76
|
"Computation always wins" is **not** priced into the ladder (a computed result
|
|
@@ -69,3 +84,4 @@ the sole completion there. Keep policy in callers; keep the engine neutral.
|
|
|
69
84
|
- `test/53` — cross-region probe instrumentation
|
|
70
85
|
- `test/54` — evidence `k` instrumentation
|
|
71
86
|
- `test/55` — cost meter (`Meter`, `CostReport`, `searchPops`/`searchPushes`)
|
|
87
|
+
- `test/151` — dominance: a hub's degree generates no chart work
|
|
@@ -7,19 +7,20 @@ Siblings: `match-project.md`, `commonality.md`, `meter.md`.
|
|
|
7
7
|
|
|
8
8
|
## Single-definition contracts
|
|
9
9
|
|
|
10
|
-
| Symbol | Defined in
|
|
11
|
-
| ------------------------------------------------------------- |
|
|
12
|
-
| `contentLevels` | `src/geometry.ts`
|
|
13
|
-
| `canonicalWindows` / `chainReach` / `leafIdRun` / `windowIds` | `src/mind/canonical.ts`
|
|
14
|
-
| `junction.ts` + `WalkCache` | `src/mind/junction.ts`
|
|
15
|
-
| `joinWithBridge` | `src/mind/resonance.ts`
|
|
16
|
-
| `dismissedKnownContent` | `src/mind/bridge.ts`
|
|
17
|
-
| `sharedReachMemo` | `src/mind/traverse.ts`
|
|
18
|
-
| `guidedFirst` | `src/mind/traverse.ts`
|
|
19
|
-
| `leadsSomewhere` | `src/mind/traverse.ts`
|
|
20
|
-
| `isChunk` | `src/sema.ts`
|
|
21
|
-
| `twoEndedSeat` | `src/sema.ts`
|
|
22
|
-
| `closed`/`admissible`/`advance`
|
|
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/store.ts` (raw), `src/mind/traverse.ts` (memoised) | Admission predicate: `hasNext` or `hasHalo`, defined once on the store; traverse memoises the edge tier per response. |
|
|
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`/`closeOver` | `src/mind/derivation.ts` | One admission for every derivation step, the readings every tier asks, and the engine that walks the post-grounding layers. |
|
|
23
|
+
| `exactNode` | `src/mind/primitives.ts` | The exact content-addressed lookup (`resolve`, `canonResolve`): the identity fold (`contentIdentity`, geometry.ts) — a miss decided by the segment filter, a hit named bottom-up, no vectors. |
|
|
23
24
|
|
|
24
25
|
## Pins
|
|
25
26
|
|
|
@@ -56,6 +56,50 @@ drift without a type error. Levels are read from the hash the cut was accepted
|
|
|
56
56
|
at — level `L` when `h` vanishes mod `W^(L+1)` — so level-`L` cuts nest inside
|
|
57
57
|
level-`(L-1)` and expected span is `W^(L+1)` bytes.
|
|
58
58
|
|
|
59
|
+
## One shape, two algebras
|
|
60
|
+
|
|
61
|
+
Which items group under which parent is decided by the cut levels, the keyring
|
|
62
|
+
and — inside an over-long row — each item's `itemKey` (eight raw gist
|
|
63
|
+
coordinates). `groupByLevel`/`foldSlice` are written ONCE over a fold algebra
|
|
64
|
+
(`join`, `key`) and run over two of them: the vector fold (`perceive`) and the
|
|
65
|
+
identity fold (`contentIdentity`), which names the node a stream folds to by
|
|
66
|
+
asking the store bottom-up and reads only the coordinates `itemKey` hashes,
|
|
67
|
+
lazily, with the same float32 additions in the same order. `exactNode` is the
|
|
68
|
+
identity fold, so resolving a span builds no D-dimensional gist and leaves
|
|
69
|
+
nothing in the perception memo (measured on the 31.7M-node store: one join query
|
|
70
|
+
went 185 s / 4.4 GB retained → 40 s / 81 MB, same answer). A grouping rule
|
|
71
|
+
written twice would be a write/read drift waiting to happen; written once, the
|
|
72
|
+
two folds cannot disagree about the tree.
|
|
73
|
+
|
|
74
|
+
## Same tree is not enough — the read side names as the write side names
|
|
75
|
+
|
|
76
|
+
The store's `intern` names a branch by its children, and when they name none it
|
|
77
|
+
looks up the FLAT node over the same bytes and REUSES it (step 1b, "same bytes,
|
|
78
|
+
same node"). Every deposit interns flat nodes — its whole input and each
|
|
79
|
+
canonical window — so a later deposit's branch is often stored as an earlier
|
|
80
|
+
deposit's window (`ver` + `!` stored as the window `ver!`). The same tree is
|
|
81
|
+
then named by a node no child lookup can reach. `exactNode` and `foldTree` name
|
|
82
|
+
a branch exactly as `intern` does (`branchNaming`, `src/mind/primitives.ts`):
|
|
83
|
+
the children first, the flat node over the same bytes when they name nothing —
|
|
84
|
+
and an unnamed child does not settle it, since the write side minted that child
|
|
85
|
+
and still reached step 1b. Measured on the 31.7M-node store: 7 of 80 dialogue
|
|
86
|
+
turns asked verbatim had resolved to nothing and fell to the composition path
|
|
87
|
+
(26–41 s); they now resolve to their own context.
|
|
88
|
+
|
|
89
|
+
A name found only through the bytes is where the exact lookup used to MISS, and
|
|
90
|
+
a flat index entry is not a learnt structure, so `resolve` still asks the
|
|
91
|
+
canonical class there (`exactNaming`'s `byBytes`): it holds the learnt member
|
|
92
|
+
that leads somewhere, when there is one. The store holds such byte-only names
|
|
93
|
+
from an earlier deposit path (today's deposits always intern the structure
|
|
94
|
+
beside the flat copy), which is why `test/152` builds the state through the
|
|
95
|
+
store's write API.
|
|
96
|
+
|
|
97
|
+
One stored turn of the same set still does not resolve: its context was stored
|
|
98
|
+
with cuts at the ends of the conversation's EARLIER contexts (103 and 227 bytes
|
|
99
|
+
into a 257-byte context) — a boundary-imposed shape neither today's deposit path
|
|
100
|
+
nor the training-time one produces from these bytes, and that the read side
|
|
101
|
+
could reproduce only by guessing turn boundaries, which this contract forbids.
|
|
102
|
+
|
|
59
103
|
## Optional canonical capability
|
|
60
104
|
|
|
61
105
|
`canonAdd`/`canonFind` (`src/store.ts` — `canonCount`/`eachContent`) is an
|
|
@@ -81,7 +125,13 @@ any change here.
|
|
|
81
125
|
- `test/59` — shift invariance floors (content-defined cuts preserved over
|
|
82
126
|
random binary and prose).
|
|
83
127
|
- `test/63` — offset/W invariance and `contentLevels` distribution expectations.
|
|
128
|
+
- `test/148` — the identity fold names exactly what the vector fold names (every
|
|
129
|
+
sub-span of corpus and noise), and groups exactly as it does over long
|
|
130
|
+
low-entropy streams that force the `itemKey` split.
|
|
131
|
+
- `test/152` — a deposit stored through an earlier deposit's flat window
|
|
132
|
+
resolves to its own context, both folds name it, and it is answered on the
|
|
133
|
+
exact path.
|
|
84
134
|
|
|
85
135
|
See:
|
|
86
|
-
`src/geometry.ts:contentLevels`/`contentBoundaries`/`contentFoldIncremental`/`stablePrefixFold`;
|
|
136
|
+
`src/geometry.ts:contentLevels`/`contentBoundaries`/`contentFoldIncremental`/`stablePrefixFold`/`contentIdentity`;
|
|
87
137
|
`AGENTS.md` §2 invariants.
|
|
@@ -67,6 +67,25 @@ Weight is one currency: `weight = moves + PASS · unaccountedBytes` where
|
|
|
67
67
|
Cover runs first so a near-zero-cost computed span prunes the rest through the
|
|
68
68
|
same mechanism — not a special case.
|
|
69
69
|
|
|
70
|
+
- **A cheaper bound is looked at first.** Before mechanism `m` first-touches
|
|
71
|
+
anything, every LATER mechanism whose floor grade is strictly below `m`'s runs
|
|
72
|
+
ahead of it (cheapest first); the lowest grade they reach is `bound`, and any
|
|
73
|
+
mechanism floored above `bound` is skipped (`meter.mechanismsBounded`). The
|
|
74
|
+
bound is learnt by calling `floor` with a `worthRunning` that refuses — the
|
|
75
|
+
investment discipline makes that free. The DECISION is the declared order's: a
|
|
76
|
+
run-ahead mechanism bounds the final grade whether or not the declared order
|
|
77
|
+
would have run it (if pruned, the incumbent already sat at or below its
|
|
78
|
+
floor); every candidate above `bound` loses to the winner, and every mechanism
|
|
79
|
+
floored at or below it meets the same run-or-prune decision, so `consider`
|
|
80
|
+
replays the same candidates in declared order. Equal floors are not skipped,
|
|
81
|
+
so an earlier mechanism keeps the tie it would win. Running ahead is never
|
|
82
|
+
extra work: only a mechanism floored at or below `p` can prune `p`, and each
|
|
83
|
+
such mechanism has already run or runs ahead of `p`. Measured on the
|
|
84
|
+
31.7M-node store: a lowercased Persian turn (#83) went from 18.0 s to 1.2 s,
|
|
85
|
+
and #114 from 1.9 s to 0.7 s. In both, a grade-1 recall or prefix answer no
|
|
86
|
+
longer waits behind CAST's climb and weave. Of 42 composition-regime queries,
|
|
87
|
+
none changed its answer.
|
|
88
|
+
|
|
70
89
|
- **Investment discipline.** `worthRunning` is passed _into_ `floor`. A floor
|
|
71
90
|
that would first-touch an expensive shared analysis (`pre.attention()` climb,
|
|
72
91
|
`pre.weave()`, `pre.resonance()`) checks `worthRunning(cheapestBound)` first
|
|
@@ -93,3 +112,5 @@ out so `PASS`-bridged bytes are still charged. `narrowDecision` and
|
|
|
93
112
|
|
|
94
113
|
- `test/01-floor` — floor geometry.
|
|
95
114
|
- `test/04-think` — decider, admissible pruning, investment discipline.
|
|
115
|
+
- `test/153` — run-ahead bounds: the composition market is skipped below CAST's
|
|
116
|
+
floor, and the decision equals a declared-order oracle.
|
|
@@ -47,9 +47,9 @@ conversation's persistent ones (content-keyed, cross-turn).
|
|
|
47
47
|
| Memo | Key | Scope |
|
|
48
48
|
| ------------------- | ----------------------------------------- | -------------------------------------------- |
|
|
49
49
|
| `perceiveMemo` | `perceiveKey(bytes)` (latin1) | response / conversation |
|
|
50
|
-
| `recogniseMemo` | `
|
|
51
|
-
| `climbMemo` | `
|
|
52
|
-
| `canonMemo` | `
|
|
50
|
+
| `recogniseMemo` | `latin1(bytes)` | response / conversation |
|
|
51
|
+
| `climbMemo` | `latin1(bytes)` | response / conversation |
|
|
52
|
+
| `canonMemo` | `latin1(bytes)` | response (when `canon` set) |
|
|
53
53
|
| `_resolvedSubtrees` | `WeakMap<Sema, {id,len}>` (node identity) | response / conversation |
|
|
54
54
|
| `_edgeChoice` | `Map<nodeId, pick>` | response only — **cleared** in `endResponse` |
|
|
55
55
|
| `_gistCache` | `BoundedMap<nodeId, Vec>` 32 MB | **session-lifetime** (not per-response) |
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
`src/meter.ts` is the one computational-usage accounting surface. It counts what
|
|
4
4
|
inference _cost_ so a slow response can be attributed instead of guessed at. The
|
|
5
5
|
rationale says why an answer was chosen; the meter says what it cost to choose
|
|
6
|
-
it. Harness: `
|
|
6
|
+
it. Harness: the public path — `new Mind({ profile: true })`, then
|
|
7
|
+
`mind.lastCost` (`formatReport` / `sumReports`).
|
|
7
8
|
|
|
8
9
|
## Five contracts
|
|
9
10
|
|
|
@@ -48,6 +48,18 @@ full — identical to the unbounded climb. Work is `O(bound)` contexts times loc
|
|
|
48
48
|
structure, never `O(N)`. Container seeding is streamed in `bound`-sized pages
|
|
49
49
|
for the same reason.
|
|
50
50
|
|
|
51
|
+
Refuted tightening: **container fan-out as a hub** — deciding a containment seed
|
|
52
|
+
saturated when its first `containersSlice(bound+1)` page overflows, the reading
|
|
53
|
+
`junction.ts` applies to the same links. It conflates the PLACES a window occurs
|
|
54
|
+
with the CONTEXTS it reaches, and saturation is defined over contexts. Proved on
|
|
55
|
+
`test/49`'s fixture (N = 5, `sqrt(N)` = 3): `fran` sits in 4 containers yet its
|
|
56
|
+
full climb reaches 2 contexts — discriminative — and the rule called it
|
|
57
|
+
saturated, as it did `of f`, `fra`, `is`, `ranc`, `ance`. On the 31.7M-node
|
|
58
|
+
store no such window climbed unsaturated (18 composition queries; those climbs
|
|
59
|
+
were 38% of all visits), because at `sqrt(N)` = 1,560 a full page of containers
|
|
60
|
+
rarely converges on few contexts — but the rule is the same wrong reading at
|
|
61
|
+
both scales. The streamed seed stays.
|
|
62
|
+
|
|
51
63
|
Trace records the first deciding stop as
|
|
52
64
|
`SaturationStop { reason, node, observed, limit }` plus `visited`/`maxDepth`;
|
|
53
65
|
absent when unsaturated or untraced.
|
|
@@ -27,7 +27,23 @@ a row. `has(id)` is `id < 0 || id < _nextId`.
|
|
|
27
27
|
A branch whose kids are all leaves is **flat** — stored as raw bytes in `leaf`
|
|
28
28
|
with an empty `kids` blob as marker (`flatKidsBytes`/`flatBytesKids`). Dedup
|
|
29
29
|
probes hash then verify: `hashOf`→`h`→`LIMIT 1` fetch→byte compare (bloom
|
|
30
|
-
negative filter first).
|
|
30
|
+
negative filter first). `flatBranchMayExist(bytes)` is the filter alone — its
|
|
31
|
+
`false` is exact, its `true` means "look it up" — for a caller that will verify
|
|
32
|
+
anyway: `exactNode` (primitives.ts) refuses a stream whose level-0 segment
|
|
33
|
+
cannot exist before naming any node, so a resolve miss costs hashing.
|
|
34
|
+
`findFlatBranch` memoizes HITS (`_flatKey`, keyed by the bytes themselves) and
|
|
35
|
+
never misses — the filter answers first, so a span that is not stored builds no
|
|
36
|
+
key, while the segments the identity fold names, asked by every span that
|
|
37
|
+
contains them, cost a map hit. `flatSpans(bytes)` returns a prober over ONE
|
|
38
|
+
buffer that answers exactly `findFlatBranch(bytes.subarray(s, e))`. `hashOf` is
|
|
39
|
+
FNV-1a, a left fold, so the prober extends the hash each start was last probed
|
|
40
|
+
at, and keeps one byte-short copy for the edge scan's trimmed retry. A span
|
|
41
|
+
scanner sweeping ends upward pays O(1) per probe instead of O(span).
|
|
42
|
+
Recognition's interior pass was hashing O(n·reach²) bytes: 251,660,406 for one
|
|
43
|
+
response on the 31.7M-node store (`test/153.4`).
|
|
44
|
+
|
|
45
|
+
`leadsSomewhere(id)` — `hasNext || hasHalo` — is the admission predicate's ONE
|
|
46
|
+
raw definition; `traverse.ts` memoises its edge tier per response.
|
|
31
47
|
|
|
32
48
|
`bytes(id)`/`bytesPrefix(id, cap)` are shared with `BoundedMap` caches — callers
|
|
33
49
|
must **never mutate** the returned buffer. `contentLen(id, cap)` walks with
|
|
@@ -43,7 +59,14 @@ window apart. Gists sit in `_pendingGist` (byte-budgeted `BoundedMap`);
|
|
|
43
59
|
`batchSize` batches. Buffers flush on cadence, `commit()`, and close. Halo mass
|
|
44
60
|
re-indexes geometrically (`mass<=4 || powerOfTwo`) and encodes 2-bit quantized.
|
|
45
61
|
Canon index is optional: `canonAdd`/ `canonFind`/`canonCount` over 32-bit
|
|
46
|
-
canonical hashes, caller verifies bytes.
|
|
62
|
+
canonical hashes, caller verifies bytes. The SQLite backend keeps a negative
|
|
63
|
+
filter over the canon hashes too (kept exact on `canonAdd`; the table is never
|
|
64
|
+
deleted from), because recognition and the join probe it once per span and
|
|
65
|
+
almost every answer is "no such key". It is PERSISTED (`canon_bloom`) in the
|
|
66
|
+
same transaction as the canon rows it covers, stamped with that commit's
|
|
67
|
+
`canon.upto`; an open whose meta disagrees with the stamp (rows written without
|
|
68
|
+
it) rebuilds it by one scan of the h column — seconds on a trained store, paid
|
|
69
|
+
once instead of per process (`test/36`).
|
|
47
70
|
|
|
48
71
|
## Containment, batching, LRU
|
|
49
72
|
|