v0.13.0
latest2026-10-08A save whose parameters were swallowed into another field is refused instead of stored
+ Added
- +The save response says what was stored: the length of each field, which ones arrived empty, and which values came from a default. It warns when no type arrived, when an unknown argument such as memory_type was sent, and when a rule runs past 400 characters (the damaged median was 992, the clean median 306)
- +memgit doctor counts damaged memories by project, and memgit doctor --repair-markup splits them back into their fields: swallowed tags, related and supersedes merge into the real lists, a swallowed type or priority is restored, the timestamp is kept, and superseded memories are covered too. It is a dry run until --yes and writes one checkpoint. On the store it was built against it repaired 315 memories with 0 conflicts
✓ Fixed
- ✓save_memory refuses values that carry tool-call markup. A model sometimes closes a value with a tag named after the field, and the host then delivers the next parameters inside that value, so why, when, tags and type never arrive and the memory is stored with defaults. Measured on one machine: 748 of 3,025 save calls, every one answered ok. The refusal names the damaged field and the parameters found inside it, nothing is written, and the model retries in the same turn. Markup quoted on purpose inside backticks is allowed. Replayed over the 2,935 save calls still on disk, it refuses 725, and the only two loose matches it lets through quote the markup deliberately
- ✓Damaged text is no longer injected back into context. Exposure to a damaged memory raised one model's damage rate from 40.5% to 59.6%, because the markup reads as content. The session digest, the recall hook, the core guide and every read now show each field cut at the damage, and the store is never rewritten by a read