Skip to content

feat: memory retention expiry sweep (#6 follow-up)#58

Merged
BunsDev merged 1 commit into
mainfrom
feat/issue-6-retention
Jul 7, 2026
Merged

feat: memory retention expiry sweep (#6 follow-up)#58
BunsDev merged 1 commit into
mainfrom
feat/issue-6-retention

Conversation

@BunsDev

@BunsDev BunsDev commented Jul 7, 2026

Copy link
Copy Markdown
Member

The last deferred item from #6: adapter-side retention expiry.

What it does

  • Store: expire_memory_activity_before(cutoff) / expire_memory_activity(days) delete memory-audit rows older than the horizon. Revocations are deliberately never expired — an expired revocation would silently un-revoke memory. record_memory_activity now honors an explicit timestamp (empty → now), which makes the sweep deterministically testable.
  • Server: when [memory] retention_days is set, a background task sweeps on a 6-hour interval, with the first tick firing immediately so a stale audit is trimmed at boot.

Boundary

This expires the adapter's memory audit. The actual memory bytes live in coven-code and are expired there via the same retention_days the policy already forwards — the bilateral half, unchanged. Per-repo retention overrides (retention is currently global) could be a later nicety; not needed for the contract.

With this, every part of #6's design is implemented on the adapter side — nothing deferred remains.

Local gates: cargo check --all-targets + cargo clippy --all-targets -- -D warnings + cargo test --all (211 passed, 0 failed).

🤖 Generated with Claude Code

A periodic server sweep (first tick at boot, then every 6h) expires memory
audit rows older than retention_days; revocations are never expired, since an
expired revocation would silently un-revoke memory. record_memory_activity now
honors an explicit timestamp for deterministic sweeps/tests. Completes the last
deferred item of the memory governance contract.

Signed-off-by: Val Alexander <bunsthedev@gmail.com>
Copilot AI review requested due to automatic review settings July 7, 2026 06:38
@BunsDev
BunsDev merged commit cf69e52 into main Jul 7, 2026
2 checks passed
@BunsDev
BunsDev deleted the feat/issue-6-retention branch July 7, 2026 06:40

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Implements the adapter-side half of hosted memory retention expiry (issue #6 follow-up) by adding store APIs to expire old memory-audit rows and a server background task to sweep on a fixed interval when configured.

Changes:

  • Added Store::expire_memory_activity_before / Store::expire_memory_activity plus tests ensuring audit expiry doesn’t affect revocations.
  • Updated record_memory_activity to honor an explicit timestamp when provided (enabling deterministic tests/backfills).
  • Added a server-side background sweep that runs immediately on boot and then every 6 hours when memory.retention_days is set; updated docs/config notes accordingly.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
docs/memory-contract.md Updates contract status text to reflect retention expiry completion.
crates/store/src/lib.rs Adds audit-expiry APIs, adjusts timestamp handling for memory activity, and adds tests.
crates/server/src/main.rs Spawns periodic retention sweep task when configured.
config/example.toml Clarifies retention_days affects both runtime bytes and adapter audit expiry.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread crates/store/src/lib.rs
Comment on lines +757 to +761
let conn = conn.lock().expect("store mutex poisoned");
let n = conn.execute(
"DELETE FROM memory_activity WHERE at < ?1",
params![cutoff],
)?;
Comment thread crates/store/src/lib.rs
Comment on lines +753 to +761
pub async fn expire_memory_activity_before(&self, cutoff: &str) -> Result<usize> {
let conn = self.conn.clone();
let cutoff = cutoff.to_string();
tokio::task::spawn_blocking(move || {
let conn = conn.lock().expect("store mutex poisoned");
let n = conn.execute(
"DELETE FROM memory_activity WHERE at < ?1",
params![cutoff],
)?;
Comment thread crates/store/src/lib.rs
Comment on lines +611 to +617
// Honor an explicit timestamp when provided (tests/backfills);
// otherwise stamp the current time.
let at = if row.at.is_empty() {
now_rfc3339()
} else {
row.at.clone()
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants