Skip to content

fix(memory): prevent config ABA fence bypass - #1972

Merged
zerob13 merged 4 commits into
devfrom
fix/memory-config-aba-fence
Jul 14, 2026
Merged

fix(memory): prevent config ABA fence bypass#1972
zerob13 merged 4 commits into
devfrom
fix/memory-config-aba-fence

Conversation

@yyhhyyyyyy

@yyhhyyyyyy yyhhyyyyyy commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator
  • Generalize the per-Agent generation into an execution epoch covering memory enablement and embedding changes.
  • Bind queued extraction and continuations to the Agent identity and execution token captured at admission.
  • Propagate builtin memory configuration changes to affected inheriting Agents.
  • Fence recall, search, and injection results across asynchronous boundaries.
  • Add ABA, queue, inheritance, lifecycle, and error-propagation regression coverage.

Summary by CodeRabbit

  • Bug Fixes

    • Prevented stale memory operations (recall/search/injection/extraction and queued continuations) from committing after memory-enabled/config transitions or session agent reassignment.
  • Enhancements

    • Added execution-fencing with per-agent tokens/epochs so eligible work continues safely while stale results are dropped without cursor/anchor/accounting pollution.
    • Added management API to list resolved managed DeepChat agent configurations.
  • Documentation

    • Updated/added specs and plans for the execution-fence model and operational invalidation semantics.
  • Tests

    • Expanded ABA/queue/session fencing and maintenance fan-out coverage with stronger timing and token checks.

@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a unified per-agent execution token and configuration fingerprint model for memory operations. Runtime, maintenance, extraction, retrieval, injection, provider cancellation, agent configuration resolution, and regression tests now reject stale work across destructive and enabled/embedding ABA transitions.

Changes

Memory execution fence

