Confirmed loss of a later acknowledged memory save
Reviewed master at 886c36d8ebe861aa987059a1744d45b78797baae (v4.7.0). Suggested priority: P1, conditional data loss.
memory_manage holds an asyncio lock while awaiting a threaded save. Cancellation releases the lock although the synchronous atomic-file writer continues. That old snapshot can overwrite a later save which already returned success.
Persistence: _save_all_memory. REST memory mutations share the same lock/offloaded-save pattern.
Deterministic isolated reproduction
Use a disposable memory file, real StateTools/persistence methods and threading events. Pause a first save after its snapshot is captured, cancel its coroutine, complete a second save, then release the first writer.
after cancellation: lock free=True, worker finished=False
second result: Saved global note 'later'.
file before release: {'global': {'later': 'B'}}
file after old worker: {'global': {'cancelled': 'A'}}
Independently reproduced repeatedly and rerun by the parent. Values are synthetic; no actual memory store was touched.
Acceptance criteria
- Once the newer save succeeds, an earlier cancelled operation cannot publish a stale snapshot over it.
- Hold mutation ownership through physical worker completion or serialize read/modify/publication with equivalent ordering guarantees.
- Cover save, delete and REST mutation paths under cancellation and subsequent writes.
- Keep valid JSON atomicity, existing scope policy and memory injection behavior unchanged.
The file remains syntactically valid; the bug is lost updates, not reproduced JSON corruption. Behavior change: cancellation acknowledgment may wait for persistence cleanup. No source changes were made.
Confirmed loss of a later acknowledged memory save
Reviewed
masterat886c36d8ebe861aa987059a1744d45b78797baae(v4.7.0). Suggested priority: P1, conditional data loss.memory_manageholds an asyncio lock while awaiting a threaded save. Cancellation releases the lock although the synchronous atomic-file writer continues. That old snapshot can overwrite a later save which already returned success.Persistence:
_save_all_memory. REST memory mutations share the same lock/offloaded-save pattern.Deterministic isolated reproduction
Use a disposable memory file, real StateTools/persistence methods and threading events. Pause a first save after its snapshot is captured, cancel its coroutine, complete a second save, then release the first writer.
Independently reproduced repeatedly and rerun by the parent. Values are synthetic; no actual memory store was touched.
Acceptance criteria
The file remains syntactically valid; the bug is lost updates, not reproduced JSON corruption. Behavior change: cancellation acknowledgment may wait for persistence cleanup. No source changes were made.