feat: improve memory guardrails and live activity tracking#35
Merged
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Pull request overview
This PR tightens durable-memory guardrails and improves the reliability of iOS Live Activity updates by moving job-tracking into a testable state machine and coalescing APNs update pushes. It also introduces a persistence protocol for easier mocking and adds substantial unit test coverage around AppState.
Changes:
- Refactor Live Activity job tracking into
JobActivityTrackerand throttle/coalesce Live Activity update pushes to avoid APNs budget exhaustion. - Add explicit-memory-intent detection and stricter acceptance rules for
ide__memory_add, plus system-prompt memory injection support. - Add new unit tests for
AppState, memory intent guardrails, and the Live Activity job tracker; introduce a persistence service protocol to enable mocking.
Reviewed changes
Copilot reviewed 21 out of 21 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| RxCodeTests/MemoryIntentTests.swift | Adds tests for explicit memory intent detection and system-prompt injection rules. |
| RxCodeTests/AppStateTests.swift | Adds extensive unit test coverage for AppState behavior using a mocked persistence layer. |
| RxCodeTests/AppStateProjectSwitchTests.swift | Updates test setup to disable background services for deterministic tests. |
| RxCode/Services/PersistenceService.swift | Introduces AppStatePersistenceService protocol and makes PersistenceService conform for mockability. |
| RxCode/Services/OpenAISummarizationService.swift | Updates memory-extraction prompt to require explicit intent and reduce max memories returned. |
| RxCode/Services/MobileSyncService+LiveActivity.swift | Switches to JobActivityTracker and adds throttled/coalesced Live Activity update pushes. |
| RxCode/Services/MobileSyncService+EventDispatch.swift | Cancels pending coalesced pushes on dismissal and updates token registration handling. |
| RxCode/Services/MobileSyncService.swift | Adds job-tracker state, push throttling state, and cancels pending pushes on stop. |
| RxCode/Services/IDEServer/IDEMCPServer.swift | Adds MCP tool annotations for read-only tools in descriptors. |
| RxCode/Services/IDEServer/AppState+IDEToolHandling.swift | Adds guardrails for ide__memory_add using explicit-intent acceptance logic. |
| RxCode/Services/CodexAppServer+Turn.swift | Handles MCP elicitation permission requests and centralizes approval-decision logic. |
| RxCode/Services/CodexAppServer+Protocol.swift | Tightens guidance around memory usage (explicit intent only, avoid transient details). |
| RxCode/Services/ClaudeService+Process.swift | Mirrors updated memory tool guidance for Claude Code integration. |
| RxCode/App/AppState+MemoryIntent.swift | Adds phrase-based detection for explicit memory intent and system-prompt injection eligibility. |
| RxCode/App/AppState+CrossProject.swift | Injects both “system prompt” memories and related memory hits into prompt context. |
| RxCode/App/AppState+Agents.swift | Adds system-prompt memory retrieval and splits injected memory into “always apply” vs “related hits”. |
| RxCode/App/AppState.swift | Adds injectable persistence + startBackgroundServices flag to support deterministic tests. |
| RxCode.xcodeproj/project.pbxproj | Registers the new test files in the Xcode project. |
| Packages/Tests/RxCodeCoreTests/JobActivityTrackerTests.swift | Adds Swift Testing coverage for the new job-tracking state machine. |
| Packages/Sources/RxCodeCore/Models/JobActivityTracker.swift | Introduces the JobActivityTracker and shared JobContent model in RxCodeCore. |
| Packages/Sources/RxCodeCore/Backend/IDEToolRegistry.swift | Updates the ide__memory_add tool description to reflect explicit-intent requirements. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+19
to
+26
| func systemPromptMemoryItems(projectId: UUID?) async -> [MemoryItem] { | ||
| let items = await memoryService.allMemories() | ||
| return items.filter { item in | ||
| if let memoryProjectId = item.projectId { | ||
| guard memoryProjectId == projectId else { return false } | ||
| } | ||
| return Self.shouldInjectMemoryIntoSystemPrompt(item) | ||
| } |
Comment on lines
+74
to
+91
| guard memoryEnabled, memoryInjectEnabled, !systemItems.isEmpty || !relatedHits.isEmpty else { return "" } | ||
|
|
||
| let systemIds = Set(systemItems.map(\.id)) | ||
| let systemLines = systemItems.enumerated().map { idx, item in | ||
| "\(idx + 1). \(item.content)" | ||
| }.joined(separator: "\n") | ||
| let relatedLines = relatedHits | ||
| .filter { !systemIds.contains($0.item.id) } | ||
| .prefix(memoryMaxContextItems) | ||
| .enumerated() | ||
| .map { idx, hit in | ||
| "\(idx + 1). \(hit.item.content)" | ||
| } | ||
| .joined(separator: "\n") | ||
| let sections = [ | ||
| systemLines.isEmpty ? nil : "Always apply these saved user preferences and recurring instructions:\n\(systemLines)", | ||
| relatedLines.isEmpty ? nil : "Related memories for this turn:\n\(relatedLines)" | ||
| ].compactMap { $0 }.joined(separator: "\n\n") |
Comment on lines
259
to
+265
| let scope = arguments["scope"]?.stringValue ?? "project" | ||
| let kind = arguments["kind"]?.stringValue ?? "fact" | ||
| guard Self.shouldAcceptAgentMemoryAdd(content: content, kind: kind) else { | ||
| throw IDEToolError.invalidArguments( | ||
| "memory_add requires an explicit user preference, future instruction, or remember-this request" | ||
| ) | ||
| } |
Comment on lines
+230
to
+238
| func testSetSessionModelUpdatesWindowStateSessionStateAndProjectDefault() async { | ||
| let project = makeProject("A") | ||
| appState.projects = [project] | ||
| window.selectedProject = project | ||
| window.currentSessionId = "session" | ||
|
|
||
| appState.setSessionModel("gpt-5.4", provider: .codex, in: window) | ||
| try? await Task.sleep(nanoseconds: 50_000_000) | ||
|
|
Contributor
Author
|
🎉 This PR is included in version 1.9.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
RxCode — live-activity-fix
liveactivitypush issues and optimizing job state coalescing.isReadfreeze guard and relocating the job-tracking state machine intoJobActivityTracker.swift.Threads