@soulcraft/cor 3.0.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/LICENSE +16 -0
  2. package/README.md +328 -0
  3. package/dist/aggregation/NativeAggregationEngine.d.ts +118 -0
  4. package/dist/aggregation/NativeAggregationEngine.js +186 -0
  5. package/dist/cli.d.ts +12 -0
  6. package/dist/cli.js +236 -0
  7. package/dist/graph/GraphAccelerationAdapter.d.ts +153 -0
  8. package/dist/graph/GraphAccelerationAdapter.js +326 -0
  9. package/dist/graph/NativeGraphAdjacencyIndex.d.ts +286 -0
  10. package/dist/graph/NativeGraphAdjacencyIndex.js +944 -0
  11. package/dist/hnsw/AdaptiveDiskAnnModeSelector.d.ts +187 -0
  12. package/dist/hnsw/AdaptiveDiskAnnModeSelector.js +313 -0
  13. package/dist/hnsw/NativeDiskAnnWrapper.d.ts +489 -0
  14. package/dist/hnsw/NativeDiskAnnWrapper.js +1456 -0
  15. package/dist/index.d.ts +28 -0
  16. package/dist/index.js +29 -0
  17. package/dist/legacyLayoutGuard.d.ts +93 -0
  18. package/dist/legacyLayoutGuard.js +237 -0
  19. package/dist/license/constants.d.ts +30 -0
  20. package/dist/license/constants.js +30 -0
  21. package/dist/license/onlineValidator.d.ts +43 -0
  22. package/dist/license/onlineValidator.js +225 -0
  23. package/dist/license/types.d.ts +39 -0
  24. package/dist/license/types.js +5 -0
  25. package/dist/license.d.ts +64 -0
  26. package/dist/license.js +165 -0
  27. package/dist/migration/MigrationCoordinator.d.ts +171 -0
  28. package/dist/migration/MigrationCoordinator.js +249 -0
  29. package/dist/migration/indexEpochGuard.d.ts +163 -0
  30. package/dist/migration/indexEpochGuard.js +202 -0
  31. package/dist/native/NativeEmbeddingEngine.d.ts +79 -0
  32. package/dist/native/NativeEmbeddingEngine.js +318 -0
  33. package/dist/native/NativeRoaringBitmap32.d.ts +114 -0
  34. package/dist/native/NativeRoaringBitmap32.js +221 -0
  35. package/dist/native/ffi.d.ts +20 -0
  36. package/dist/native/ffi.js +48 -0
  37. package/dist/native/idMapperTestSupport.d.ts +67 -0
  38. package/dist/native/idMapperTestSupport.js +112 -0
  39. package/dist/native/index.d.ts +49 -0
  40. package/dist/native/index.js +87 -0
  41. package/dist/native/napi.d.ts +21 -0
  42. package/dist/native/napi.js +88 -0
  43. package/dist/native/types.d.ts +1298 -0
  44. package/dist/native/types.js +16 -0
  45. package/dist/plugin.d.ts +50 -0
  46. package/dist/plugin.js +388 -0
  47. package/dist/providerContracts.d.ts +277 -0
  48. package/dist/providerContracts.js +38 -0
  49. package/dist/resource/OsMemoryProbe.d.ts +175 -0
  50. package/dist/resource/OsMemoryProbe.js +206 -0
  51. package/dist/resource/ResourceManager.d.ts +491 -0
  52. package/dist/resource/ResourceManager.js +960 -0
  53. package/dist/utils/ColumnManifest.d.ts +97 -0
  54. package/dist/utils/ColumnManifest.js +129 -0
  55. package/dist/utils/NativeColumnStore.d.ts +284 -0
  56. package/dist/utils/NativeColumnStore.js +685 -0
  57. package/dist/utils/NativeMetadataIndex.d.ts +882 -0
  58. package/dist/utils/NativeMetadataIndex.js +2631 -0
  59. package/dist/utils/NativeUnifiedCache.d.ts +87 -0
  60. package/dist/utils/NativeUnifiedCache.js +273 -0
  61. package/dist/utils/binaryIdMapperFactory.d.ts +59 -0
  62. package/dist/utils/binaryIdMapperFactory.js +94 -0
  63. package/dist/utils/collation.d.ts +30 -0
  64. package/dist/utils/collation.js +40 -0
  65. package/dist/utils/columnStoreTypes.d.ts +161 -0
  66. package/dist/utils/columnStoreTypes.js +29 -0
  67. package/dist/utils/nativeBinaryEntityIdMapper.d.ts +211 -0
  68. package/dist/utils/nativeBinaryEntityIdMapper.js +381 -0
  69. package/dist/utils/nativeEntityIdMapper.d.ts +111 -0
  70. package/dist/utils/nativeEntityIdMapper.js +170 -0
  71. package/docs/ADR-002-diskann-100-percent-rust.md +294 -0
  72. package/docs/ADR-003-semantic-time-travel.md +100 -0
  73. package/docs/aggregation.md +251 -0
  74. package/docs/comparison.md +162 -0
  75. package/docs/deployment-limits.md +87 -0
  76. package/docs/diskann.md +184 -0
  77. package/docs/migration-3.0.md +396 -0
  78. package/docs/performance-budget.md +274 -0
  79. package/docs/performance.md +117 -0
  80. package/docs/scaling.md +439 -0
  81. package/docs/snapshot-safety.md +246 -0
  82. package/docs/u64-id-space.md +214 -0
  83. package/docs/verification-report.md +670 -0
  84. package/native/brainy-native.node +0 -0
  85. package/native/index.d.ts +3916 -0
  86. package/package.json +92 -0
  87. package/scripts/migrate-cortex-2x-to-3x.mjs +970 -0
