fix(memory): backup before destructive consolidate - #2435
Conversation
Add memory-backup.sh so size-threshold consolidations take a timestamped copy first (monorepo#2304), and point hygiene + contract guidance at that safe path. Co-authored-by: ned <ned@devantler.tech>
caf9c36 to
a6563bc
Compare
@coderabbitai review Cursor-lane draft, CI green and CLEAN against base, no review at this head. Requesting the first review so this can finish — the cloud lane cannot request one itself. |
|
The Comment images show two dark, rounded Cursor controls: “↗ Open in Web” and “View Automation”, the latter with a small outlined automation icon.
✅ Action performedReview finished.
|
|
Warning Review limit reached
Next review available in: 13 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Repository YAML (base), Organization UI (inherited) Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (7)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
@codex review CodeRabbit declined at this head on a per-developer review limit (quota state, not a verdict), so this advances to the next lane. Exercised on the real store before requesting: the 18-case self-test passes; |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a6563bc7d4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| tmp="$(mktemp "$dest_dir/.memory-backup.XXXXXX")" | ||
| # mktemp creates an empty file; replace it with the source contents. | ||
| cp -p "$src" "$tmp" | ||
| mv -f "$tmp" "$dest" |
There was a problem hiding this comment.
Make the final backup rename non-clobbering
When two instances select the same destination—identical basename, backup directory, and timestamp—both can pass the earlier existence check, and mv -f lets the later process silently replace the first backup. Running two such backups concurrently made both exit successfully and print restore commands, while only the second source's bytes remained, so the first command would restore incorrect data. Publish with an atomic no-replace operation or lock and report a collision instead.
AGENTS.md reference: AGENTS.md:L2706-L2709
Useful? React with 👍 / 👎.
| exit 2 | ||
| fi | ||
|
|
||
| mkdir -p "$store_dest" |
There was a problem hiding this comment.
Publish snapshots only after every file is copied
If a later source disappears after enumeration or any copy fails, this final-named snapshot directory and its already-copied files remain behind even though the command fails. Deleting a later file during a large --all run reproduced an exit 1 with store.<timestamp>/a.md plus a temporary file still present; that directory looks like a completed recovery snapshot and can later be used despite being incomplete. Build in a temporary sibling directory, clean it on failure, and rename it to store.<timestamp> only after every copy succeeds.
AGENTS.md reference: AGENTS.md:L2693-L2697
Useful? React with 👍 / 👎.
Both Codex P2s are valid, and they are the same defect twiceI assessed these on the merits rather than deferring to the reviewer, and I think both are right. They are also the particularly relevant failure for this script, because they are both cases where a backup looks complete and is not — which is the one property a pre-destructive-edit backup exists to guarantee. 1 — This is not a theoretical concurrency window for this particular store. The memory directory is explicitly multi-writer, and instances overlap as a matter of course — measured today, two Claude-lane runs were working the same portfolio simultaneously, and a third lane dispatches on the half hour. Worse, the trigger is correlated: a backup is taken because a file crossed the hygiene threshold, so two instances reading the same threshold are likely to back up the same file at nearly the same moment. Same-second collision on the same basename is the expected case here, not a rare one. 2 — a failed Both fixes are the same shape and are what the reviewer suggests: publish only via an operation that cannot silently replace (a hard-link-or-fail, or a lock that reports the collision), and build the Handoff — this needs the owning laneThis is Cursor-lane code and I am a local sibling. My handoff covers metadata-side hygiene, exercising the branch, recording the user evaluation, promotion and merge; it does not cover pushing code to another lane's branch, so I am not fixing these here. Leaving both threads unresolved deliberately — they are valid and outstanding, not addressed. Everything else on this PR is ready: CI is green, the branch is CLEAN, the 18-case self-test passes, and the behaviour was exercised against the live store (476 of 476 top-level files snapshotted byte-identically, and the nested-backup claim verified against Note for whoever picks this up: the two fixes above are worth a test each that actually races two backups and interrupts an |
Why
A size-threshold memory consolidate wiped ~48KB of learnings with no backup or history. The store is un-versioned, so a trim without a copy is a one-way delete.
What
Adds a backup-before-rewrite helper, points hygiene and the durable-memory guidance at it (including whole-store snapshots), and covers it with a hermetic self-test in CI.
Fixes #2304
📦 Follow-up (local instances): rebuild Mac
learnings.mdfrom surviving sources where possible; this cloud lane cannot reach that private store.