Shipped in v1.6.0. Off by default — the zero-config posture is preserved. Enable via
config.memory.enabled = True or a memory: block in YAML.What it does
Learning Memory is a persistent store of(id_a, id_b, decision) corrections plus a learner that turns enough corrections into threshold adjustments.
- Pipeline applies corrections automatically.
dedupe_dfandmatch_dfapply stored corrections after scoring (hard1.0for approve, hard0.0for reject) and overlay learned threshold deltas before scoring. - Re-anchors via
record_hash. Corrections survive row reordering and refresh. If a correction’s row IDs are no longer present, the system looks the entity up by content hash. Ambiguous rehydrations (duplicate rows) report asstale_ambiguousrather than silently misapplying. - Seven collection points. Every place a steward, an LLM, or an agent makes a decision writes a correction: review queue, boost tab,
unmerge_record/unmerge_cluster, LLM scorer, MCPagent_approve_reject, RESTPOST /reviews/decide, Pythonadd_correction(). - Threshold learning. Once a matchkey accumulates
threshold_min_corrections(default 10) corrections, the learner runs a trust-weighted grid search and stores per-matchkey threshold deltas. The pipeline overlays them on the next run. - Postflight reports impact. Every run with memory active emits
Memory: N applied, M stale, K stale-ambiguous, J unanchorable.
Quick walkthrough
Three commands. The data and the config don’t change between runs — the system improves because it remembers.goldenmatch.yml:
y approve, n reject, s skip — and writes decisions to .goldenmatch/memory.db with source=steward, trust=1.0.
goldenmatch memory learn (or the auto-learn pass on the next pipeline call) tunes that matchkey’s threshold so future runs need fewer corrections.
Configuration
MemoryConfig lives at config.memory. Top-level YAML:
Postgres backend:
CLI
Thegoldenmatch memory subgroup exposes the store directly.
Python API
After a pipeline run, every result also carries a
memory_stats field:
MCP
Six MCP tools bring Learning Memory into Claude Desktop / Code. Total tool count is now 69.
A natural-language workflow against an MCP-connected goldenmatch run:
“Show me uncertain pairs from the last goldenmatch run on customers.csv, then mark rows 17 and 23 as not-a-match because they have different EINs.”The host LLM calls
list_corrections -> add_correction -> learn_thresholds.
How it works
- Trust-weighted upsert. Every correction has a
trustscore (steward/unmerge1.0,agent/llm0.5). New corrections only override existing ones when their trust is at least as high. - Dual-hash staleness. Each correction stores both a
field_hash(only the matchkey fields) and arecord_hash(all columns). On apply, if either hash diverges from the live data, the correction is reportedstalerather than applied — it would no longer be safe. - Re-anchoring. When a correction’s stored
(id_a, id_b)are not present in the current frame, the system looks both rows up byrecord_hash. Single hits re-anchor cleanly; multiple hits reportstale_ambiguous; no hits reportunanchorable. Ambiguous and unanchorable corrections are not applied. - Stale persistence. Stale corrections are enqueued to a sibling SQLite review queue (
.goldenmatch/review_queue.db) so the nextgoldenmatch reviewinvocation surfaces them for human re-decision. - Threshold learner. A trust-weighted grid search picks the threshold that maximizes agreement with the stored decisions for that matchkey. Learned deltas overlay before the next scoring pass.
docs/superpowers/specs/2026-05-04-learning-memory-completion.md for readers who want algorithm-level detail.
When to enable
- Always, if you have stewards reviewing borderline pairs. Their decisions otherwise evaporate.
- Always, if you re-run the same dataset on a schedule. The same false positives shouldn’t keep coming back.
- Probably not, for one-shot dedupes on data you’ll never see again.
- Probably not, if you need byte-for-byte reproducible output (e.g. DQBench parity runs). Use
auto_configure_df(df, strict=True)and leave memory off.