@@ -0,0 +1,277 @@
1
+ /**
2
+ * @module providerContracts
3
+ * @description Cor-local copies of brainy's provider contracts — the EXACT
4
+ * method/property surface brainy calls on each native provider cor registers.
5
+ *
6
+ * Cor's wrappers `implements` these, so dropping or drifting a member brainy
7
+ * depends on becomes a compile error here (not a runtime crash when the code
8
+ * path first runs with cor active). This is the compile-time half of the
9
+ * provider-parity guarantee; `scripts/check-brainy-compat.mjs` is the runtime
10
+ * half (it instantiates each provider and asserts the same surface).
11
+ *
12
+ * ## Why a local copy
13
+ *
14
+ * These interfaces are exported from brainy's `@soulcraft/brainy/plugin`
15
+ * entrypoint, but only from the brainy release that ships alongside cor
16
+ * 2.3.0 — they are NOT in published brainy 7.24.0, which cor currently
17
+ * builds against. So cor keeps a local copy (exactly as it already does for
18
+ * `ColumnStoreProvider` and `EntityIdMapperLike` in {@link module:utils/columnStoreTypes}
19
+ * and for the collation routine — see `docs/ADR-001`). The copies MUST stay in
20
+ * lockstep with brainy's `src/plugin.ts`. When cor bumps its brainy
21
+ * dependency to the release that exports them, replace this file's interface
22
+ * bodies with re-exports from `@soulcraft/brainy/plugin`:
23
+ *
24
+ * ```ts
25
+ * export type {
26
+ * MetadataIndexProvider, GraphIndexProvider, HnswProvider,
27
+ * EntityIdMapperProvider, CacheProvider,
28
+ * } from '@soulcraft/brainy/plugin'
29
+ * ```
30
+ *
31
+ * `AggregationProvider` is intentionally absent here: it is already a published
32
+ * export of brainy 7.24.0, so `NativeAggregationProvider` implements it directly
33
+ * from `@soulcraft/brainy`. `ColumnStoreProvider` likewise lives in
34
+ * {@link module:utils/columnStoreTypes} (its bitmap types reference cor's
35
+ * binary-compatible `RoaringBitmap32`).
36
+ */
37
+ import type { Vector, VectorDocument, GraphVerb, NounType, VerbType } from '@soulcraft/brainy';
38
+ import type { ColumnStoreProvider } from './utils/columnStoreTypes.js';
39
+ /**
40
+ * @description The `'metadataIndex'` provider contract — the surface brainy
41
+ * calls via `this.metadataIndex.*` (plus the transactional add/remove
42
+ * operations). Mirror of brainy's `MetadataIndexProvider`.
43
+ */
44
+ export interface MetadataIndexProvider {
45
+ init(): Promise<void>;
46
+ flush(): Promise<void>;
47
+ rebuild(): Promise<void>;
48
+ addToIndex(id: string, entityOrMetadata: any, skipFlush?: boolean, deferWrites?: boolean): Promise<void>;
49
+ removeFromIndex(id: string, metadata?: any): Promise<void>;
50
+ getIds(field: string, value: any): Promise<string[]>;
51
+ getIdsForFilter(filter: any, opts?: {
52
+ limit?: number;
53
+ offset?: number;
54
+ }): Promise<string[]>;
55
+ getIdsForTextQuery(query: string): Promise<Array<{
56
+ id: string;
57
+ matchCount: number;
58
+ }>>;
59
+ getSortedIdsForFilter(filter: any, orderBy: string, order?: 'asc' | 'desc', topK?: number): Promise<string[]>;
60
+ getFilterValues(field: string): Promise<string[]>;
61
+ getFilterFields(): Promise<string[]>;
62
+ getFieldValueForEntity(entityId: string, field: string): Promise<any>;
63
+ getFieldsForType(nounType: NounType): Promise<Array<{
64
+ field: string;
65
+ affinity: number;
66
+ occurrences: number;
67
+ totalEntities: number;
68
+ }>>;
69
+ getFieldStatistics(): Promise<Map<string, unknown>>;
70
+ getFieldsWithCardinality(): Promise<Array<{
71
+ field: string;
72
+ cardinality: number;
73
+ distribution: string;
74
+ }>>;
75
+ getOptimalQueryPlan(filters: Record<string, any>): Promise<unknown>;
76
+ /** Report which index path a `where` clause on `field` will hit (drives `brain.explain()`). */
77
+ explainField(field: string): Promise<{
78
+ path: 'column-store' | 'sparse-chunked' | 'none';
79
+ notes?: string;
80
+ }>;
81
+ getCountForCriteria(field: string, value: any): Promise<number>;
82
+ getEntityCountByType(type: string): number;
83
+ getEntityCountByTypeEnum(type: NounType): number;
84
+ getTotalEntityCount(): number;
85
+ getAllEntityCounts(): Map<string, number>;
86
+ getTopNounTypes(n: number): NounType[];
87
+ getTopVerbTypes(n: number): VerbType[];
88
+ getAllNounTypeCounts(): Map<NounType, number>;
89
+ getAllVerbTypeCounts(): Map<VerbType, number>;
90
+ getAllVFSEntityCounts(): Promise<Map<string, number>>;
91
+ detectAndRepairCorruption(): Promise<void>;
92
+ validateConsistency(): Promise<{
93
+ healthy: boolean;
94
+ avgEntriesPerEntity: number;
95
+ entityCount: number;
96
+ indexEntryCount: number;
97
+ recommendation: string | null;
98
+ }>;
99
+ /**
100
+ * O(1)-ish cross-bucket consistency probe. Brainy rc.6+ calls this ONCE on
101
+ * the first read; on `false` it runs `detectAndRepairCorruption()`. Returns
102
+ * `true` if healthy (or indeterminate), `false` if a cross-bucket phantom is
103
+ * sampled. Best-effort — never throws into the read path.
104
+ */
105
+ probeConsistency(): Promise<boolean>;
106
+ tokenize(text: string): string[];
107
+ extractTextContent(data: any): string;
108
+ getStats(): Promise<{
109
+ totalEntries: number;
110
+ totalIds: number;
111
+ fieldsIndexed: string[];
112
+ lastRebuild: number;
113
+ indexSize: number;
114
+ }>;
115
+ /** The shared UUID ↔ int mapper. Brainy reads `.getUuid(intId)` off the result. */
116
+ getIdMapper(): {
117
+ getUuid(intId: number): string | undefined;
118
+ };
119
+ /** The column store the coordinator delegates `where`/`orderBy` to. */
120
+ readonly columnStore: ColumnStoreProvider;
121
+ }
122
+ /**
123
+ * @description The `'graphIndex'` provider contract — the surface brainy calls
124
+ * via `this.graphIndex.*` (some optional-chained). Mirror of brainy's
125
+ * `GraphIndexProvider`.
126
+ *
127
+ * **Cor 3.0 Piece D**: entity ids cross as `bigint` (the canonical u64
128
+ * from brainy's `BinaryIdMapper`). Verb-ids likewise cross as `bigint`
129
+ * (the verb-int interned via cor's `verb_id_namespace`). Brainy 8.0
130
+ * owns UUID ↔ int conversion on its side via the same `BinaryIdMapper`
131
+ * it already maintains. The legacy string-id surface is retired —
132
+ * brainy 7.x consumers will not work against this contract.
133
+ */
134
+ export interface GraphIndexProvider {
135
+ /** `false` until the index has loaded; brainy probes this before fast paths. */
136
+ readonly isInitialized: boolean;
137
+ /**
138
+ * Eagerly cold-load the durable graph (the four u64 LSM trees) from
139
+ * persistence. Brainy 8.0 (#36) awaits this right after
140
+ * `metadataIndex.init()` and BEFORE consulting {@link isReady}, so the
141
+ * rebuild gate reads an honest readiness signal. Idempotent and a no-op
142
+ * for an in-memory (no `persistence_dir`) index. Mirrors
143
+ * {@link MetadataIndexProvider.init}.
144
+ */
145
+ init(): Promise<void>;
146
+ /**
147
+ * Whether the graph's edges are loaded and queryable WITHOUT a rebuild —
148
+ * brainy's rebuild gate (#36). `true` once the durable cold-load restored
149
+ * the adjacency (so brainy SKIPS its O(E) rebuild-from-storage), or while
150
+ * live edges sit in a memtable. Edges-loaded semantics ONLY — never gated
151
+ * on the verb-id membership walk. Synchronous (no await).
152
+ */
153
+ isReady(): boolean;
154
+ getNeighbors(id: bigint, optionsOrDirection?: {
155
+ direction?: 'in' | 'out' | 'both';
156
+ limit?: number;
157
+ offset?: number;
158
+ } | 'in' | 'out' | 'both'): Promise<bigint[]>;
159
+ getVerbIdsBySource(sourceInt: bigint, options?: {
160
+ limit?: number;
161
+ offset?: number;
162
+ }): Promise<bigint[]>;
163
+ getVerbIdsByTarget(targetInt: bigint, options?: {
164
+ limit?: number;
165
+ offset?: number;
166
+ }): Promise<bigint[]>;
167
+ /** Resolve interned verb ints back to verb-id strings (null per missing int).
168
+ * brainy hard-calls this to hydrate edge verb-ids; mirrored here so the
169
+ * `implements` guard catches any future drift on it. (#79 cluster C.) */
170
+ verbIntsToIds(verbInts: bigint[]): Promise<(string | null)[]>;
171
+ getVerbsBatchCached(verbIds: string[]): Promise<Map<string, GraphVerb>>;
172
+ rebuild(): Promise<void>;
173
+ flush(): Promise<void>;
174
+ close(): Promise<void>;
175
+ size(): number;
176
+ getStats(): {
177
+ totalRelationships: number;
178
+ sourceNodes: number;
179
+ targetNodes: number;
180
+ memoryUsage: number;
181
+ lastRebuild: number;
182
+ rebuildTime: number;
183
+ };
184
+ getRelationshipStats(): {
185
+ totalRelationships: number;
186
+ relationshipsByType: Record<string, number>;
187
+ uniqueSourceNodes: number;
188
+ uniqueTargetNodes: number;
189
+ totalNodes: number;
190
+ };
191
+ getRelationshipCountByType(type: string): number;
192
+ getTotalRelationshipCount(): number;
193
+ getAllRelationshipCounts(): Map<string, number>;
194
+ }
195
+ /**
196
+ * @description The object returned by the `'vector'` provider factory
197
+ * — the surface brainy hard-calls via `this.index.*` plus the
198
+ * transactional add/remove operations. Mirror of brainy 8.0's
199
+ * `VectorIndexProvider`.
200
+ *
201
+ * Cor's implementation is [[`NativeDiskAnnWrapper`]] (Adaptive
202
+ * DiskANN). Brainy 8.0 keeps its own pure-JS HNSW for the standalone
203
+ * open-source path (~10 M entities) — the contract name is shared
204
+ * vocabulary so brainy can swap implementations transparently.
205
+ *
206
+ * `enableCOW`, `getItem`, and `setPersistMode` are intentionally
207
+ * absent: brainy feature-detects each (`typeof x === 'function'`),
208
+ * so they are optional, not part of the required contract.
209
+ */
210
+ export interface VectorIndexProvider {
211
+ addItem(item: VectorDocument): Promise<string>;
212
+ removeItem(id: string): Promise<boolean>;
213
+ search(queryVector: Vector, k?: number, filter?: (id: string) => Promise<boolean>, options?: {
214
+ rerank?: {
215
+ multiplier: number;
216
+ };
217
+ candidateIds?: string[];
218
+ /**
219
+ * **Predicate pushdown (#10).** The metadata∩graph universe (entity
220
+ * UUIDs) brainy's `find()` has already computed for this query. When
221
+ * supplied and selective, cor pushes it INTO the native beam walk
222
+ * (collect only allowed slots, walk wider) instead of post-filtering —
223
+ * far higher recall on selective filters. brainy feature-detects this:
224
+ * passing `allowedIds` is optional and a provider may ignore it (the
225
+ * pure-JS path falls back to `filter`). Coordinate the matching
226
+ * addition to brainy 8.0's `VectorIndexProvider.search` contract +
227
+ * `find()` wiring via PLATFORM-HANDOFF (CTX-PUSHDOWN-ALLOWEDIDS).
228
+ */
229
+ allowedIds?: ReadonlySet<string>;
230
+ }): Promise<Array<[string, number]>>;
231
+ size(): number;
232
+ clear(): void;
233
+ rebuild(options?: any): Promise<void>;
234
+ flush(): Promise<number>;
235
+ getPersistMode(): 'immediate' | 'deferred';
236
+ }
237
+ /**
238
+ * @description The `'entityIdMapper'` provider contract — a drop-in for brainy's
239
+ * `EntityIdMapper`. Injected into brainy's TypeScript `MetadataIndexManager`
240
+ * when a native metadata index is not also registered; that coordinator calls
241
+ * this full surface (incl. `getAllIntIds`, the all-ids universe brainy uses for
242
+ * negation / `exists:false` filters). Mirror of brainy's `EntityIdMapperProvider`.
243
+ */
244
+ export interface EntityIdMapperProvider {
245
+ init(): Promise<void>;
246
+ getOrAssign(uuid: string): number;
247
+ getUuid(intId: number): string | undefined;
248
+ getInt(uuid: string): number | undefined;
249
+ remove(uuid: string): boolean;
250
+ flush(): Promise<void>;
251
+ clear(): Promise<void>;
252
+ getAllIntIds(): number[];
253
+ intsIterableToUuids(ints: Iterable<number>): string[];
254
+ readonly size: number;
255
+ }
256
+ /**
257
+ * @description Vector-index cache category union. Four hot working-
258
+ * set slices brainy + cor coordinate cache budget across:
259
+ * `'vectors'` (graph hops + PQ codes pages), `'metadata'` (LSM block
260
+ * cache), `'embedding'` (embedding model cache), and `'other'`
261
+ * (catch-all).
262
+ */
263
+ export type CacheCategory = 'vectors' | 'metadata' | 'embedding' | 'other';
264
+ /**
265
+ * @description The `'cache'` provider contract — a drop-in for
266
+ * brainy's `UnifiedCache`. Brainy installs it as the global cache
267
+ * (`setGlobalCache`) and calls this surface via `getGlobalCache()`.
268
+ * Mirror of brainy's `CacheProvider`.
269
+ */
270
+ export interface CacheProvider {
271
+ getSync(key: string): any | undefined;
272
+ set(key: string, data: any, type: CacheCategory, size: number, rebuildCost?: number): void;
273
+ delete(key: string): boolean;
274
+ deleteByPrefix(prefix: string): number;
275
+ clear(type?: CacheCategory): void;
276
+ }
277
+ //# sourceMappingURL=providerContracts.d.ts.map
@@ -0,0 +1,38 @@
1
+ /**
2
+ * @module providerContracts
3
+ * @description Cor-local copies of brainy's provider contracts — the EXACT
4
+ * method/property surface brainy calls on each native provider cor registers.
5
+ *
6
+ * Cor's wrappers `implements` these, so dropping or drifting a member brainy
7
+ * depends on becomes a compile error here (not a runtime crash when the code
8
+ * path first runs with cor active). This is the compile-time half of the
9
+ * provider-parity guarantee; `scripts/check-brainy-compat.mjs` is the runtime
10
+ * half (it instantiates each provider and asserts the same surface).
11
+ *
12
+ * ## Why a local copy
13
+ *
14
+ * These interfaces are exported from brainy's `@soulcraft/brainy/plugin`
15
+ * entrypoint, but only from the brainy release that ships alongside cor
16
+ * 2.3.0 — they are NOT in published brainy 7.24.0, which cor currently
17
+ * builds against. So cor keeps a local copy (exactly as it already does for
18
+ * `ColumnStoreProvider` and `EntityIdMapperLike` in {@link module:utils/columnStoreTypes}
19
+ * and for the collation routine — see `docs/ADR-001`). The copies MUST stay in
20
+ * lockstep with brainy's `src/plugin.ts`. When cor bumps its brainy
21
+ * dependency to the release that exports them, replace this file's interface
22
+ * bodies with re-exports from `@soulcraft/brainy/plugin`:
23
+ *
24
+ * ```ts
25
+ * export type {
26
+ * MetadataIndexProvider, GraphIndexProvider, HnswProvider,
27
+ * EntityIdMapperProvider, CacheProvider,
28
+ * } from '@soulcraft/brainy/plugin'
29
+ * ```
30
+ *
31
+ * `AggregationProvider` is intentionally absent here: it is already a published
32
+ * export of brainy 7.24.0, so `NativeAggregationProvider` implements it directly
33
+ * from `@soulcraft/brainy`. `ColumnStoreProvider` likewise lives in
34
+ * {@link module:utils/columnStoreTypes} (its bitmap types reference cor's
35
+ * binary-compatible `RoaringBitmap32`).
36
+ */
37
+ export {};
38
+ //# sourceMappingURL=providerContracts.js.map
@@ -0,0 +1,175 @@
1
+ /**
2
+ * @module resource/OsMemoryProbe
3
+ * @description OS-level memory observer for the cor 3.0 **Adaptive
4
+ * DiskANN** mode selector (Piece J of the cor 3.0 plan).
5
+ *
6
+ * The {@link ResourceManager} already observes the V8 heap and a
7
+ * coarse system-RSS pressure ratio (Piece 8). What it didn't have
8
+ * was a read on the kernel's `MemAvailable` figure — the metric the
9
+ * Linux kernel computes as "how much physical RAM can a new
10
+ * allocation claim without swapping," factoring in reclaimable page
11
+ * cache and slab. That's the right signal for the adaptive selector
12
+ * to pick a DiskANN open mode in multi-tenant scenarios where a
13
+ * shared box runs many brainy+cor instances: each instance's
14
+ * `os.freemem()` undercounts available memory (it reports MemFree,
15
+ * not MemAvailable), so a naïve `freemem`-based check would push
16
+ * the selector toward OnDisk hints even when there's plenty of
17
+ * reclaimable cache available.
18
+ *
19
+ * ## Surface
20
+ *
21
+ * - {@link parseMeminfo} — pure parser; fixture-friendly.
22
+ * - {@link OsMemoryProbe} — readers + caching wrapper. Dependency-
23
+ * injected so tests can simulate Linux on macOS and exercise the
24
+ * `MemAvailable` missing branch without touching the real
25
+ * `/proc/meminfo`.
26
+ *
27
+ * ## Why a cache
28
+ *
29
+ * `/proc/meminfo` reads cost ~10 μs of syscall time — not free, but
30
+ * also not worth re-reading on every single call. The 250 ms cache
31
+ * is comfortably below the 5 s pressure-tick cadence and the 30 s
32
+ * rebalance cadence the ResourceManager already runs, so any
33
+ * meaningful pressure event lands on a fresh read.
34
+ *
35
+ * ## Non-Linux fallback
36
+ *
37
+ * On macOS and Windows there is no `/proc/meminfo`. The probe falls
38
+ * back to `os.totalmem()` + `os.freemem()` and marks the snapshot
39
+ * `source: 'os-fallback'` so callers can degrade gracefully (the
40
+ * adaptive selector currently treats fallback snapshots as
41
+ * "available bytes is conservative, prefer Hybrid over OnDisk").
42
+ */
43
+ /**
44
+ * Snapshot of OS-level memory state at observation time. All byte
45
+ * fields are in absolute bytes (the on-disk units in `/proc/meminfo`
46
+ * are KiB; the parser converts).
47
+ */
48
+ export interface OsMemorySnapshot {
49
+ /**
50
+ * Total physical RAM on the machine — the `MemTotal` line in
51
+ * `/proc/meminfo`, or `os.totalmem()` on non-Linux fallback.
52
+ */
53
+ totalBytes: number;
54
+ /**
55
+ * Memory the kernel reports as available for new allocations
56
+ * without swapping. On Linux ≥ 3.14, this is the `MemAvailable`
57
+ * line — accounts for reclaimable page cache + slab. On older
58
+ * kernels and on the os-fallback path, falls back to
59
+ * {@link freeBytes}.
60
+ *
61
+ * This is the load-bearing field for the Adaptive DiskANN mode
62
+ * selector: it answers "can this brain afford to keep PQ codes
63
+ * RAM-resident?".
64
+ */
65
+ availableBytes: number;
66
+ /**
67
+ * Physically free memory — the `MemFree` line in `/proc/meminfo`,
68
+ * or `os.freemem()` on non-Linux fallback. Smaller than
69
+ * {@link availableBytes} on a healthy Linux system because it
70
+ * excludes reclaimable page cache.
71
+ */
72
+ freeBytes: number;
73
+ /**
74
+ * `1 - (availableBytes / totalBytes)` clamped to `[0, 1]`. A high
75
+ * pressure score means little headroom for new allocations; the
76
+ * adaptive selector uses this as the primary mode-down signal.
77
+ */
78
+ pressureScore: number;
79
+ /**
80
+ * `'proc-meminfo'` when the values came from a successful
81
+ * `/proc/meminfo` read; `'os-fallback'` when the probe degraded
82
+ * to `os.totalmem()`/`os.freemem()`. Surface for diagnostics —
83
+ * a fallback snapshot is a hint that the deployment is on macOS
84
+ * or Windows.
85
+ */
86
+ source: 'proc-meminfo' | 'os-fallback';
87
+ }
88
+ /**
89
+ * Subset of `/proc/meminfo` lines the probe cares about. Returned by
90
+ * {@link parseMeminfo} so the snapshot composition stays unit-
91
+ * testable.
92
+ */
93
+ export interface MeminfoFields {
94
+ totalKib?: number;
95
+ availableKib?: number;
96
+ freeKib?: number;
97
+ }
98
+ /**
99
+ * Parse a `/proc/meminfo` text blob and extract the three fields the
100
+ * probe needs. Pure function — no I/O, fully deterministic, the
101
+ * only thing fixture tests need to cover.
102
+ *
103
+ * Returns `null` only when `MemTotal` is missing, which would mean
104
+ * the input isn't `/proc/meminfo` at all (every Linux kernel since
105
+ * the file existed has emitted it). Missing `MemAvailable` or
106
+ * `MemFree` is normal on old or specialised kernels and is left for
107
+ * the snapshot composer to handle.
108
+ */
109
+ export declare function parseMeminfo(text: string): MeminfoFields | null;
110
+ /**
111
+ * Build an {@link OsMemorySnapshot} from the parsed `/proc/meminfo`
112
+ * fields. Visible for tests; production callers use
113
+ * {@link OsMemoryProbe.snapshot}.
114
+ */
115
+ export declare function snapshotFromMeminfo(fields: MeminfoFields): OsMemorySnapshot;
116
+ /**
117
+ * Build the os-fallback snapshot from Node's `os` module. Visible
118
+ * for tests; production callers use {@link OsMemoryProbe.snapshot}.
119
+ */
120
+ export declare function snapshotFromOs(): OsMemorySnapshot;
121
+ /**
122
+ * Optional config for {@link OsMemoryProbe}. All fields are mainly
123
+ * for tests — production callers construct with defaults.
124
+ */
125
+ export interface OsMemoryProbeOptions {
126
+ /**
127
+ * Cache TTL in milliseconds. The snapshot is reused for repeated
128
+ * calls within this window. Default 250 ms — comfortably below
129
+ * the ResourceManager's 5 s pressure-tick.
130
+ */
131
+ cacheMs?: number;
132
+ /**
133
+ * Override the `/proc/meminfo` reader. Tests inject custom text
134
+ * to exercise the parser's edge cases without touching the real
135
+ * filesystem.
136
+ */
137
+ procReader?: () => string | null;
138
+ /**
139
+ * Override the os-fallback snapshot generator. Tests use this to
140
+ * pin the fallback shape without depending on the host's actual
141
+ * `os.totalmem()` reading.
142
+ */
143
+ osFallback?: () => OsMemorySnapshot;
144
+ /**
145
+ * Override the wall clock used for cache expiry. Tests pass a
146
+ * controllable timestamp source to assert cache behaviour
147
+ * deterministically.
148
+ */
149
+ now?: () => number;
150
+ }
151
+ /**
152
+ * Cached `/proc/meminfo` observer. Wire one instance into the
153
+ * {@link ResourceManager}; the adaptive DiskANN selector (Piece I)
154
+ * will read `snapshot()` at brain-open time.
155
+ */
156
+ export declare class OsMemoryProbe {
157
+ private readonly cacheMs;
158
+ private readonly procReader;
159
+ private readonly osFallback;
160
+ private readonly now;
161
+ private cached;
162
+ constructor(options?: OsMemoryProbeOptions);
163
+ /**
164
+ * Latest memory snapshot. Cached for {@link OsMemoryProbeOptions.cacheMs}
165
+ * milliseconds; calls inside the window reuse the cached value.
166
+ */
167
+ snapshot(): OsMemorySnapshot;
168
+ /**
169
+ * Invalidate the cache so the next {@link snapshot} call performs
170
+ * a fresh read. Used by tests; production callers shouldn't need
171
+ * this because the cache TTL is short.
172
+ */
173
+ invalidate(): void;
174
+ }
175
+ //# sourceMappingURL=OsMemoryProbe.d.ts.map