Layer / File(s) Summary
Execution fence contract
docs/architecture/..., docs/issues/memory-config-aba-fence/*
Documents read versus execution epochs, token-bound queue admission, selective configuration invalidation, lifecycle rules, and validation criteria.
Execution identity and runtime state
src/main/presenter/memoryPresenter/core/*, src/main/presenter/memoryPresenter/context.ts, scripts/lib/memory-architecture-guard.mjs, test/main/presenter/memoryRuntimeContext.test.ts
Adds execution-token and configuration-fingerprint helpers, per-agent generation state, token validation, and tagged provider cancellation errors.
Resolved configuration propagation
src/main/agent/deepchat/*, src/main/presenter/agentRepository/*, src/main/presenter/memoryPresenter/index.ts, src/main/presenter/memoryPresenter/ports.ts, test/main/presenter/memory/maintenanceService.test.ts
Enumerates resolved DeepChat configurations and synchronizes execution identity selectively across managed agents.
Token-bound extraction execution
src/main/agent/deepchat/memory/memoryRuntimeCoordinator.ts, src/main/presenter/agentRuntimePresenter/*, test/main/agent/deepchat/memory/*, test/main/presenter/agentRuntimePresenter/*
Carries agent identity and execution tokens through contribution, queued extraction, chunk processing, continuations, and session changes.
Retrieval, injection, and provider fencing
src/main/presenter/memoryPresenter/services/retrievalService.ts, src/main/presenter/memoryPresenter/infra/*, test/main/presenter/memory/*, test/main/presenter/memoryExtraction.test.ts
Revalidates execution continuity across async retrieval and injection work, suppresses stale side effects, preserves real errors, and standardizes provider abort classification.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant AgentRuntime
  participant MemoryRuntimeCoordinator
  participant MemoryPresenter
  participant RetrievalService
  participant MemoryProviderGateway
  participant VectorStoreManager
  AgentRuntime->>MemoryRuntimeCoordinator: contribute session memory
  MemoryRuntimeCoordinator->>MemoryPresenter: capture execution token
  MemoryPresenter->>RetrievalService: build injection or retrieve
  RetrievalService->>MemoryProviderGateway: run embedding request
  RetrievalService->>VectorStoreManager: query memory vectors
  VectorStoreManager-->>RetrievalService: return retrieval data
  RetrievalService-->>MemoryPresenter: return fenced result
  MemoryPresenter-->>MemoryRuntimeCoordinator: return injection or null
  MemoryRuntimeCoordinator->>MemoryRuntimeCoordinator: validate token before accounting and anchors
Loading

Possibly related PRs

Suggested reviewers: zerob13

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately captures the main change: preventing a memory config ABA fence bypass.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ 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 fix/memory-config-aba-fence

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.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/main/agent/deepchat/memory/memoryRuntimeCoordinator.ts (1)

370-377: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Fence the extraction write against session-agent reassignment.

extractAndStore can persist under executionToken.agentId while awaited. If the session switches Agents during that call, Line 377 only suppresses the cursor and anchor afterward—the stale memory write has already occurred.

Pass a session-assignment fence into the persistence boundary, or invalidate/abort the write before its commit when the session Agent changes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/agent/deepchat/memory/memoryRuntimeCoordinator.ts` around lines 370
- 377, The extraction persistence path in memoryRuntimeCoordinator’s
extractAndStore call must be fenced against session-agent reassignment during
the await. Pass the current session assignment or executionToken fence into
extractAndStore, and ensure the persistence boundary validates it immediately
before committing so reassigned sessions cannot store stale memory; retain the
existing post-call canContinueExecution check for cursor and anchor updates.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/main/agent/deepchat/memory/memoryRuntimeCoordinator.ts`:
- Around line 316-318: Update the queue-admission flow around ensureSessionEpoch
and task so the session epoch is captured when the task is enqueued, before it
can wait behind earlier tasks. Pass that captured epoch to the later validation
and task invocation, and do not call ensureSessionEpoch at task execution time;
preserve expectedEpoch validation and discard tasks whose admission epoch is no
longer current.

In `@src/main/presenter/memoryPresenter/core/executionIdentity.ts`:
- Around line 21-25: Update memoryEmbeddingFingerprint to use an unambiguous
encoding of providerId and modelId, such as JSON.stringify on the ordered pair,
while preserving the existing null behavior and overload return types.

In `@src/main/presenter/memoryPresenter/core/providerCancellation.ts`:
- Around line 1-12: Separate capacity-exhaustion errors from stale-cancellation
errors in createMemoryProviderAbortError and isMemoryProviderAbortError.
Introduce a distinct code or reason for provider request capacity exhaustion,
update providerGateway.ts to use it, and ensure retrievalService.ts only
suppresses execution-invalidation cancellations rather than all matching errors.

In `@test/main/presenter/memory/maintenanceService.test.ts`:
- Around line 1233-1264: Add teardown to the test using the MemoryPresenter
instance created in “runs builtin maintenance even when managed config
enumeration fails”: call await presenter.dispose() in the finally block before
restoring fake timers, ensuring cleanup runs even when assertions or timer
advancement fail.

---

Outside diff comments:
In `@src/main/agent/deepchat/memory/memoryRuntimeCoordinator.ts`:
- Around line 370-377: The extraction persistence path in
memoryRuntimeCoordinator’s extractAndStore call must be fenced against
session-agent reassignment during the await. Pass the current session assignment
or executionToken fence into extractAndStore, and ensure the persistence
boundary validates it immediately before committing so reassigned sessions
cannot store stale memory; retain the existing post-call canContinueExecution
check for cursor and anchor updates.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1922836d-b4b3-440c-ad37-8ace3e0621e6

📥 Commits

Reviewing files that changed from the base of the PR and between 868b5a8 and 1164be8.

📒 Files selected for processing (28)
  • docs/architecture/agent-memory-system/spec.md
  • docs/issues/memory-config-aba-fence/plan.md
  • docs/issues/memory-config-aba-fence/spec.md
  • docs/issues/memory-config-aba-fence/tasks.md
  • scripts/lib/memory-architecture-guard.mjs
  • src/main/agent/deepchat/deepChatAgentRepository.ts
  • src/main/agent/deepchat/memory/memoryRuntimeCoordinator.ts
  • src/main/presenter/agentRepository/index.ts
  • src/main/presenter/index.ts
  • src/main/presenter/memoryPresenter/context.ts
  • src/main/presenter/memoryPresenter/core/executionIdentity.ts
  • src/main/presenter/memoryPresenter/core/injectionPort.ts
  • src/main/presenter/memoryPresenter/core/providerCancellation.ts
  • src/main/presenter/memoryPresenter/index.ts
  • src/main/presenter/memoryPresenter/infra/providerGateway.ts
  • src/main/presenter/memoryPresenter/infra/vectorStoreManager.ts
  • src/main/presenter/memoryPresenter/injection.ts
  • src/main/presenter/memoryPresenter/ports.ts
  • src/main/presenter/memoryPresenter/services/retrievalService.ts
  • src/main/presenter/memoryPresenter/types.ts
  • test/main/agent/deepchat/memory/memoryRuntimeCoordinator.test.ts
  • test/main/presenter/agentRepository.test.ts
  • test/main/presenter/agentRuntimePresenter/agentRuntimePresenter.test.ts
  • test/main/presenter/memory/maintenanceService.test.ts
  • test/main/presenter/memory/retrievalService.test.ts
  • test/main/presenter/memory/serviceTestSupport.ts
  • test/main/presenter/memoryExtraction.test.ts
  • test/main/presenter/memoryRuntimeContext.test.ts

Comment thread src/main/agent/deepchat/memory/memoryRuntimeCoordinator.ts Outdated
Comment thread src/main/presenter/memoryPresenter/core/executionIdentity.ts
Comment thread src/main/presenter/memoryPresenter/core/providerCancellation.ts Outdated
Comment thread test/main/presenter/memory/maintenanceService.test.ts
yyhhyyyyyy and others added 2 commits July 14, 2026 17:43

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/main/presenter/agentRuntimePresenter/sessionSettingsCoordinator.ts`:
- Around line 130-145: Persist the reassigned agent ID alongside the other
session settings in the reassignment flow before or when calling
instance.setAgentId(nextAgentId). Update the relevant sessionStore persistence
method so newSessionsTable.agent_id is written with nextAgentId, ensuring
getSessionAgentId() restores the reassigned value after eviction or restart.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 47104c88-8f51-4c31-81ca-1b870c9d349c

📥 Commits

Reviewing files that changed from the base of the PR and between 66b606a and 033231f.

📒 Files selected for processing (3)
  • src/main/presenter/agentRuntimePresenter/index.ts
  • src/main/presenter/agentRuntimePresenter/sessionSettingsCoordinator.ts
  • test/main/presenter/agentRuntimePresenter/agentRuntimePresenter.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/main/presenter/agentRuntimePresenter/agentRuntimePresenter.test.ts

Comment on lines +130 to +145
this.deps.sessionStore.updateSessionConfiguration(
sessionId,
nextProviderId,
nextModelId,
buildPersistedGenerationSettingsReplacement(generationSettings),
permissionMode
)

const instance = this.deps.getInstance(sessionId)
instance.setRuntimeState({
status: state?.status ?? 'idle',
providerId: nextProviderId,
modelId: nextModelId,
permissionMode
})
instance.setAgentId(nextAgentId)

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.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Confirm whether agent_id persistence happens inside updateSessionConfiguration or elsewhere.
rg -nP -C10 'updateSessionConfiguration\s*\(' --type ts src/main/presenter/agentRuntimePresenter/sessionStore.ts
rg -nP '\bagent_id\b' --type ts -C3 src/main
rg -nP '\.setSessionAgentContext\s*\(' --type ts -C5 src/main

Repository: ThinkInAIXYZ/deepchat

Length of output: 50378


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- sessionStore updateSessionConfiguration ---'
sed -n '182,240p' src/main/presenter/agentRuntimePresenter/sessionStore.ts

echo
echo '--- sessionSettingsCoordinator relevant region ---'
sed -n '110,170p' src/main/presenter/agentRuntimePresenter/sessionSettingsCoordinator.ts

echo
echo '--- index getSessionAgentId references ---'
rg -n -C4 'getSessionAgentId|agent_id|session agent id|setSessionAgentId|setSessionAgentContext' src/main/presenter/agentRuntimePresenter/index.ts src/main/presenter/agentRuntimePresenter -g '*.ts'

Repository: ThinkInAIXYZ/deepchat

Length of output: 42962


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- search for agent id persistence/update helpers ---'
rg -n -C3 'update.*agent|agent_id.*update|set.*agent.*context|newSessionsTable.*agent_id|updateSessionAgent|setSessionAgentId|agentId.*persist' src/main/presenter/agentRuntimePresenter src/main -g '*.ts'

echo
echo '--- newSessionsTable methods ---'
rg -n -C4 'class .*NewSessionsTable|interface .*NewSessionsTable|update.*agent_id|get.*agent_id|insert.*agent_id|agent_id' src/main -g '*newSessions*' -g '*.ts'

echo
echo '--- SessionAgentContextUpdate type ---'
rg -n -C4 'type SessionAgentContextUpdate|interface SessionAgentContextUpdate' src/main -g '*.ts'

Repository: ThinkInAIXYZ/deepchat

Length of output: 50378


Persist the reassigned agent id
In src/main/presenter/agentRuntimePresenter/sessionSettingsCoordinator.ts:130-145, instance.setAgentId(nextAgentId) only updates memory. getSessionAgentId() rehydrates from newSessionsTable.agent_id, so this reassignment will revert after eviction/restart unless nextAgentId is written to persistence too.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/presenter/agentRuntimePresenter/sessionSettingsCoordinator.ts`
around lines 130 - 145, Persist the reassigned agent ID alongside the other
session settings in the reassignment flow before or when calling
instance.setAgentId(nextAgentId). Update the relevant sessionStore persistence
method so newSessionsTable.agent_id is written with nextAgentId, ensuring
getSessionAgentId() restores the reassigned value after eviction or restart.

@zerob13
zerob13 merged commit a461415 into dev Jul 14, 2026
4 checks passed
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