@samesake/enrich
@samesake/enrich owns the enrichment and resolution brain. It is store-free and
performs model I/O only through closures supplied by the consumer.
Public surface
Section titled “Public surface”enrichandenrichRowexecute typed stages, derive surfaces, and return explicit ready, quarantined, or failed row outcomes.scoreCandidate,scoreBest, andclusterBatchimplement pure resolution scoring, threshold decisions, and offer grouping.contentHashandselectDirtysupport incremental work without owning persistence.scoreEnrichmentand its result types score predictions against gold attributes.createEnrichercomposes those cores with anEnrichStore, optional candidate provider, generation closure, embedding closure, and consumer-chosen concurrency.memoryStoreis a reference in-memory store for tests and local experiments.
EnrichStore is the durable row-state contract. It covers upsert, dirty loading,
optional hard deletion, enriched writes, failures, retries, and optional enriched-row/candidate access for
resolution. CandidateProvider supplies a shortlist; blocking is backend work, while
scoring remains pure.
The factory returns an Enricher with:
upsert(rows)remove(ids)enrich({ limit, concurrency })resolve({ limit })retryFailed({ limit })evaluate(gold)remove(ids) calls the store’s optional hard-delete capability and throws a clear error when the
store does not implement it. createEnricher does not schedule jobs, retry network calls, or run a
dead-letter queue. The application platform and its store own those concerns.
Example
Section titled “Example”import { createEnricher } from '@samesake/enrich';
const enricher = createEnricher({ collection, generate, embed, store,});
await enricher.upsert(rows);await enricher.enrich({ limit: 100 });Use the pure functions directly when the surrounding workflow already owns durable state. Use the factory when one application-owned store should coordinate the loop.