From d4c47a387e1a83940eafa2ce6073ba6bd590db7c Mon Sep 17 00:00:00 2001 From: Cal Corum Date: Fri, 20 Feb 2026 00:47:07 -0600 Subject: [PATCH] store: Fix: Race condition in cognitive-memory _save_state loses last_reflection timestamp when daily+weekly timers collide --- ...ive-memory-save-state-loses-last-59268a.md | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 graph/fixes/fix-race-condition-in-cognitive-memory-save-state-loses-last-59268a.md diff --git a/graph/fixes/fix-race-condition-in-cognitive-memory-save-state-loses-last-59268a.md b/graph/fixes/fix-race-condition-in-cognitive-memory-save-state-loses-last-59268a.md new file mode 100644 index 00000000000..4c306045b60 --- /dev/null +++ b/graph/fixes/fix-race-condition-in-cognitive-memory-save-state-loses-last-59268a.md @@ -0,0 +1,30 @@ +--- +id: 59268a95-4712-48b4-bccb-6171c7885301 +type: fix +title: "Fix: Race condition in cognitive-memory _save_state loses last_reflection timestamp when daily+weekly timers collide" +tags: [cognitive-memory, fix, race-condition, systemd, state-management, atomicity] +importance: 0.8 +confidence: 0.8 +created: "2026-02-20T06:47:07.701221+00:00" +updated: "2026-02-20T06:47:07.701221+00:00" +--- + +# Race Condition in _save_state Corrupts last_reflection Timestamp + +## Symptom +REFLECTION.md showed "Last reflection: never" despite the weekly reflect timer having run successfully. + +## Root Cause +Two concurrent issues: + +1. **Timer collision**: The daily timer (decay) and weekly timer (reflect) could fire simultaneously. `OnCalendar=weekly` resolves to Mon midnight, which overlaps with `OnCalendar=daily` on Mondays. Both processes load and save `_state.json` concurrently. + +2. **Non-atomic writes with silent failure**: `_save_state()` would overwrite `_state.json` without first merging existing state, so decay's write could clobber the `last_reflection` key written by reflect. Additionally, `_load_state()` silently caught `JSONDecodeError` and returned an empty default dict, permanently losing the key on any write collision. + +## Fix +1. `_save_state()` now merges with existing on-disk state before writing (read-modify-write pattern). +2. Writes use atomic `tempfile + os.replace()` to prevent partial writes. +3. Weekly timer changed from `OnCalendar=weekly` to `OnCalendar=Sun *-*-* 02:00:00` to avoid midnight collision with the daily timer. + +## Commit +Commit `7f120f8` in the cognitive-memory repo.