LearnNewsExamplesServices
Frontmatter
id15126
titleBound session-summary discovery memory usage
stateOpen
labels
enhancementaitestingperformance
assigneesneo-gpt-emmy
createdAt12:47 PM
updatedAt12:51 PM
githubUrlhttps://github.com/neomjs/neo/issues/15126
authorneo-gpt
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
milestonev13.2

Bound session-summary discovery memory usage

Open Backlog/active-chunk-5 enhancementaitestingperformance
neo-gpt
neo-gpt commented on 12:47 PM

Context

A maintainer reviewing Discussion #9739 independently noticed that SessionService.findSessionsToSummarize() paginates safely but retains every fetched memory and summary metadata object until each full scan completes. A 2026-07-13 code-level V-B-A confirmed the observation in current dev.

This is a bounded Memory Core performance hardening ticket. It does not change which sessions qualify for summarization or how summaries are generated.

Live duplicate sweep: latest 20 open issues plus recent all-state A2A claims checked at 2026-07-13T10:46Z. Targeted GitHub, Knowledge Base, Memory Core, and archived-ticket searches found no equivalent issue. Historical #7864 added configurable pagination and the safety break; it did not address full-scan retention.

The Problem

findSessionsToSummarize() scans the all-time memory collection and existing session summaries in pages. The method currently:

  1. concatenates every memory metadata row into allMetadatas;
  2. groups that complete array into per-session count/last-activity state;
  3. concatenates every summary metadata row into allSummaryMetadatas;
  4. groups that complete array into the summary-count map.

The safety ceiling permits up to 1000 pages — documented in code as as many as 2 million records — so peak retained JS metadata grows with total collection size even though the decision only needs:

  • per-session memory count;
  • per-session newest activity timestamp;
  • per-session last summarized memoryCount.

No production OOM is asserted here; the verified defect is the unnecessary O(total records) retention shape on an all-time maintenance scan.

The Architectural Reality

  • ai/services/memory-core/SessionService.mjs#findSessionsToSummarize owns the candidate calculation.
  • Chroma pagination remains the correct collection-read boundary.
  • Existing churn gates, current-session exclusion, externally-active session handling, timestamp normalization, and count-mismatch semantics are already encoded after the scan and must remain byte-for-byte equivalent at the returned session-id boundary.
  • summarizeSessions() already caps the drain per sweep through maxSessionsPerSummarySweep; that bounds work after discovery but does not bound discovery retention.

The Agent OS structure map was executed on 2026-07-13. This is an in-place method/spec change; no new service or directory is needed.

The Fix

Aggregate each page into the final bounded maps as it arrives:

  1. Memory pages update Map<sessionId, {count, lastActivity}> directly, then release the page.
  2. Summary pages update Map<sessionId, memoryCount> directly, then release the page.
  3. Preserve the configured page size, offset progression, short-page termination, empty-page termination, safety break, and existing timestamp resolver.
  4. Keep candidate filtering and return semantics unchanged.
  5. Add a many-page fixture that proves retention is proportional to distinct sessions plus one page, not total memory rows.

Contract Ledger Matrix

Target Surface Source of Authority Proposed Behavior Fallback / Edge Case Docs Evidence
findSessionsToSummarize() return value Existing method contract and focused specs Same candidate ids for the same memory/summary pages Collection error preserves current caller-visible failure behavior Method JSDoc Before/after parity fixture
Memory scan aggregation Memory metadata sessionId, timestamp, name Incremental count + latest timestamp per session Rows without sessionId remain ignored Method JSDoc Many-page bounded-retention spec
Summary scan aggregation Summary metadata sessionId, memoryCount Incremental latest map equivalent to current scan order Rows without sessionId remain ignored Method JSDoc Duplicate-session summary fixture
Pagination guard Existing configured limit + safety break Unchanged offset/short-page/empty-page termination Offset-blind/repeated-page behavior remains explicitly bounded Existing logs/JSDoc Pagination regression specs

Decision Record impact

None. This is an allocation-shape optimization inside the accepted Memory Core session-summary contract.

Decision Record

Not needed. Discussion #9739 is the observation source, not an architectural graduation authority for this repair.

Acceptance Criteria

  • The method no longer builds allMetadatas or allSummaryMetadatas full-scan arrays.
  • Memory pages aggregate directly into per-session count + latest-activity state.
  • Summary pages aggregate directly into the per-session summary-count map.
  • Existing eligibility behavior remains unchanged for unsummarized sessions, count mismatches, current session, externally active sessions, churn cooldown, future-skew timestamps, and unparseable timestamps.
  • Pagination semantics remain unchanged for empty, short, and full pages plus the safety break.
  • A deterministic many-page fixture demonstrates retained aggregation state scales with distinct sessions plus one page rather than total rows.
  • Focused SessionService unit coverage passes with no live Chroma writes.
  • PR evidence reports the fixture's page count, total synthetic rows, distinct sessions, and parity result.

Out of Scope

  • Changing the all-time discovery scope restored by #12823.
  • Changing the per-sweep execution cap from #13592.
  • Reworking Chroma's storage format, server-side aggregation, or summary-generation concurrency.
  • Adding token accounting or changing model-provider timeouts.
  • Temporal-pyramid synthesis or Bird-View rendering.

Avoided Traps

  • Reduce the 2M safety ceiling: lowers the symptom but can silently miss sessions.
  • Fetch only ids: eligibility needs count and timestamp metadata.
  • Move the scan into a new service: adds a boundary without changing the allocation problem.
  • Conflate discovery with the bounded drain: maxSessionsPerSummarySweep limits processing, not the full pre-scan.

Related

All-time scan restoration: #12823
Bounded summary drain: #13592
Temporal-pyramid consumer: #12679
Observation source: Discussion #9739

Origin Session ID: 837ad74b-c2d2-413d-9aab-b7165a93a82a

Retrieval Hint: SessionService findSessionsToSummarize allMetadatas pagination 2M retention
Retrieval Hint: Discussion 9739 nested Memory Core scalability observation