@fgv/ts-agent-memory 5.1.0-49 → 5.1.0-51
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/dist/packlets/index/memoryIndex.js +23 -16
- package/dist/packlets/index/memoryIndex.js.map +1 -1
- package/dist/packlets/ingest/orchestrator.js +13 -1
- package/dist/packlets/ingest/orchestrator.js.map +1 -1
- package/dist/packlets/retrieve/fragmentSemanticRetriever.js +94 -5
- package/dist/packlets/retrieve/fragmentSemanticRetriever.js.map +1 -1
- package/dist/packlets/retrieve/linkTraversalRetriever.js +12 -26
- package/dist/packlets/retrieve/linkTraversalRetriever.js.map +1 -1
- package/dist/packlets/retrieve/recencyRetriever.js +7 -7
- package/dist/packlets/retrieve/recencyRetriever.js.map +1 -1
- package/dist/packlets/retrieve/retriever.js +91 -10
- package/dist/packlets/retrieve/retriever.js.map +1 -1
- package/dist/packlets/retrieve/semanticRetriever.js +16 -16
- package/dist/packlets/retrieve/semanticRetriever.js.map +1 -1
- package/dist/packlets/retrieve/structuredFilterRetriever.js +7 -7
- package/dist/packlets/retrieve/structuredFilterRetriever.js.map +1 -1
- package/dist/packlets/retrieve/tagRetriever.js +7 -7
- package/dist/packlets/retrieve/tagRetriever.js.map +1 -1
- package/dist/packlets/retrieve/temporalRetrievers.js +23 -20
- package/dist/packlets/retrieve/temporalRetrievers.js.map +1 -1
- package/dist/packlets/store/coverage.js +6 -0
- package/dist/packlets/store/coverage.js.map +1 -0
- package/dist/packlets/store/fileTreeMemoryStore.js +234 -103
- package/dist/packlets/store/fileTreeMemoryStore.js.map +1 -1
- package/dist/packlets/store/index.js +4 -0
- package/dist/packlets/store/index.js.map +1 -1
- package/dist/packlets/store/listSelection.js +36 -0
- package/dist/packlets/store/listSelection.js.map +1 -0
- package/dist/packlets/store/memoryStore.js +6 -0
- package/dist/packlets/store/memoryStore.js.map +1 -0
- package/dist/packlets/store/reconcile.js +6 -0
- package/dist/packlets/store/reconcile.js.map +1 -0
- package/dist/packlets/store/storeCoverage.js +102 -0
- package/dist/packlets/store/storeCoverage.js.map +1 -0
- package/dist/packlets/store/storeIdentity.js +62 -0
- package/dist/packlets/store/storeIdentity.js.map +1 -0
- package/dist/packlets/store/storeReconcile.js +122 -0
- package/dist/packlets/store/storeReconcile.js.map +1 -0
- package/dist/packlets/store/vectorMaintenance.js +116 -8
- package/dist/packlets/store/vectorMaintenance.js.map +1 -1
- package/dist/packlets/store/vectorRecordSource.js +44 -0
- package/dist/packlets/store/vectorRecordSource.js.map +1 -0
- package/dist/packlets/tools/memoryTools.js +25 -2
- package/dist/packlets/tools/memoryTools.js.map +1 -1
- package/dist/packlets/types/envelope.js +25 -0
- package/dist/packlets/types/envelope.js.map +1 -1
- package/dist/packlets/types/identityResolver.js +6 -0
- package/dist/packlets/types/identityResolver.js.map +1 -0
- package/dist/packlets/types/index.js +2 -0
- package/dist/packlets/types/index.js.map +1 -1
- package/dist/packlets/types/recordResolver.js +6 -0
- package/dist/packlets/types/recordResolver.js.map +1 -0
- package/dist/packlets/types/temporal.js.map +1 -1
- package/dist/packlets/vector/inMemoryCosineIndex.js +39 -18
- package/dist/packlets/vector/inMemoryCosineIndex.js.map +1 -1
- package/dist/packlets/vector/inMemoryFragmentCosineIndex.js +109 -14
- package/dist/packlets/vector/inMemoryFragmentCosineIndex.js.map +1 -1
- package/dist/packlets/vector/rebuildHelpers.js +38 -0
- package/dist/packlets/vector/rebuildHelpers.js.map +1 -0
- package/dist/packlets/vector/vectorIndex.js.map +1 -1
- package/dist/ts-agent-memory.d.ts +1226 -114
- package/lib/packlets/index/memoryIndex.d.ts +118 -27
- package/lib/packlets/index/memoryIndex.d.ts.map +1 -1
- package/lib/packlets/index/memoryIndex.js +23 -16
- package/lib/packlets/index/memoryIndex.js.map +1 -1
- package/lib/packlets/ingest/orchestrator.d.ts.map +1 -1
- package/lib/packlets/ingest/orchestrator.js +13 -1
- package/lib/packlets/ingest/orchestrator.js.map +1 -1
- package/lib/packlets/retrieve/fragmentSemanticRetriever.d.ts +79 -1
- package/lib/packlets/retrieve/fragmentSemanticRetriever.d.ts.map +1 -1
- package/lib/packlets/retrieve/fragmentSemanticRetriever.js +94 -5
- package/lib/packlets/retrieve/fragmentSemanticRetriever.js.map +1 -1
- package/lib/packlets/retrieve/linkTraversalRetriever.d.ts +3 -10
- package/lib/packlets/retrieve/linkTraversalRetriever.d.ts.map +1 -1
- package/lib/packlets/retrieve/linkTraversalRetriever.js +11 -25
- package/lib/packlets/retrieve/linkTraversalRetriever.js.map +1 -1
- package/lib/packlets/retrieve/recencyRetriever.d.ts +3 -3
- package/lib/packlets/retrieve/recencyRetriever.d.ts.map +1 -1
- package/lib/packlets/retrieve/recencyRetriever.js +6 -6
- package/lib/packlets/retrieve/recencyRetriever.js.map +1 -1
- package/lib/packlets/retrieve/retriever.d.ts +88 -7
- package/lib/packlets/retrieve/retriever.d.ts.map +1 -1
- package/lib/packlets/retrieve/retriever.js +94 -9
- package/lib/packlets/retrieve/retriever.js.map +1 -1
- package/lib/packlets/retrieve/semanticRetriever.d.ts +3 -5
- package/lib/packlets/retrieve/semanticRetriever.d.ts.map +1 -1
- package/lib/packlets/retrieve/semanticRetriever.js +15 -15
- package/lib/packlets/retrieve/semanticRetriever.js.map +1 -1
- package/lib/packlets/retrieve/structuredFilterRetriever.d.ts +3 -3
- package/lib/packlets/retrieve/structuredFilterRetriever.d.ts.map +1 -1
- package/lib/packlets/retrieve/structuredFilterRetriever.js +6 -6
- package/lib/packlets/retrieve/structuredFilterRetriever.js.map +1 -1
- package/lib/packlets/retrieve/tagRetriever.d.ts +3 -3
- package/lib/packlets/retrieve/tagRetriever.d.ts.map +1 -1
- package/lib/packlets/retrieve/tagRetriever.js +6 -6
- package/lib/packlets/retrieve/tagRetriever.js.map +1 -1
- package/lib/packlets/retrieve/temporalRetrievers.d.ts +7 -5
- package/lib/packlets/retrieve/temporalRetrievers.d.ts.map +1 -1
- package/lib/packlets/retrieve/temporalRetrievers.js +22 -19
- package/lib/packlets/retrieve/temporalRetrievers.js.map +1 -1
- package/lib/packlets/store/coverage.d.ts +102 -0
- package/lib/packlets/store/coverage.d.ts.map +1 -0
- package/lib/packlets/store/coverage.js +7 -0
- package/lib/packlets/store/coverage.js.map +1 -0
- package/lib/packlets/store/fileTreeMemoryStore.d.ts +56 -167
- package/lib/packlets/store/fileTreeMemoryStore.d.ts.map +1 -1
- package/lib/packlets/store/fileTreeMemoryStore.js +234 -103
- package/lib/packlets/store/fileTreeMemoryStore.js.map +1 -1
- package/lib/packlets/store/index.d.ts +4 -0
- package/lib/packlets/store/index.d.ts.map +1 -1
- package/lib/packlets/store/index.js +4 -0
- package/lib/packlets/store/index.js.map +1 -1
- package/lib/packlets/store/listSelection.d.ts +101 -0
- package/lib/packlets/store/listSelection.d.ts.map +1 -0
- package/lib/packlets/store/listSelection.js +40 -0
- package/lib/packlets/store/listSelection.js.map +1 -0
- package/lib/packlets/store/memoryStore.d.ts +237 -0
- package/lib/packlets/store/memoryStore.d.ts.map +1 -0
- package/lib/packlets/store/memoryStore.js +7 -0
- package/lib/packlets/store/memoryStore.js.map +1 -0
- package/lib/packlets/store/reconcile.d.ts +82 -0
- package/lib/packlets/store/reconcile.d.ts.map +1 -0
- package/lib/packlets/store/reconcile.js +7 -0
- package/lib/packlets/store/reconcile.js.map +1 -0
- package/lib/packlets/store/storeCoverage.d.ts +45 -0
- package/lib/packlets/store/storeCoverage.d.ts.map +1 -0
- package/lib/packlets/store/storeCoverage.js +105 -0
- package/lib/packlets/store/storeCoverage.js.map +1 -0
- package/lib/packlets/store/storeIdentity.d.ts +38 -0
- package/lib/packlets/store/storeIdentity.d.ts.map +1 -0
- package/lib/packlets/store/storeIdentity.js +67 -0
- package/lib/packlets/store/storeIdentity.js.map +1 -0
- package/lib/packlets/store/storeReconcile.d.ts +41 -0
- package/lib/packlets/store/storeReconcile.d.ts.map +1 -0
- package/lib/packlets/store/storeReconcile.js +125 -0
- package/lib/packlets/store/storeReconcile.js.map +1 -0
- package/lib/packlets/store/vectorMaintenance.d.ts +74 -0
- package/lib/packlets/store/vectorMaintenance.d.ts.map +1 -1
- package/lib/packlets/store/vectorMaintenance.js +117 -8
- package/lib/packlets/store/vectorMaintenance.js.map +1 -1
- package/lib/packlets/store/vectorRecordSource.d.ts +36 -0
- package/lib/packlets/store/vectorRecordSource.d.ts.map +1 -0
- package/lib/packlets/store/vectorRecordSource.js +47 -0
- package/lib/packlets/store/vectorRecordSource.js.map +1 -0
- package/lib/packlets/tools/memoryTools.d.ts.map +1 -1
- package/lib/packlets/tools/memoryTools.js +25 -2
- package/lib/packlets/tools/memoryTools.js.map +1 -1
- package/lib/packlets/types/envelope.d.ts +24 -2
- package/lib/packlets/types/envelope.d.ts.map +1 -1
- package/lib/packlets/types/envelope.js +26 -0
- package/lib/packlets/types/envelope.js.map +1 -1
- package/lib/packlets/types/identityResolver.d.ts +42 -0
- package/lib/packlets/types/identityResolver.d.ts.map +1 -0
- package/lib/packlets/types/identityResolver.js +7 -0
- package/lib/packlets/types/identityResolver.js.map +1 -0
- package/lib/packlets/types/index.d.ts +2 -0
- package/lib/packlets/types/index.d.ts.map +1 -1
- package/lib/packlets/types/index.js +2 -0
- package/lib/packlets/types/index.js.map +1 -1
- package/lib/packlets/types/recordResolver.d.ts +39 -0
- package/lib/packlets/types/recordResolver.d.ts.map +1 -0
- package/lib/packlets/types/recordResolver.js +7 -0
- package/lib/packlets/types/recordResolver.js.map +1 -0
- package/lib/packlets/types/temporal.d.ts +26 -6
- package/lib/packlets/types/temporal.d.ts.map +1 -1
- package/lib/packlets/types/temporal.js.map +1 -1
- package/lib/packlets/vector/inMemoryCosineIndex.d.ts +9 -2
- package/lib/packlets/vector/inMemoryCosineIndex.d.ts.map +1 -1
- package/lib/packlets/vector/inMemoryCosineIndex.js +40 -19
- package/lib/packlets/vector/inMemoryCosineIndex.js.map +1 -1
- package/lib/packlets/vector/inMemoryFragmentCosineIndex.d.ts +18 -4
- package/lib/packlets/vector/inMemoryFragmentCosineIndex.d.ts.map +1 -1
- package/lib/packlets/vector/inMemoryFragmentCosineIndex.js +108 -13
- package/lib/packlets/vector/inMemoryFragmentCosineIndex.js.map +1 -1
- package/lib/packlets/vector/rebuildHelpers.d.ts +30 -0
- package/lib/packlets/vector/rebuildHelpers.d.ts.map +1 -0
- package/lib/packlets/vector/rebuildHelpers.js +42 -0
- package/lib/packlets/vector/rebuildHelpers.js.map +1 -0
- package/lib/packlets/vector/vectorIndex.d.ts +326 -20
- package/lib/packlets/vector/vectorIndex.d.ts.map +1 -1
- package/lib/packlets/vector/vectorIndex.js.map +1 -1
- package/package.json +7 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"temporalRetrievers.js","sourceRoot":"","sources":["../../../src/packlets/retrieve/temporalRetrievers.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright (c) 2026 Erik Fortune\n * SPDX-License-Identifier: MIT\n */\n\nimport { Result, succeed } from '@fgv/ts-utils';\nimport { IMemoryRecord, isTemporalRecord, selectCurrentVersion, selectVersionAsOf } from '../types';\nimport { IMemoryIndex } from '../index';\nimport {\n IMemoryQuery,\n IMemoryRetriever,\n IMemoryRetrieverCapabilities,\n guardRetrieverCapabilities,\n indexedRecordMatchesQuery,\n limitRecords,\n recencyCompare\n} from './retriever';\n\n/**\n * The capabilities every temporal retriever exposes: temporal \"as-of\" queries\n * are operational (semantic recall and link traversal are not this retriever's\n * concern).\n * @public\n */\nexport const TEMPORAL_CAPABILITIES: IMemoryRetrieverCapabilities = {\n supportsSemanticRecall: false,\n supportsTemporalQuery: true,\n supportsLinkTraversal: false\n};\n\n/**\n * Group the temporal records surviving a query's scope / kind / tag / provenance-source / predicate\n * pre-filter by entity (`kind` + `entityId`). Non-temporal records are excluded —\n * the temporal retrievers operate only over versioned entities. The map values\n * are each entity's versions (unordered).\n */\nfunction groupTemporalVersionsByEntity(\n index: IMemoryIndex,\n query: IMemoryQuery\n): Map<string, IMemoryRecord<unknown>[]> {\n const groups: Map<string, IMemoryRecord<unknown>[]> = new Map<string, IMemoryRecord<unknown>[]>();\n for (const entry of index.entries()) {\n if (!isTemporalRecord(entry.record) || !indexedRecordMatchesQuery(entry, query)) {\n continue;\n }\n const key: string = `${entry.record.envelope.kind}\\0${entry.record.envelope.entityId}`;\n const existing: IMemoryRecord<unknown>[] | undefined = groups.get(key);\n if (existing === undefined) {\n groups.set(key, [entry.record]);\n } else {\n existing.push(entry.record);\n }\n }\n return groups;\n}\n\n/**\n * Temporal retriever returning the **current** version of each temporal entity\n * matching the query (the newest version whose `invalid_at` is null/absent),\n * recency-ordered and limited. A fully-invalidated (soft-deleted) entity\n * contributes nothing. Non-temporal records are not this retriever's concern.\n * @public\n */\nexport class CurrentValidRetriever implements IMemoryRetriever {\n private readonly _index: IMemoryIndex;\n\n private constructor(index: IMemoryIndex) {\n this._index = index;\n }\n\n /** {@inheritDoc IMemoryRetriever.capabilities} */\n public get capabilities(): IMemoryRetrieverCapabilities {\n return TEMPORAL_CAPABILITIES;\n }\n\n /** Family-convention factory. */\n public static create(index: IMemoryIndex): Result<CurrentValidRetriever> {\n return succeed(new CurrentValidRetriever(index));\n }\n\n /** {@inheritDoc IMemoryRetriever.retrieve} */\n public retrieve(query: IMemoryQuery): Promise<Result<ReadonlyArray<IMemoryRecord<unknown>>>> {\n return Promise.resolve(\n guardRetrieverCapabilities(query, this.capabilities).onSuccess(() => {\n const selected: IMemoryRecord<unknown>[] = [];\n for (const versions of groupTemporalVersionsByEntity(this._index, query).values()) {\n const current: IMemoryRecord<unknown> | undefined = selectCurrentVersion(versions);\n if (current !== undefined) {\n selected.push(current);\n }\n }\n selected.sort(recencyCompare);\n return succeed(limitRecords(selected, query.limit, query.offset));\n })\n );\n }\n}\n\n/**\n * Temporal retriever returning, for each temporal entity matching the query, the\n * version valid at `query.asOf` (epoch ms). `asOf` is this retriever's axis: a\n * query without it yields an empty success (a no-op contribution to a\n * {@link HybridRetriever}, not a failure). Results are recency-ordered and\n * limited.\n * @public\n */\nexport class AsOfRetriever implements IMemoryRetriever {\n private readonly _index: IMemoryIndex;\n\n private constructor(index: IMemoryIndex) {\n this._index = index;\n }\n\n /** {@inheritDoc IMemoryRetriever.capabilities} */\n public get capabilities(): IMemoryRetrieverCapabilities {\n return TEMPORAL_CAPABILITIES;\n }\n\n /** Family-convention factory. */\n public static create(index: IMemoryIndex): Result<AsOfRetriever> {\n return succeed(new AsOfRetriever(index));\n }\n\n /** {@inheritDoc IMemoryRetriever.retrieve} */\n public retrieve(query: IMemoryQuery): Promise<Result<ReadonlyArray<IMemoryRecord<unknown>>>> {\n return Promise.resolve(\n guardRetrieverCapabilities(query, this.capabilities).onSuccess(() => {\n if (query.asOf === undefined) {\n return succeed([]);\n }\n const asOf: number = query.asOf;\n const selected: IMemoryRecord<unknown>[] = [];\n for (const versions of groupTemporalVersionsByEntity(this._index, query).values()) {\n const valid: IMemoryRecord<unknown> | undefined = selectVersionAsOf(versions, asOf);\n if (valid !== undefined) {\n selected.push(valid);\n }\n }\n selected.sort(recencyCompare);\n return succeed(limitRecords(selected, query.limit, query.offset));\n })\n );\n }\n}\n\n/**\n * Temporal retriever returning **every** version of each temporal entity matching\n * the query, ordered ascending by `valid_at` (then `seq` as a stable tiebreak) —\n * the entity's full history. Limited after ordering.\n *\n * @remarks\n * When the query matches more than one entity, the result is a single\n * CROSS-entity list globally sorted by `valid_at` — versions of different\n * entities interleave, NOT grouped per entity — so `limit` truncates that\n * globally-sorted list. Constrain to one entity (e.g. via `query.scope`) for a\n * single entity's contiguous history.\n * @public\n */\nexport class HistoryRetriever implements IMemoryRetriever {\n private readonly _index: IMemoryIndex;\n\n private constructor(index: IMemoryIndex) {\n this._index = index;\n }\n\n /** {@inheritDoc IMemoryRetriever.capabilities} */\n public get capabilities(): IMemoryRetrieverCapabilities {\n return TEMPORAL_CAPABILITIES;\n }\n\n /** Family-convention factory. */\n public static create(index: IMemoryIndex): Result<HistoryRetriever> {\n return succeed(new HistoryRetriever(index));\n }\n\n /** {@inheritDoc IMemoryRetriever.retrieve} */\n public retrieve(query: IMemoryQuery): Promise<Result<ReadonlyArray<IMemoryRecord<unknown>>>> {\n return Promise.resolve(\n guardRetrieverCapabilities(query, this.capabilities).onSuccess(() => {\n const history: IMemoryRecord<unknown>[] = [];\n for (const versions of groupTemporalVersionsByEntity(this._index, query).values()) {\n history.push(...versions);\n }\n history.sort(HistoryRetriever._byValidAtAscending);\n return succeed(limitRecords(history, query.limit, query.offset));\n })\n );\n }\n\n /** A version's world-truth start: its `valid_at`, defaulting to `created` when absent. */\n private static _startOf(record: IMemoryRecord<unknown>): number {\n const temporal: IMemoryRecord<unknown>['envelope']['temporal'] = record.envelope.temporal;\n /* c8 ignore next 3 -- unreachable: HistoryRetriever orders only temporal records (pre-filtered by isTemporalRecord), so `temporal` is always present; the guard keeps the type honest */\n if (temporal === undefined) {\n return record.envelope.created;\n }\n return temporal.valid_at ?? record.envelope.created;\n }\n\n /**\n * Ascending-by-`valid_at` comparator (a version's `valid_at` defaults to its\n * `created` when absent), with `seq` as a stable ascending tiebreak so\n * same-instant versions order by write sequence.\n */\n private static _byValidAtAscending(a: IMemoryRecord<unknown>, b: IMemoryRecord<unknown>): number {\n const aStart: number = HistoryRetriever._startOf(a);\n const bStart: number = HistoryRetriever._startOf(b);\n return aStart !== bStart ? aStart - bStart : a.envelope.seq - b.envelope.seq;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"temporalRetrievers.js","sourceRoot":"","sources":["../../../src/packlets/retrieve/temporalRetrievers.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright (c) 2026 Erik Fortune\n * SPDX-License-Identifier: MIT\n */\n\nimport { Result, succeed } from '@fgv/ts-utils';\nimport {\n IMemoryRecord,\n IMemoryRecordResolver,\n isTemporalRecord,\n selectCurrentVersion,\n selectVersionAsOf\n} from '../types';\nimport { IIndexedMemoryEntry, IMemoryIndex } from '../index';\nimport {\n IMemoryQuery,\n IMemoryRetriever,\n IMemoryRetrieverCapabilities,\n IRetrieverCreateParams,\n guardRetrieverCapabilities,\n indexedRecordMatchesQuery,\n materializePage,\n recencyCompare\n} from './retriever';\n\n/**\n * The capabilities every temporal retriever exposes: temporal \"as-of\" queries\n * are operational (semantic recall and link traversal are not this retriever's\n * concern).\n * @public\n */\nexport const TEMPORAL_CAPABILITIES: IMemoryRetrieverCapabilities = {\n supportsSemanticRecall: false,\n supportsTemporalQuery: true,\n supportsLinkTraversal: false\n};\n\n/**\n * Group the temporal records surviving a query's scope / kind / tag / provenance-source / predicate\n * pre-filter by entity (`kind` + `entityId`). Non-temporal records are excluded —\n * the temporal retrievers operate only over versioned entities. The map values\n * are each entity's versions (unordered).\n */\nfunction groupTemporalVersionsByEntity(\n index: IMemoryIndex,\n query: IMemoryQuery\n): Map<string, IIndexedMemoryEntry[]> {\n const groups: Map<string, IIndexedMemoryEntry[]> = new Map<string, IIndexedMemoryEntry[]>();\n for (const entry of index.entries()) {\n if (!isTemporalRecord(entry) || !indexedRecordMatchesQuery(entry, query)) {\n continue;\n }\n const key: string = `${entry.envelope.kind}\\0${entry.envelope.entityId}`;\n const existing: IIndexedMemoryEntry[] | undefined = groups.get(key);\n if (existing === undefined) {\n groups.set(key, [entry]);\n } else {\n existing.push(entry);\n }\n }\n return groups;\n}\n\n/**\n * Temporal retriever returning the **current** version of each temporal entity\n * matching the query (the newest version whose `invalid_at` is null/absent),\n * recency-ordered and limited. A fully-invalidated (soft-deleted) entity\n * contributes nothing. Non-temporal records are not this retriever's concern.\n * @public\n */\nexport class CurrentValidRetriever implements IMemoryRetriever {\n private readonly _index: IMemoryIndex;\n private readonly _resolver: IMemoryRecordResolver;\n\n private constructor(params: IRetrieverCreateParams) {\n this._index = params.index;\n this._resolver = params.resolver;\n }\n\n /** {@inheritDoc IMemoryRetriever.capabilities} */\n public get capabilities(): IMemoryRetrieverCapabilities {\n return TEMPORAL_CAPABILITIES;\n }\n\n /** Family-convention factory. */\n public static create(params: IRetrieverCreateParams): Result<CurrentValidRetriever> {\n return succeed(new CurrentValidRetriever(params));\n }\n\n /** {@inheritDoc IMemoryRetriever.retrieve} */\n public retrieve(query: IMemoryQuery): Promise<Result<ReadonlyArray<IMemoryRecord<unknown>>>> {\n return Promise.resolve(\n guardRetrieverCapabilities(query, this.capabilities).onSuccess(() => {\n const selected: IIndexedMemoryEntry[] = [];\n for (const versions of groupTemporalVersionsByEntity(this._index, query).values()) {\n const current: IIndexedMemoryEntry | undefined = selectCurrentVersion(versions);\n if (current !== undefined) {\n selected.push(current);\n }\n }\n selected.sort(recencyCompare);\n return materializePage(selected, query, this._resolver);\n })\n );\n }\n}\n\n/**\n * Temporal retriever returning, for each temporal entity matching the query, the\n * version valid at `query.asOf` (epoch ms). `asOf` is this retriever's axis: a\n * query without it yields an empty success (a no-op contribution to a\n * {@link HybridRetriever}, not a failure). Results are recency-ordered and\n * limited.\n * @public\n */\nexport class AsOfRetriever implements IMemoryRetriever {\n private readonly _index: IMemoryIndex;\n private readonly _resolver: IMemoryRecordResolver;\n\n private constructor(params: IRetrieverCreateParams) {\n this._index = params.index;\n this._resolver = params.resolver;\n }\n\n /** {@inheritDoc IMemoryRetriever.capabilities} */\n public get capabilities(): IMemoryRetrieverCapabilities {\n return TEMPORAL_CAPABILITIES;\n }\n\n /** Family-convention factory. */\n public static create(params: IRetrieverCreateParams): Result<AsOfRetriever> {\n return succeed(new AsOfRetriever(params));\n }\n\n /** {@inheritDoc IMemoryRetriever.retrieve} */\n public retrieve(query: IMemoryQuery): Promise<Result<ReadonlyArray<IMemoryRecord<unknown>>>> {\n return Promise.resolve(\n guardRetrieverCapabilities(query, this.capabilities).onSuccess(() => {\n if (query.asOf === undefined) {\n return succeed([]);\n }\n const asOf: number = query.asOf;\n const selected: IIndexedMemoryEntry[] = [];\n for (const versions of groupTemporalVersionsByEntity(this._index, query).values()) {\n const valid: IIndexedMemoryEntry | undefined = selectVersionAsOf(versions, asOf);\n if (valid !== undefined) {\n selected.push(valid);\n }\n }\n selected.sort(recencyCompare);\n return materializePage(selected, query, this._resolver);\n })\n );\n }\n}\n\n/**\n * Temporal retriever returning **every** version of each temporal entity matching\n * the query, ordered ascending by `valid_at` (then `seq` as a stable tiebreak) —\n * the entity's full history. Limited after ordering.\n *\n * @remarks\n * When the query matches more than one entity, the result is a single\n * CROSS-entity list globally sorted by `valid_at` — versions of different\n * entities interleave, NOT grouped per entity — so `limit` truncates that\n * globally-sorted list. Constrain to one entity (e.g. via `query.scope`) for a\n * single entity's contiguous history.\n * @public\n */\nexport class HistoryRetriever implements IMemoryRetriever {\n private readonly _index: IMemoryIndex;\n private readonly _resolver: IMemoryRecordResolver;\n\n private constructor(params: IRetrieverCreateParams) {\n this._index = params.index;\n this._resolver = params.resolver;\n }\n\n /** {@inheritDoc IMemoryRetriever.capabilities} */\n public get capabilities(): IMemoryRetrieverCapabilities {\n return TEMPORAL_CAPABILITIES;\n }\n\n /** Family-convention factory. */\n public static create(params: IRetrieverCreateParams): Result<HistoryRetriever> {\n return succeed(new HistoryRetriever(params));\n }\n\n /** {@inheritDoc IMemoryRetriever.retrieve} */\n public retrieve(query: IMemoryQuery): Promise<Result<ReadonlyArray<IMemoryRecord<unknown>>>> {\n return Promise.resolve(\n guardRetrieverCapabilities(query, this.capabilities).onSuccess(() => {\n const history: IIndexedMemoryEntry[] = [];\n for (const versions of groupTemporalVersionsByEntity(this._index, query).values()) {\n history.push(...versions);\n }\n history.sort(HistoryRetriever._byValidAtAscending);\n return materializePage(history, query, this._resolver);\n })\n );\n }\n\n /** A version's world-truth start: its `valid_at`, defaulting to `created` when absent. */\n private static _startOf(record: IIndexedMemoryEntry): number {\n const temporal: IMemoryRecord<unknown>['envelope']['temporal'] = record.envelope.temporal;\n /* c8 ignore next 3 -- unreachable: HistoryRetriever orders only temporal records (pre-filtered by isTemporalRecord), so `temporal` is always present; the guard keeps the type honest */\n if (temporal === undefined) {\n return record.envelope.created;\n }\n return temporal.valid_at ?? record.envelope.created;\n }\n\n /**\n * Ascending-by-`valid_at` comparator (a version's `valid_at` defaults to its\n * `created` when absent), with `seq` as a stable ascending tiebreak so\n * same-instant versions order by write sequence.\n */\n private static _byValidAtAscending(a: IIndexedMemoryEntry, b: IIndexedMemoryEntry): number {\n const aStart: number = HistoryRetriever._startOf(a);\n const bStart: number = HistoryRetriever._startOf(b);\n return aStart !== bStart ? aStart - bStart : a.envelope.seq - b.envelope.seq;\n }\n}\n"]}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { Kind } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* How much of one derived artifact exists, for one {@link Kind}.
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* Two numbers rather than a percentage, deliberately: a ratio cannot express
|
|
7
|
+
* *"nothing was expected"*, and a kind that is intentionally not derived (an
|
|
8
|
+
* excluded kind, a kind with no projector) is a normal and healthy state that a
|
|
9
|
+
* `0%` would render as an alarm.
|
|
10
|
+
* @public
|
|
11
|
+
*/
|
|
12
|
+
export interface IArtifactCoverage {
|
|
13
|
+
/**
|
|
14
|
+
* Records of this kind the store would derive this artifact for, **after** any
|
|
15
|
+
* exclusion. Read against {@link IDerivedStateCoverage.records} for the same
|
|
16
|
+
* kind: `records: 40, expected: 0` is the exclusion story, stated rather than
|
|
17
|
+
* inferred.
|
|
18
|
+
*/
|
|
19
|
+
readonly expected: number;
|
|
20
|
+
/**
|
|
21
|
+
* Of those, how many the **store believes** are covered. See
|
|
22
|
+
* {@link IIndexCoverage.indexSize} for why the word "believes" is load-bearing.
|
|
23
|
+
*/
|
|
24
|
+
readonly covered: number;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Coverage of the record-granular vector index.
|
|
28
|
+
* @public
|
|
29
|
+
*/
|
|
30
|
+
export interface IIndexCoverage {
|
|
31
|
+
/** Per-kind expected/covered, derived from the envelope walk. */
|
|
32
|
+
readonly perKind: ReadonlyMap<Kind, IArtifactCoverage>;
|
|
33
|
+
/**
|
|
34
|
+
* What the index **actually holds**, whole-index.
|
|
35
|
+
*
|
|
36
|
+
* @remarks
|
|
37
|
+
* **This is a fact and {@link IArtifactCoverage.covered} is a belief, and the
|
|
38
|
+
* two are reported separately because their disagreement is the only free
|
|
39
|
+
* signal that distinguishes a persistent index from a fresh one.** `covered`
|
|
40
|
+
* counts envelopes carrying an `embeddingRef`; `indexSize` counts vectors. With
|
|
41
|
+
* a persistent index they agree. With an in-memory index at open they do not —
|
|
42
|
+
* the envelopes still claim references from previous sessions while the index
|
|
43
|
+
* holds nothing, so `covered` **lies, in the confident direction**.
|
|
44
|
+
*
|
|
45
|
+
* Collapsing them into one "coverage %" would destroy that signal, which is why
|
|
46
|
+
* this type does not offer one.
|
|
47
|
+
*/
|
|
48
|
+
readonly indexSize: number;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Coverage of the fragment-granular vector index.
|
|
52
|
+
*
|
|
53
|
+
* @remarks
|
|
54
|
+
* **Aggregate only, and the reason is structural rather than an omission.** The
|
|
55
|
+
* record lane has a per-record marker on the envelope (`embeddingRef`), so its
|
|
56
|
+
* numerator falls out of the same free walk that produces the denominator. The
|
|
57
|
+
* fragment lane has **no envelope marker at all** — nothing on a record says
|
|
58
|
+
* whether it has fragments — so a per-kind numerator would cost one
|
|
59
|
+
* `IFragmentVectorIndex.has` call per record, and coverage is contractually
|
|
60
|
+
* cheap (see {@link IMemoryStore.coverage}).
|
|
61
|
+
*
|
|
62
|
+
* The per-kind **denominator** is still available on
|
|
63
|
+
* {@link IDerivedStateCoverage.records}. A caller who needs the per-kind
|
|
64
|
+
* numerator runs `reconcile(kind, 'fragment-vector')`, which reports it because
|
|
65
|
+
* it is already paying for the walk.
|
|
66
|
+
* @public
|
|
67
|
+
*/
|
|
68
|
+
export interface IFragmentIndexCoverage {
|
|
69
|
+
/** Records with at least one fragment held. Mirrors `IFragmentVectorIndex.recordCount`. */
|
|
70
|
+
readonly indexRecordCount: number;
|
|
71
|
+
/** Total fragments held — the fan-out. Mirrors `IFragmentVectorIndex.fragmentCount`. */
|
|
72
|
+
readonly indexFragmentCount: number;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* A snapshot of how much of the store's **derived state** exists, resolved by
|
|
76
|
+
* {@link Kind} — the answer to *"is my derived state consistent with my
|
|
77
|
+
* records?"*.
|
|
78
|
+
*
|
|
79
|
+
* @remarks
|
|
80
|
+
* **Absent is not zero.** Each artifact member is optional, and `undefined` means
|
|
81
|
+
* *this artifact is not derived here at all* — no rank projector is registered,
|
|
82
|
+
* or that index lane is not wired. It never means *nothing is covered*. Folding
|
|
83
|
+
* the two would make a health surface render a confident `0%` for a feature the
|
|
84
|
+
* deployment deliberately did not turn on, which is the same defect as
|
|
85
|
+
* `embeddingRef`'s three-way ambiguity one level up.
|
|
86
|
+
*
|
|
87
|
+
* So: `fragmentVectors: undefined` is a store with no fragment index and is not a
|
|
88
|
+
* problem. `fragmentVectors: { indexRecordCount: 0, indexFragmentCount: 0 }` is a
|
|
89
|
+
* wired fragment index holding nothing, and probably is.
|
|
90
|
+
* @public
|
|
91
|
+
*/
|
|
92
|
+
export interface IDerivedStateCoverage {
|
|
93
|
+
/** Records per kind — the denominator every other number is read against. */
|
|
94
|
+
readonly records: ReadonlyMap<Kind, number>;
|
|
95
|
+
/** Absent when no kind has a registered {@link RankProjector}. */
|
|
96
|
+
readonly rank?: ReadonlyMap<Kind, IArtifactCoverage>;
|
|
97
|
+
/** Absent when the record-vector lane is not wired. */
|
|
98
|
+
readonly recordVectors?: IIndexCoverage;
|
|
99
|
+
/** Absent when the fragment lane is not wired. */
|
|
100
|
+
readonly fragmentVectors?: IFragmentIndexCoverage;
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=coverage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coverage.d.ts","sourceRoot":"","sources":["../../../src/packlets/store/coverage.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAEhC;;;;;;;;;GASG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,iEAAiE;IACjE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;IACvD;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,sBAAsB;IACrC,2FAA2F;IAC3F,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,wFAAwF;IACxF,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;CACrC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,qBAAqB;IACpC,6EAA6E;IAC7E,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC5C,kEAAkE;IAClE,QAAQ,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;IACrD,uDAAuD;IACvD,QAAQ,CAAC,aAAa,CAAC,EAAE,cAAc,CAAC;IACxC,kDAAkD;IAClD,QAAQ,CAAC,eAAe,CAAC,EAAE,sBAAsB,CAAC;CACnD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coverage.js","sourceRoot":"","sources":["../../../src/packlets/store/coverage.ts"],"names":[],"mappings":";AAAA;;;GAGG","sourcesContent":["/*\n * Copyright (c) 2026 Erik Fortune\n * SPDX-License-Identifier: MIT\n */\n\nimport { Kind } from '../types';\n\n/**\n * How much of one derived artifact exists, for one {@link Kind}.\n *\n * @remarks\n * Two numbers rather than a percentage, deliberately: a ratio cannot express\n * *\"nothing was expected\"*, and a kind that is intentionally not derived (an\n * excluded kind, a kind with no projector) is a normal and healthy state that a\n * `0%` would render as an alarm.\n * @public\n */\nexport interface IArtifactCoverage {\n /**\n * Records of this kind the store would derive this artifact for, **after** any\n * exclusion. Read against {@link IDerivedStateCoverage.records} for the same\n * kind: `records: 40, expected: 0` is the exclusion story, stated rather than\n * inferred.\n */\n readonly expected: number;\n /**\n * Of those, how many the **store believes** are covered. See\n * {@link IIndexCoverage.indexSize} for why the word \"believes\" is load-bearing.\n */\n readonly covered: number;\n}\n\n/**\n * Coverage of the record-granular vector index.\n * @public\n */\nexport interface IIndexCoverage {\n /** Per-kind expected/covered, derived from the envelope walk. */\n readonly perKind: ReadonlyMap<Kind, IArtifactCoverage>;\n /**\n * What the index **actually holds**, whole-index.\n *\n * @remarks\n * **This is a fact and {@link IArtifactCoverage.covered} is a belief, and the\n * two are reported separately because their disagreement is the only free\n * signal that distinguishes a persistent index from a fresh one.** `covered`\n * counts envelopes carrying an `embeddingRef`; `indexSize` counts vectors. With\n * a persistent index they agree. With an in-memory index at open they do not —\n * the envelopes still claim references from previous sessions while the index\n * holds nothing, so `covered` **lies, in the confident direction**.\n *\n * Collapsing them into one \"coverage %\" would destroy that signal, which is why\n * this type does not offer one.\n */\n readonly indexSize: number;\n}\n\n/**\n * Coverage of the fragment-granular vector index.\n *\n * @remarks\n * **Aggregate only, and the reason is structural rather than an omission.** The\n * record lane has a per-record marker on the envelope (`embeddingRef`), so its\n * numerator falls out of the same free walk that produces the denominator. The\n * fragment lane has **no envelope marker at all** — nothing on a record says\n * whether it has fragments — so a per-kind numerator would cost one\n * `IFragmentVectorIndex.has` call per record, and coverage is contractually\n * cheap (see {@link IMemoryStore.coverage}).\n *\n * The per-kind **denominator** is still available on\n * {@link IDerivedStateCoverage.records}. A caller who needs the per-kind\n * numerator runs `reconcile(kind, 'fragment-vector')`, which reports it because\n * it is already paying for the walk.\n * @public\n */\nexport interface IFragmentIndexCoverage {\n /** Records with at least one fragment held. Mirrors `IFragmentVectorIndex.recordCount`. */\n readonly indexRecordCount: number;\n /** Total fragments held — the fan-out. Mirrors `IFragmentVectorIndex.fragmentCount`. */\n readonly indexFragmentCount: number;\n}\n\n/**\n * A snapshot of how much of the store's **derived state** exists, resolved by\n * {@link Kind} — the answer to *\"is my derived state consistent with my\n * records?\"*.\n *\n * @remarks\n * **Absent is not zero.** Each artifact member is optional, and `undefined` means\n * *this artifact is not derived here at all* — no rank projector is registered,\n * or that index lane is not wired. It never means *nothing is covered*. Folding\n * the two would make a health surface render a confident `0%` for a feature the\n * deployment deliberately did not turn on, which is the same defect as\n * `embeddingRef`'s three-way ambiguity one level up.\n *\n * So: `fragmentVectors: undefined` is a store with no fragment index and is not a\n * problem. `fragmentVectors: { indexRecordCount: 0, indexFragmentCount: 0 }` is a\n * wired fragment index holding nothing, and probably is.\n * @public\n */\nexport interface IDerivedStateCoverage {\n /** Records per kind — the denominator every other number is read against. */\n readonly records: ReadonlyMap<Kind, number>;\n /** Absent when no kind has a registered {@link RankProjector}. */\n readonly rank?: ReadonlyMap<Kind, IArtifactCoverage>;\n /** Absent when the record-vector lane is not wired. */\n readonly recordVectors?: IIndexCoverage;\n /** Absent when the fragment lane is not wired. */\n readonly fragmentVectors?: IFragmentIndexCoverage;\n}\n"]}
|
|
@@ -1,28 +1,14 @@
|
|
|
1
1
|
import { Logging, Result } from '@fgv/ts-utils';
|
|
2
2
|
import { FileTree } from '@fgv/ts-json-base';
|
|
3
|
-
import { DedupScope, EntityId, IIdentityCodec, IMemoryRecord, IWritePolicy, Kind, MemoryId, MemoryScopeKey, RankProjector
|
|
3
|
+
import { DedupScope, EntityId, IIdentityCodecResult, IIdentityCodec, IMemoryRecord, IWritePolicy, Kind, MemoryId, MemoryScopeKey, RankProjector } from '../types';
|
|
4
4
|
import { IBodyConverterRegistry as IRegistry } from '../converters';
|
|
5
|
-
import {
|
|
5
|
+
import { IDerivedStateCoverage } from './coverage';
|
|
6
|
+
import { DerivedArtifact, ReconcileReport } from './reconcile';
|
|
7
|
+
import { IIndexedMemoryEntry, IMemoryIndex } from '../index';
|
|
6
8
|
import { IMemoryObserver } from '../observe';
|
|
7
9
|
import { FragmentEmbedder, IFragmentVectorIndex, IMemoryRecordSource, IScopedMemoryRecord, IVectorIndex, MemoryEmbedder } from '../vector';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
* @public
|
|
11
|
-
*/
|
|
12
|
-
export interface IMemoryStoreListFilter {
|
|
13
|
-
/** Restrict to records in this scope. */
|
|
14
|
-
readonly scope?: MemoryScopeKey;
|
|
15
|
-
/** Restrict to records of this kind. */
|
|
16
|
-
readonly kind?: Kind;
|
|
17
|
-
/** Restrict to records carrying this tag (exact match). */
|
|
18
|
-
readonly tag?: Tag;
|
|
19
|
-
/**
|
|
20
|
-
* For temporal (versioned) kinds: collapse each entity to the single version
|
|
21
|
-
* valid at this epoch ms. Non-temporal records are timeless and pass through
|
|
22
|
-
* unchanged. Absent = no temporal projection (every version is returned).
|
|
23
|
-
*/
|
|
24
|
-
readonly asOf?: number;
|
|
25
|
-
}
|
|
10
|
+
import { IMemoryStore } from './memoryStore';
|
|
11
|
+
import { MemoryListSelection } from './listSelection';
|
|
26
12
|
/**
|
|
27
13
|
* Policy for how {@link FileTreeMemoryStore.create}'s initial vault walk reacts
|
|
28
14
|
* to a record that fails to parse or validate.
|
|
@@ -54,147 +40,6 @@ export interface ISkippedRecord {
|
|
|
54
40
|
/** The parse/validation failure message (includes the record path). */
|
|
55
41
|
readonly error: string;
|
|
56
42
|
}
|
|
57
|
-
/**
|
|
58
|
-
* The writable, FileTree-backed, content-hash-deduped memory store.
|
|
59
|
-
* @public
|
|
60
|
-
*/
|
|
61
|
-
export interface IMemoryStore {
|
|
62
|
-
/**
|
|
63
|
-
* Keyed read by entity id. Resolves `entityId` to a storage address via the
|
|
64
|
-
* registered {@link IIdentityCodec} for `kind`. Returns `undefined` when no
|
|
65
|
-
* record exists. For a versioned (temporal) kind this returns the current
|
|
66
|
-
* version, resolved from the derived in-memory index (not re-read/re-verified
|
|
67
|
-
* from disk per call — the index is kept in sync with every write).
|
|
68
|
-
*/
|
|
69
|
-
get(kind: Kind, entityId: EntityId): Promise<Result<IMemoryRecord<unknown> | undefined>>;
|
|
70
|
-
/**
|
|
71
|
-
* Direct read by `(scope, MemoryId)`. Returns `undefined` when not found.
|
|
72
|
-
*/
|
|
73
|
-
getById(scope: MemoryScopeKey, id: MemoryId): Promise<Result<IMemoryRecord<unknown> | undefined>>;
|
|
74
|
-
/**
|
|
75
|
-
* List records, filtered in-memory over the derived index.
|
|
76
|
-
*/
|
|
77
|
-
list(filter?: IMemoryStoreListFilter): Promise<Result<ReadonlyArray<IMemoryRecord<unknown>>>>;
|
|
78
|
-
/**
|
|
79
|
-
* List EVERY record in the vault, each paired with its scope-qualified
|
|
80
|
-
* `(scope, id)` address — the projection {@link IMemoryRecordSource} requires.
|
|
81
|
-
* Unlike {@link IMemoryStore.list | list}, it takes no filter (whole-vault) and
|
|
82
|
-
* returns {@link IScopedMemoryRecord}s so a re-index keys each entry on the same
|
|
83
|
-
* scoped target the incremental embed-on-write path uses. Two records that share
|
|
84
|
-
* a filename stem across scopes appear as distinct entries.
|
|
85
|
-
*/
|
|
86
|
-
listScoped(): Promise<Result<ReadonlyArray<IScopedMemoryRecord>>>;
|
|
87
|
-
/**
|
|
88
|
-
* Adapt this store to the {@link IMemoryRecordSource} seam so it can drive
|
|
89
|
-
* {@link IVectorIndex} rebuilds (e.g. `InMemoryCosineIndex.rebuild`). The
|
|
90
|
-
* returned source's `list()` delegates to {@link IMemoryStore.listScoped},
|
|
91
|
-
* **filtered to the kinds {@link IMemoryStore.embedsKind | embedsKind} reports** —
|
|
92
|
-
* this source exists to feed the record vector index, so a kind excluded from
|
|
93
|
-
* that index is excluded here too, and a reopen does not re-embed records the
|
|
94
|
-
* index will never return. With no
|
|
95
|
-
* {@link IFileTreeMemoryStoreCreateParams.embedKinds | embedKinds} declaration
|
|
96
|
-
* every kind participates and the filter is the identity. `listScoped` itself is
|
|
97
|
-
* **not** filtered and remains the whole-vault surface.
|
|
98
|
-
*
|
|
99
|
-
* The store cannot implement {@link IMemoryRecordSource} directly because its
|
|
100
|
-
* `list(filter?)` returns bare records (the ergonomic query surface) while the
|
|
101
|
-
* seam's `list()` returns scope-qualified records.
|
|
102
|
-
*/
|
|
103
|
-
asRecordSource(): IMemoryRecordSource;
|
|
104
|
-
/**
|
|
105
|
-
* The EFFECTIVE {@link DedupScope} for `kind` — the granularity at which a
|
|
106
|
-
* write for this kind deduplicates against the existing vault.
|
|
107
|
-
*
|
|
108
|
-
* @remarks
|
|
109
|
-
* This is a **read accessor over the store's already-injected write policies**,
|
|
110
|
-
* and it is the single place any caller — the store's own write path included —
|
|
111
|
-
* asks what a kind's dedup granularity is. It resolves the full chain the store
|
|
112
|
-
* applies on write: the kind's registered {@link IWritePolicy}, falling back to
|
|
113
|
-
* the store's default policy, then that policy's
|
|
114
|
-
* {@link IWritePolicy.dedupScope | dedupScope}, falling back to
|
|
115
|
-
* {@link DEFAULT_DEDUP_SCOPE}. Note the store's default policy is a
|
|
116
|
-
* {@link KnowledgeLwwPolicy}, which declares `'content'` — so a kind with NO
|
|
117
|
-
* registered policy resolves to `'content'`, not to `DEFAULT_DEDUP_SCOPE`.
|
|
118
|
-
*
|
|
119
|
-
* It exists so a caller that must agree with the store about dedup granularity
|
|
120
|
-
* — notably the ingest orchestrator's stage-4 layer-1 exact match — can read the
|
|
121
|
-
* declaration through this seam instead of being handed a second copy of the
|
|
122
|
-
* policy map. A second declaration site is precisely the defect this accessor
|
|
123
|
-
* was added to remove.
|
|
124
|
-
*
|
|
125
|
-
* Deliberately synchronous, total, and NOT `Result`-returning: it reads
|
|
126
|
-
* constructor-injected configuration, touches no I/O, and cannot fail (every
|
|
127
|
-
* link in the fallback chain has a total default). It exposes only the scope,
|
|
128
|
-
* never the {@link IWritePolicy} itself, so it can never become a back door for
|
|
129
|
-
* invoking admission or merge logic out of band.
|
|
130
|
-
*/
|
|
131
|
-
dedupScopeFor(kind: Kind): DedupScope;
|
|
132
|
-
/**
|
|
133
|
-
* Whether records of `kind` participate in the **record-granular** vector index.
|
|
134
|
-
*
|
|
135
|
-
* @remarks
|
|
136
|
-
* A read accessor over the store's injected {@link IFileTreeMemoryStoreCreateParams.embedKinds | embedKinds}
|
|
137
|
-
* declaration, in the same spirit as {@link IMemoryStore.dedupScopeFor} — one
|
|
138
|
-
* place to ask, so the store's write path and any caller reasoning about index
|
|
139
|
-
* coverage cannot disagree. `true` for every kind when no declaration was made.
|
|
140
|
-
*
|
|
141
|
-
* **This is distinct from a {@link MemoryEmbedder} decline, and the difference is
|
|
142
|
-
* cost.** An embedder that returns `undefined` has already been called: the
|
|
143
|
-
* round trip is paid, and on a locally-hosted model that round trip is the
|
|
144
|
-
* expense. A kind excluded here is never handed to the embedder at all. The
|
|
145
|
-
* decline makes the intent *expressible*; this makes it *free*.
|
|
146
|
-
*
|
|
147
|
-
* Deliberately synchronous, total, and NOT `Result`-returning: it reads
|
|
148
|
-
* constructor-injected configuration, touches no I/O, and cannot fail.
|
|
149
|
-
*/
|
|
150
|
-
embedsKind(kind: Kind): boolean;
|
|
151
|
-
/**
|
|
152
|
-
* Write a record. Validates the body, computes a content hash, deduplicates
|
|
153
|
-
* (scope-wide, before policy), applies the kind's {@link IWritePolicy}, stamps
|
|
154
|
-
* transaction-time metadata (`created` / `updated` / `seq` / `contentHash`),
|
|
155
|
-
* writes the file, and patches the index. Returns the written record — or the
|
|
156
|
-
* existing record unchanged on a dedup no-op.
|
|
157
|
-
*/
|
|
158
|
-
put(record: IMemoryRecord<unknown>): Promise<Result<IMemoryRecord<unknown>>>;
|
|
159
|
-
/**
|
|
160
|
-
* Re-apply the kind's {@link RankProjector} to every record of `kind` already
|
|
161
|
-
* in the store, restamping {@link IMemoryEnvelope.rank}. Returns the number of
|
|
162
|
-
* records whose `rank` actually changed.
|
|
163
|
-
*
|
|
164
|
-
* @remarks
|
|
165
|
-
* **This exists because `rank` is otherwise new-store-only, and fails in a way
|
|
166
|
-
* that looks like it works.** The projector runs on the write path only, so
|
|
167
|
-
* registering one against a populated store ranks nothing already written —
|
|
168
|
-
* and because an absent `rank` sorts *last*, every pre-registration record
|
|
169
|
-
* lands below every post-registration one no matter what the projector would
|
|
170
|
-
* have scored it. The ordering is not merely partial; it is **inverted with
|
|
171
|
-
* respect to the projector's own intent**, with no failure anywhere to say so.
|
|
172
|
-
*
|
|
173
|
-
* Deliberately **does not** touch `created` / `updated` / `seq`, and fires no
|
|
174
|
-
* `'write'` observation. Routing a reconcile through {@link IMemoryStore.put}
|
|
175
|
-
* would bump transaction time on every record — trading a wrong `rank` order
|
|
176
|
-
* for a wrong recency order, and flooding any wired observer with writes that
|
|
177
|
-
* are not writes. The body is re-serialized verbatim from the file's own
|
|
178
|
-
* bytes; only the envelope's `rank` moves.
|
|
179
|
-
*
|
|
180
|
-
* Fails loudly if `kind` has no registered projector: asking to reconcile a
|
|
181
|
-
* kind you never configured is a caller error, not a no-op.
|
|
182
|
-
*
|
|
183
|
-
* **Not atomic, and safe for it.** A failure part-way leaves earlier records
|
|
184
|
-
* restamped. That is benign because restamping is idempotent — re-running
|
|
185
|
-
* converges — which is also why no report shape is offered here. A count is
|
|
186
|
-
* enough.
|
|
187
|
-
*/
|
|
188
|
-
reconcileRank(kind: Kind): Promise<Result<number>>;
|
|
189
|
-
/**
|
|
190
|
-
* Delete a record by `(kind, entityId)`. Non-temporal kinds physically delete
|
|
191
|
-
* the file and return the deleted record's {@link MemoryId}. Temporal
|
|
192
|
-
* (versioned) kinds SOFT-delete: the current version is invalidated
|
|
193
|
-
* (`invalid_at` set), history is retained, and the invalidated version's
|
|
194
|
-
* {@link MemoryId} is returned.
|
|
195
|
-
*/
|
|
196
|
-
delete(kind: Kind, entityId: EntityId): Promise<Result<MemoryId>>;
|
|
197
|
-
}
|
|
198
43
|
/**
|
|
199
44
|
* Parameters for {@link FileTreeMemoryStore.create}.
|
|
200
45
|
* @public
|
|
@@ -471,9 +316,52 @@ export declare class FileTreeMemoryStore implements IMemoryStore {
|
|
|
471
316
|
/** {@inheritDoc IMemoryStore.getById} */
|
|
472
317
|
getById(scope: MemoryScopeKey, id: MemoryId): Promise<Result<IMemoryRecord<unknown> | undefined>>;
|
|
473
318
|
/** {@inheritDoc IMemoryStore.list} */
|
|
474
|
-
list(
|
|
319
|
+
list(selection: MemoryListSelection): Promise<Result<ReadonlyArray<IMemoryRecord<unknown>>>>;
|
|
320
|
+
/** {@inheritDoc IMemoryStore.coverage} */
|
|
321
|
+
coverage(): Promise<Result<IDerivedStateCoverage>>;
|
|
322
|
+
/** {@inheritDoc IMemoryStore.listEntries} */
|
|
323
|
+
listEntries(): Promise<Result<ReadonlyArray<IIndexedMemoryEntry>>>;
|
|
475
324
|
/** {@inheritDoc IMemoryStore.listScoped} */
|
|
476
325
|
listScoped(): Promise<Result<ReadonlyArray<IScopedMemoryRecord>>>;
|
|
326
|
+
/** {@inheritDoc IMemoryRecordResolver.resolveRecord} */
|
|
327
|
+
resolveRecord(scope: MemoryScopeKey, id: MemoryId): Result<IMemoryRecord<unknown> | undefined>;
|
|
328
|
+
private _codec;
|
|
329
|
+
/** {@inheritDoc IIdentityResolver.resolveIdentity} */
|
|
330
|
+
resolveIdentity(kind: Kind, entityId: EntityId): Result<IIdentityCodecResult>;
|
|
331
|
+
/**
|
|
332
|
+
* Materialize a selected set of entries into records, dropping any that have
|
|
333
|
+
* vanished since selection.
|
|
334
|
+
*
|
|
335
|
+
* @remarks
|
|
336
|
+
* A miss is not a failure. Selection reads the in-memory index and
|
|
337
|
+
* materialization reads storage, so a record deleted in between is a legitimate
|
|
338
|
+
* race and yields a shorter list rather than an error. A read that FAILS is a
|
|
339
|
+
* real fault and propagates.
|
|
340
|
+
*/
|
|
341
|
+
private _materialize;
|
|
342
|
+
/**
|
|
343
|
+
* Materialize one entry, treating "gone" as a fault rather than a miss.
|
|
344
|
+
*
|
|
345
|
+
* @remarks
|
|
346
|
+
* For paths where a vanished record really does mean the index and the vault
|
|
347
|
+
* disagree, rather than that something legitimately removed it in between.
|
|
348
|
+
*
|
|
349
|
+
* Three of the four callers hold the write lock, so nothing can have removed
|
|
350
|
+
* the record since the entry was read. `get()`'s versioned path does not, and
|
|
351
|
+
* is safe only because temporal kinds never physically delete a version — they
|
|
352
|
+
* invalidate in place, and cap-cull does not apply to them. **If eviction is
|
|
353
|
+
* ever added to the temporal path, that caller must change**, or it
|
|
354
|
+
* reintroduces the race this method exists to detect.
|
|
355
|
+
*
|
|
356
|
+
* `listScoped` also does not hold the lock, and uses this deliberately anyway:
|
|
357
|
+
* it feeds a coverage report, so a silent drop there is worse than a loud
|
|
358
|
+
* failure. See its comment, and `docs/FUTURE.md` for the eviction window.
|
|
359
|
+
*
|
|
360
|
+
* The drop-tolerant counterpart is {@link FileTreeMemoryStore._materialize},
|
|
361
|
+
* for readers where a record that vanished between selection and
|
|
362
|
+
* materialization is a miss rather than a fault.
|
|
363
|
+
*/
|
|
364
|
+
private _resolveRequired;
|
|
477
365
|
/** {@inheritDoc IMemoryStore.asRecordSource} */
|
|
478
366
|
asRecordSource(): IMemoryRecordSource;
|
|
479
367
|
/**
|
|
@@ -484,8 +372,8 @@ export declare class FileTreeMemoryStore implements IMemoryStore {
|
|
|
484
372
|
* contributes nothing.
|
|
485
373
|
*/
|
|
486
374
|
private static _projectAsOf;
|
|
487
|
-
/** {@inheritDoc IMemoryStore.
|
|
488
|
-
|
|
375
|
+
/** {@inheritDoc IMemoryStore.reconcile} */
|
|
376
|
+
reconcile(kind: Kind, artifact: DerivedArtifact): Promise<Result<ReconcileReport>>;
|
|
489
377
|
/** {@inheritDoc IMemoryStore.put} */
|
|
490
378
|
put(record: IMemoryRecord<unknown>): Promise<Result<IMemoryRecord<unknown>>>;
|
|
491
379
|
/** {@inheritDoc IMemoryStore.delete} */
|
|
@@ -661,7 +549,7 @@ export declare class FileTreeMemoryStore implements IMemoryStore {
|
|
|
661
549
|
private _isMutableMetadataUnchanged;
|
|
662
550
|
private _contentHash;
|
|
663
551
|
/**
|
|
664
|
-
* The
|
|
552
|
+
* The rank branch of {@link FileTreeMemoryStore.reconcile}, under the write lock.
|
|
665
553
|
*
|
|
666
554
|
* @remarks
|
|
667
555
|
* Re-reads each record's file rather than trusting the in-memory index, for
|
|
@@ -690,13 +578,15 @@ export declare class FileTreeMemoryStore implements IMemoryStore {
|
|
|
690
578
|
* another on a reconcile. `_stampRank` itself is reused verbatim, which also
|
|
691
579
|
* inherits its throw semantics (logged at `warn`, `rank` cleared).
|
|
692
580
|
*/
|
|
581
|
+
private _reconcileLocked;
|
|
582
|
+
/** The rank branch of {@link FileTreeMemoryStore._reconcileLocked}. */
|
|
693
583
|
private _reconcileRankLocked;
|
|
694
584
|
/**
|
|
695
585
|
* Re-apply the rank projector to one record on disk. Returns whether `rank`
|
|
696
586
|
* actually changed — an unchanged rank writes nothing, so a reconcile over an
|
|
697
587
|
* already-consistent store touches no files.
|
|
698
588
|
*/
|
|
699
|
-
private
|
|
589
|
+
private _rewriteEnvelope;
|
|
700
590
|
/**
|
|
701
591
|
* Stamp the store-computed {@link IMemoryEnvelope.rank} onto a fully-built,
|
|
702
592
|
* fully-stamped record by running the kind's registered {@link RankProjector}.
|
|
@@ -710,7 +600,6 @@ export declare class FileTreeMemoryStore implements IMemoryStore {
|
|
|
710
600
|
* than preserving it), so a ranking bug never loses an authoritative write.
|
|
711
601
|
*/
|
|
712
602
|
private _stampRank;
|
|
713
|
-
private _codecFor;
|
|
714
603
|
private _policyFor;
|
|
715
604
|
/** {@inheritDoc IMemoryStore.dedupScopeFor} */
|
|
716
605
|
dedupScopeFor(kind: Kind): DedupScope;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fileTreeMemoryStore.d.ts","sourceRoot":"","sources":["../../../src/packlets/store/fileTreeMemoryStore.ts"],"names":[],"mappings":"AAKA,OAAO,EAAQ,OAAO,EAAE,MAAM,EAAyC,MAAM,eAAe,CAAC;AAC7F,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAGL,UAAU,EACV,QAAQ,EACR,cAAc,EAEd,aAAa,EAGb,YAAY,EACZ,IAAI,EAEJ,QAAQ,EACR,cAAc,EACd,aAAa,
|
|
1
|
+
{"version":3,"file":"fileTreeMemoryStore.d.ts","sourceRoot":"","sources":["../../../src/packlets/store/fileTreeMemoryStore.ts"],"names":[],"mappings":"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"}
|