Skip to content

fix(memory): tighten persistence rules and add conversational events#522

Open
vsumner wants to merge 2 commits intomainfrom
codex/memory-observation-p1
Open

fix(memory): tighten persistence rules and add conversational events#522
vsumner wants to merge 2 commits intomainfrom
codex/memory-observation-p1

Conversation

@vsumner
Copy link
Copy Markdown
Collaborator

@vsumner vsumner commented Apr 1, 2026

Why

This is the first packet of the memory-evolution work. The immediate goal is to tighten what the persistence branch is allowed to save and to start recording the most important conversational corrections explicitly.

Before this change, the persistence prompt still allowed too much derivable or noisy state into durable memory, and the working-memory event surface did not have first-class types for user corrections or revised decisions. That made the next observation-memory work harder because the system was still losing important conversational pivots while retaining lower-value chatter.

Scope

This PR is intentionally narrow.

It includes prompt-discipline changes plus the first conversational working-memory event semantics. It does not yet expand the broader event vocabulary or improve working-memory rendering end to end.

What Changed

  • tightened automatic memory persistence guidance to exclude derivable repo state, git churn, and ephemeral task chatter
  • taught persistence runs to normalize relative dates into absolute timestamps and to treat stale recalled memory as something to verify, not blindly trust
  • added user_correction and decision_revised as working-memory event types and allowed memory_persistence_complete to persist them
  • replaced the conversational-event regression with deterministic eventual polling instead of a fixed sleep
  • included a minimal clippy cleanup in src/llm/model.rs because repo gates were red on this branch otherwise

Testing

  • just preflight
  • just gate-pr
  • cargo test -p spacebot persists_conversational_events -- --test-threads=1 --nocapture
  • cargo test -p spacebot test_event_type_roundtrip -- --test-threads=1 --nocapture

Notes

  • The src/llm/model.rs change is not part of the memory packet itself. It is the smallest repo-level lint fix needed to get just gate-pr green.
  • Follow-up work should expand the conversational event vocabulary and improve working-memory rendering so recent activity reads less like ops telemetry.

Note

Memory persistence now enforces stricter guard rails on what gets saved durably. The core changes include introducing user_correction and decision_revised event types to capture conversational inflection points, normalizing relative dates to absolute timestamps for cache stability, and filtering out derivable/transient data (repo state, git history, ephemeral task output). These constraints ensure memory captures semantically valuable pivots rather than noise. The MemoryPersistenceConfig docs now clarify that active persistence thresholds are configured via WorkingMemoryConfig rather than the legacy branch cadence. Updated tests verify both new event types round-trip correctly through the persistence pipeline.
Written by Tembo for commit af64604

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 1, 2026

Walkthrough

The PR extends the working memory event taxonomy by adding UserCorrection and DecisionRevised event types, updates memory persistence prompts and configuration documentation, refines event extraction guidance with ISO timestamp normalization and operational rules, and adjusts SSE parsing error handling in the LLM streaming code.

Changes

Cohort / File(s) Summary
Prompt & Instruction Templates
prompts/en/memory_persistence.md.j2, prompts/en/tools/memory_save_description.md.j2
Enhanced event extraction specification to distinguish user corrections and revised decisions; added guidance on normalizing relative time to ISO-like timestamps with timezone, and new operational rules to exclude ephemeral details and verify recalled memory against latest context.
Configuration Documentation
src/config/types.rs
Updated MemoryPersistenceConfig docs to label message_interval as legacy branch cadence, noting that runtime persistence now uses WorkingMemoryConfig thresholds instead.
Working Memory Event Types
src/memory/working.rs, src/tools/memory_persistence_complete.rs
Added UserCorrection and DecisionRevised variants to WorkingMemoryEventType with full lifecycle support (serialization, parsing, rendering); updated tool schema and event-type mapping logic; added integration test for new event types.
LLM Streaming Parsing
src/llm/model.rs
Refactored SSE trailing buffer JSON parsing error handling by consolidating standalone else branch with raw JSON fallback into combined conditional flow.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • jamiepine
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main changes: tightening memory persistence rules and adding support for conversational events (user_correction and decision_revised).
Description check ✅ Passed The description is directly related to the changeset, providing clear context about why the changes were made, what was changed, and how to test them.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/memory-observation-p1

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@vsumner vsumner marked this pull request as ready for review April 1, 2026 01:58
@vsumner vsumner requested a review from jamiepine April 1, 2026 01:58
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/tools/memory_persistence_complete.rs (1)

203-205: Consider logging when an unrecognized event type falls back to System.

When WorkingMemoryEventType::parse() returns None, the code silently falls back to System. This could mask LLM prompt drift or schema mismatches. A debug/trace log would aid troubleshooting without impacting normal operation.

🔍 Optional: Add trace-level logging for unrecognized event types
-                let event_type =
-                    crate::memory::WorkingMemoryEventType::parse(&event_input.event_type)
-                        .unwrap_or(crate::memory::WorkingMemoryEventType::System);
+                let event_type = match crate::memory::WorkingMemoryEventType::parse(&event_input.event_type) {
+                    Some(et) => et,
+                    None => {
+                        tracing::trace!(
+                            raw_event_type = %event_input.event_type,
+                            "unrecognized event_type, falling back to System"
+                        );
+                        crate::memory::WorkingMemoryEventType::System
+                    }
+                };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/tools/memory_persistence_complete.rs` around lines 203 - 205, The code
silently falls back to WorkingMemoryEventType::System when
WorkingMemoryEventType::parse(&event_input.event_type) returns None; add a
trace- or debug-level log in that branch to record the original
event_input.event_type and that the System fallback was used. Modify the logic
around the parse call that sets event_type (referencing
WorkingMemoryEventType::parse, event_input.event_type, and
WorkingMemoryEventType::System) to detect the None case and emit a trace/debug
message (e.g., using tracing::trace! or log::debug!) before assigning System so
unrecognized event types are visible during troubleshooting.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/tools/memory_persistence_complete.rs`:
- Around line 203-205: The code silently falls back to
WorkingMemoryEventType::System when
WorkingMemoryEventType::parse(&event_input.event_type) returns None; add a
trace- or debug-level log in that branch to record the original
event_input.event_type and that the System fallback was used. Modify the logic
around the parse call that sets event_type (referencing
WorkingMemoryEventType::parse, event_input.event_type, and
WorkingMemoryEventType::System) to detect the None case and emit a trace/debug
message (e.g., using tracing::trace! or log::debug!) before assigning System so
unrecognized event types are visible during troubleshooting.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6792852a-4058-476f-b3b6-d0df5f911645

📥 Commits

Reviewing files that changed from the base of the PR and between 66846e5 and af64604.

📒 Files selected for processing (6)
  • prompts/en/memory_persistence.md.j2
  • prompts/en/tools/memory_save_description.md.j2
  • src/config/types.rs
  • src/llm/model.rs
  • src/memory/working.rs
  • src/tools/memory_persistence_complete.rs

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.

1 participant