@soulcraft/cor 3.0.14 → 3.0.16

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.
@@ -0,0 +1,48 @@
1
+ /**
2
+ * @module utils/derivedFamilies
3
+ * @description ADR-004 §7 — cor's registered-blob family declarations
4
+ * (adopted 2026-07-13). Each provider declares the artifact families it
5
+ * owns through brainy ≥8.3.0's `registerDerivedFamily` (feature-detected;
6
+ * inert on older adapters). Once declared, the storage layer REFUSES to
7
+ * delete a member (`ProtectedArtifactError` — an in-process GC/sweeper is
8
+ * structurally incapable of removing a load-bearing file), and
9
+ * `checkDerivedFamiliesPresent` names any missing-on-open member (the
10
+ * external-deleter catch).
11
+ *
12
+ * Scope note (deliberate split, per §7): declarations cover
13
+ * KEY-ADDRESSABLE artifacts — members resolve through the same adapter
14
+ * key→path function on both sides, so consistency is by construction.
15
+ * Path-level siblings the native layer writes directly (the vector
16
+ * base's `.slotmap`/`.slotrev` sidecars) are outside the key space; their
17
+ * set-coherence is cor's own `familygen` stamp (the §7 atomic set-swap),
18
+ * not the storage contract. Growing sets use `namespace: true` prefixes.
19
+ *
20
+ * Registration is idempotent (upsert by family name) and runs on every
21
+ * open. A registration failure is LOUD but never blocks an open — the
22
+ * contract is protective, not load-bearing.
23
+ */
24
+ import type { DerivedFamilyDeclaration } from '@soulcraft/brainy';
25
+ /**
26
+ * Declare families on the adapter when it supports the contract. Never
27
+ * throws; failures are loud. Returns how many were registered (0 when the
28
+ * adapter predates the contract — callers may log that once at debug).
29
+ */
30
+ export declare function declareDerivedFamilies(storage: unknown, families: DerivedFamilyDeclaration[]): Promise<number>;
31
+ /** The vector index's key-addressable families. */
32
+ export declare const VECTOR_FAMILIES: DerivedFamilyDeclaration[];
33
+ /** The metadata LSM's families (engine dir + SSTables share the key prefix). */
34
+ export declare const METADATA_FAMILIES: DerivedFamilyDeclaration[];
35
+ /** The column store's family (fully key-addressable — API delete-refusal bites here). */
36
+ export declare const COLUMN_FAMILIES: DerivedFamilyDeclaration[];
37
+ /** The graph index's families (LSM SSTables + verb namespace stores). */
38
+ export declare const GRAPH_FAMILIES: DerivedFamilyDeclaration[];
39
+ /**
40
+ * Owner-sanctioned retirement window (the pattern brainy's
41
+ * ProtectedArtifactError names): unregister the family, run the owner's
42
+ * legitimate delete work, re-register in a finally. The unprotected
43
+ * window is small and self-healing — every provider re-declares its
44
+ * families on init, so even a crash inside the window is repaired at the
45
+ * next open. On adapters without the contract, just runs `fn`.
46
+ */
47
+ export declare function withFamilyRetirement<T>(storage: unknown, family: DerivedFamilyDeclaration, fn: () => Promise<T>): Promise<T>;
48
+ //# sourceMappingURL=derivedFamilies.d.ts.map
@@ -0,0 +1,128 @@
1
+ /**
2
+ * @module utils/derivedFamilies
3
+ * @description ADR-004 §7 — cor's registered-blob family declarations
4
+ * (adopted 2026-07-13). Each provider declares the artifact families it
5
+ * owns through brainy ≥8.3.0's `registerDerivedFamily` (feature-detected;
6
+ * inert on older adapters). Once declared, the storage layer REFUSES to
7
+ * delete a member (`ProtectedArtifactError` — an in-process GC/sweeper is
8
+ * structurally incapable of removing a load-bearing file), and
9
+ * `checkDerivedFamiliesPresent` names any missing-on-open member (the
10
+ * external-deleter catch).
11
+ *
12
+ * Scope note (deliberate split, per §7): declarations cover
13
+ * KEY-ADDRESSABLE artifacts — members resolve through the same adapter
14
+ * key→path function on both sides, so consistency is by construction.
15
+ * Path-level siblings the native layer writes directly (the vector
16
+ * base's `.slotmap`/`.slotrev` sidecars) are outside the key space; their
17
+ * set-coherence is cor's own `familygen` stamp (the §7 atomic set-swap),
18
+ * not the storage contract. Growing sets use `namespace: true` prefixes.
19
+ *
20
+ * Registration is idempotent (upsert by family name) and runs on every
21
+ * open. A registration failure is LOUD but never blocks an open — the
22
+ * contract is protective, not load-bearing.
23
+ */
24
+ import { prodLog } from '@soulcraft/brainy/internals';
25
+ /**
26
+ * Declare families on the adapter when it supports the contract. Never
27
+ * throws; failures are loud. Returns how many were registered (0 when the
28
+ * adapter predates the contract — callers may log that once at debug).
29
+ */
30
+ export async function declareDerivedFamilies(storage, families) {
31
+ const s = storage;
32
+ if (typeof s?.registerDerivedFamily !== 'function')
33
+ return 0;
34
+ let registered = 0;
35
+ for (const family of families) {
36
+ try {
37
+ await s.registerDerivedFamily(family);
38
+ registered++;
39
+ }
40
+ catch (error) {
41
+ prodLog.error(`[cor] registerDerivedFamily('${family.name}') FAILED — its members ` +
42
+ `are NOT delete-protected this session (opens are unaffected):`, error);
43
+ }
44
+ }
45
+ return registered;
46
+ }
47
+ /** The vector index's key-addressable families. */
48
+ export const VECTOR_FAMILIES = [
49
+ {
50
+ name: 'vector-base',
51
+ members: ['_system/vector-index/main.dkann'],
52
+ rebuildable: true,
53
+ },
54
+ {
55
+ name: 'vector-segments',
56
+ members: ['_system/vector-index/seg-'],
57
+ namespace: true,
58
+ rebuildable: true,
59
+ },
60
+ ];
61
+ /** The metadata LSM's families (engine dir + SSTables share the key prefix). */
62
+ export const METADATA_FAMILIES = [
63
+ {
64
+ name: 'metadata-lsm',
65
+ members: ['_metadata'],
66
+ namespace: true,
67
+ rebuildable: true,
68
+ },
69
+ {
70
+ name: 'id-mapper',
71
+ members: ['_id_mapper/'],
72
+ namespace: true,
73
+ rebuildable: true,
74
+ },
75
+ ];
76
+ /** The column store's family (fully key-addressable — API delete-refusal bites here). */
77
+ export const COLUMN_FAMILIES = [
78
+ {
79
+ name: 'column-index',
80
+ members: ['_column_index/'],
81
+ namespace: true,
82
+ rebuildable: true,
83
+ },
84
+ ];
85
+ /** The graph index's families (LSM SSTables + verb namespace stores). */
86
+ export const GRAPH_FAMILIES = [
87
+ {
88
+ name: 'graph-lsm',
89
+ members: ['graph-lsm/'],
90
+ namespace: true,
91
+ rebuildable: true,
92
+ },
93
+ {
94
+ name: 'graph-verb-namespace',
95
+ members: ['_graph_verb_ns/'],
96
+ namespace: true,
97
+ rebuildable: true,
98
+ },
99
+ ];
100
+ /**
101
+ * Owner-sanctioned retirement window (the pattern brainy's
102
+ * ProtectedArtifactError names): unregister the family, run the owner's
103
+ * legitimate delete work, re-register in a finally. The unprotected
104
+ * window is small and self-healing — every provider re-declares its
105
+ * families on init, so even a crash inside the window is repaired at the
106
+ * next open. On adapters without the contract, just runs `fn`.
107
+ */
108
+ export async function withFamilyRetirement(storage, family, fn) {
109
+ const s = storage;
110
+ if (typeof s?.unregisterDerivedFamily !== 'function' ||
111
+ typeof s?.registerDerivedFamily !== 'function') {
112
+ return fn();
113
+ }
114
+ await s.unregisterDerivedFamily(family.name);
115
+ try {
116
+ return await fn();
117
+ }
118
+ finally {
119
+ try {
120
+ await s.registerDerivedFamily(family);
121
+ }
122
+ catch (error) {
123
+ prodLog.error(`[cor] re-register of family '${family.name}' after retirement ` +
124
+ `FAILED — protection resumes at the next open:`, error);
125
+ }
126
+ }
127
+ }
128
+ //# sourceMappingURL=derivedFamilies.js.map
@@ -0,0 +1,29 @@
1
+ /**
2
+ * @module utils/invariantReport
3
+ * @description Shared composer for the ADR-004 §6 `validateInvariants()`
4
+ * hook (adopted 2026-07-13, decision `adr-004-write-index-spine-adoption`).
5
+ * Every cor provider builds its report through this so the contract holds
6
+ * uniformly: the hook NEVER throws (a thrown check is surfaced as a failing
7
+ * invariant naming the throw — never an exception, never swallowed), stays
8
+ * bounded (checks are residency + O(1) counts only; the composer measures
9
+ * and reports duration), and failures carry named, numbered detail.
10
+ *
11
+ * Types are imported from brainy 8.3.0's published surface so both engines
12
+ * share one wire shape (`ProviderInvariantReport` / `InvariantResult` /
13
+ * `InvariantHeal` — brainy's `validateIndexConsistency` feature-detects the
14
+ * hook and aggregates these verbatim; `repairIndex` maps `heal: 'rebuild'`
15
+ * to the provider's own rebuild).
16
+ */
17
+ import type { InvariantResult, ProviderInvariantReport } from '@soulcraft/brainy';
18
+ /** One invariant check: returns its result, sync or async. A throw is a
19
+ * contract violation the composer converts into a failing invariant. */
20
+ export type InvariantCheck = () => InvariantResult | Promise<InvariantResult>;
21
+ /**
22
+ * Run every check, never throw, stamp timing. A check that throws becomes
23
+ * `holds: false` with `heal: 'none'` and detail naming the throw — the
24
+ * never-throws contract surfaced as unhealthy data rather than an exception
25
+ * (and `heal: 'none'` so a flaky probe can never trigger a spurious
26
+ * rebuild; visibility without overreaction).
27
+ */
28
+ export declare function composeInvariantReport(provider: string, serving: () => boolean, checks: InvariantCheck[]): Promise<ProviderInvariantReport>;
29
+ //# sourceMappingURL=invariantReport.d.ts.map
@@ -0,0 +1,62 @@
1
+ /**
2
+ * @module utils/invariantReport
3
+ * @description Shared composer for the ADR-004 §6 `validateInvariants()`
4
+ * hook (adopted 2026-07-13, decision `adr-004-write-index-spine-adoption`).
5
+ * Every cor provider builds its report through this so the contract holds
6
+ * uniformly: the hook NEVER throws (a thrown check is surfaced as a failing
7
+ * invariant naming the throw — never an exception, never swallowed), stays
8
+ * bounded (checks are residency + O(1) counts only; the composer measures
9
+ * and reports duration), and failures carry named, numbered detail.
10
+ *
11
+ * Types are imported from brainy 8.3.0's published surface so both engines
12
+ * share one wire shape (`ProviderInvariantReport` / `InvariantResult` /
13
+ * `InvariantHeal` — brainy's `validateIndexConsistency` feature-detects the
14
+ * hook and aggregates these verbatim; `repairIndex` maps `heal: 'rebuild'`
15
+ * to the provider's own rebuild).
16
+ */
17
+ /**
18
+ * Run every check, never throw, stamp timing. A check that throws becomes
19
+ * `holds: false` with `heal: 'none'` and detail naming the throw — the
20
+ * never-throws contract surfaced as unhealthy data rather than an exception
21
+ * (and `heal: 'none'` so a flaky probe can never trigger a spurious
22
+ * rebuild; visibility without overreaction).
23
+ */
24
+ export async function composeInvariantReport(provider, serving, checks) {
25
+ const startedAt = Date.now();
26
+ const invariants = [];
27
+ for (const check of checks) {
28
+ try {
29
+ invariants.push(await check());
30
+ }
31
+ catch (error) {
32
+ invariants.push({
33
+ name: 'check-integrity',
34
+ holds: false,
35
+ detail: `an invariant check THREW (contract violation — checks must ` +
36
+ `return failures as data): ${String(error)}`,
37
+ heal: 'none',
38
+ });
39
+ }
40
+ }
41
+ let servingNow = false;
42
+ try {
43
+ servingNow = serving();
44
+ }
45
+ catch (error) {
46
+ invariants.push({
47
+ name: 'serving-probe',
48
+ holds: false,
49
+ detail: `isReady() itself threw: ${String(error)}`,
50
+ heal: 'none',
51
+ });
52
+ }
53
+ return {
54
+ provider,
55
+ healthy: invariants.every((i) => i.holds),
56
+ serving: servingNow,
57
+ invariants,
58
+ checkedAt: startedAt,
59
+ durationMs: Date.now() - startedAt,
60
+ };
61
+ }
62
+ //# sourceMappingURL=invariantReport.js.map
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @module version
3
+ * @description The package version as a CODE constant — deliberately not a
4
+ * `package.json` read. Consumers that bundle cor (bun-compiled services like
5
+ * memory) inline this literal at build time, so the version a process LOGS
6
+ * is provably the version its bundle CONTAINS. A runtime `package.json`
7
+ * lookup would report whatever file happens to sit near the bundle — the
8
+ * exact ambiguity behind the 2026-07-13 phantom-deploy incident, where a
9
+ * "fresh" bundle silently carried a stale engine and no on-box check could
10
+ * tell. `scripts/release.sh` bumps this in lockstep with `package.json`;
11
+ * `check:brainy`-style drift between the two fails the release.
12
+ */
13
+ /** The @soulcraft/cor version this build was cut from. */
14
+ export declare const COR_VERSION = "3.0.16";
15
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @module version
3
+ * @description The package version as a CODE constant — deliberately not a
4
+ * `package.json` read. Consumers that bundle cor (bun-compiled services like
5
+ * memory) inline this literal at build time, so the version a process LOGS
6
+ * is provably the version its bundle CONTAINS. A runtime `package.json`
7
+ * lookup would report whatever file happens to sit near the bundle — the
8
+ * exact ambiguity behind the 2026-07-13 phantom-deploy incident, where a
9
+ * "fresh" bundle silently carried a stale engine and no on-box check could
10
+ * tell. `scripts/release.sh` bumps this in lockstep with `package.json`;
11
+ * `check:brainy`-style drift between the two fails the release.
12
+ */
13
+ /** The @soulcraft/cor version this build was cut from. */
14
+ export const COR_VERSION = '3.0.16';
15
+ //# sourceMappingURL=version.js.map
Binary file
package/native/index.d.ts CHANGED
@@ -364,7 +364,6 @@ export declare class NativeColumnStore {
364
364
  distinctValues(field: string): Array<string>
365
365
  }
