v2.19.0 — Learned reasoning patterns stop disappearing
Per-model category coverage could sit near zero while mining reported patterns learned, run after run. Three defects were stacked on top of each other.
Consolidation merged learned patterns away as fast as mining produced them
_merge builds one fiber from a group of overlapping ones, and the merged fiber replaces its members' metadata wholesale before the members are deleted. Learned reasoning patterns are the most exposed fibers in the graph to that: every pattern in a category hangs off that category's concept neuron, and shared neurons are exactly what the overlap check keys on. A mining run's whole output collapsed into a single metadata-less Merged from N fibers row — _source_model, _reasoning_category and _reasoning_confidence gone — and coverage fell back to zero in the same cycle that produced the patterns.
The same defect had already been fixed for _habit_pattern; its guard simply never covered _reasoning_pattern. Both markers now share one guard.
Lost patterns can now be rebuilt
Distillation marks every trace it consumes as processed, including the ones it discards, and nothing could clear that flag. Re-running the miner could not help: the transcript re-scan finds the same traces, ingest deduplicates on trace_hash, and distillation only reads unprocessed rows.
reprocess re-opens that backlog — a checkbox beside Backfill in the dashboard, smem reasoning mine --reprocess, or reprocess: true on smem_reasoning. Repeating it is safe: pattern signatures make a second pass a no-op rather than a duplicate-maker. It respects mining_models (globs are resolved against the models actually present, and a filter matching nothing re-opens nothing rather than widening into a blanket reset), and dry_run still wins, since re-opening the backlog is a write.
Traces already dropped by retention_days need --backfill to be re-ingested from the transcripts first; rotated transcripts are gone for good.
A per-model pattern target above 100 was silently reduced
pattern_targets was clamped to 100 on load and rejected above 100 by the config endpoint, with nothing announcing either — a higher target written into config.toml came back as 100 on the next read while thousands of staged traces still had patterns to give. Both sites now share MAX_PATTERN_TARGET (1000).
Status and pattern endpoints could mix two brains in one response
Traces are read with an explicit brain_id, but the fiber API has none and filters on whatever brain the storage instance is bound to, which the server never rebinds per request. A request carrying an X-Brain-ID for another brain returned one brain's traces beside another brain's patterns. DELETE /patterns?model= listed victims in one scope and deleted in another, reporting a count for rows it had not removed. Pattern reads and deletes now resolve under the same scope as the traces.
Upgrade notes
No migration required. If a brain's coverage was flattened by the merge defect, rebuild it with a single reprocess run:
smem reasoning mine --reprocessRaise pattern_targets first if a model has a large trace backlog — the old ceiling of 100 was often the binding limit rather than the available material.