366
366
 
367
- /** Napi-exposed DiskANN index. */
368
367
  export declare class NativeDiskAnn {
369
368
  /** Construct via static factories. */
370
369
  constructor()
@@ -1751,6 +1750,20 @@ export declare class NativeMetadataIndex {
1751
1750
  * brains; preferred by brainy 8.0 consumers.
1752
1751
  */
1753
1752
  uuidToIntBig(uuid: string): bigint | null
1753
+ /**
1754
+ * Resolve an entity's integer id, ASSIGNING a fresh one through the
1755
+ * canonical allocator when unmapped — the same allocator
1756
+ * `add_to_index` uses, so a later `add_to_index` for this UUID
1757
+ * reuses the id and the assignment persists through the mapper's
1758
+ * own durability (delta log). Exists for the boot-heal vector
1759
+ * rebuild (CORTEX-RESTART-STRAND, 2026-07-13): a canonical entity
1760
+ * whose index ops were lost (canonical committed, postings absent)
1761
+ * has no int at cold-rebuild time — the rebuild must be able to
1762
+ * mint one instead of aborting the whole heal. The entity's missing
1763
+ * METADATA postings stay visible to `validateInvariants()`'s
1764
+ * posted-count-floor check; this method never masks that gap.
1765
+ */
1766
+ getOrAssignInt(uuid: string): bigint
1754
1767
  /**
1755
1768
  * Resolve a UUID from an entity's integer id. Backs `getIdMapper().getUuid`
1756
1769
  * for the `orderBy` path. O(1).
@@ -2614,6 +2627,15 @@ export declare function euclideanDistance(a: Array<number>, b: Array<number>): n
2614
2627
  /** Batch euclidean distance: compute distances from a query to multiple vectors. */
2615
2628
  export declare function euclideanDistanceBatch(query: Array<number>, vectors: Array<Array<number>>): Array<number>
2616
2629
 
2630
+ /**
2631
+ * Napi-exposed DiskANN index.
2632
+ * ADR-004 §7 capability probe: TRUE on binaries whose publish path
2633
+ * writes the `main.familygen` stamp and swaps the vector family
2634
+ * atomically (3.0.16+). TS code and the test suite gate stamp-dependent
2635
+ * behavior on this instead of guessing from version strings.
2636
+ */
2637
+ export declare function familygenSupported(): boolean
2638
+
2617
2639
  /**
2618
2640
  * Outcome of raising the open-file limit. Field names cross to JS as
2619
2641
  * camelCase (`softBefore`, `softAfter`, `hard`, `raised`).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@soulcraft/cor",
3
- "version": "3.0.14",
3
+ "version": "3.0.16",
4
4
  "description": "Native Rust acceleration for Brainy — SIMD distance, vector quantization, zero-copy mmap, native embeddings. Free tier for storage, Pro license for compute acceleration.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -82,7 +82,7 @@
82
82
  },
83
83
  "devDependencies": {
84
84
  "@napi-rs/cli": "^3.0.0",
85
- "@soulcraft/brainy": "8.2.6",
85
+ "@soulcraft/brainy": "8.3.0",
86
86
  "@types/node": "^22.0.0",
87
87
  "pg": "^8.21.0",
88
88
  "tsx": "^4.21.0",