Context
Carved from #13647 (parent; epic #13624; the gate itself is #13637's churn-gate, delivered by #13645) so the delivering PR has an honest close-target. The churn-gate in findSessionsToSummarize (ai/services/memory-core/SessionService.mjs) has two timestamp edge-cases, flagged by @neo-opus-ada in the #13645 review.
Live latest-open sweep: checked the latest 12 open issues at ~2026-06-20T21:20Z — no equivalent found.
The Problem
- Future-skew (correctness bug): the gate skips a session while
(nowMs - lastActivity) < churnCooldownMs. A clock-drifted memory (plausible across multi-machine / multi-tenant deployments) yields lastActivity > nowMs → the difference is negative → always < cooldown → the session is gated forever and never summarized (lost summarization).
- Unparseable timestamp: an unparseable/missing timestamp resolves to
lastActivity = 0 (falsy) → it bypasses the gate and stays eligible. That is the correct fail-open, but it was undocumented.
The Architectural Reality
findSessionsToSummarize builds per-session lastActivity via resolveGraphTimestampMs (returns null for unparseable). The churn-gate compares nowMs - lastActivity against swarmHeartbeat.idleThresholdMs.
The Fix
- Add an
idleMs >= 0 guard so a future-skewed timestamp is treated as eligible (summarize once) rather than perpetually gated.
- Document the unparseable-ts fail-open (
lastActivity = 0 → bypass).
Decision Record impact
none — pure correctness hardening of the existing gate; no config/API change.
Acceptance Criteria
Out of Scope
- The marker archived-filter (#13667 / PR #13668).
- The 45 projection-lag + the axis-3 archival.
Related
Parent: #13647. Epic: #13624. The gate: #13637 (delivered by #13645).
Origin Session ID: c4fcedd0-c449-4f8c-b368-e3ac0c0509ff
Retrieval Hint: "findSessionsToSummarize churn-gate future-skew idleMs guard unparseable timestamp fail-open #13647"
Context
Carved from #13647 (parent; epic #13624; the gate itself is #13637's churn-gate, delivered by #13645) so the delivering PR has an honest close-target. The churn-gate in
findSessionsToSummarize(ai/services/memory-core/SessionService.mjs) has two timestamp edge-cases, flagged by @neo-opus-ada in the #13645 review.Live latest-open sweep: checked the latest 12 open issues at ~2026-06-20T21:20Z — no equivalent found.
The Problem
(nowMs - lastActivity) < churnCooldownMs. A clock-drifted memory (plausible across multi-machine / multi-tenant deployments) yieldslastActivity > nowMs→ the difference is negative → always< cooldown→ the session is gated forever and never summarized (lost summarization).lastActivity = 0(falsy) → it bypasses the gate and stays eligible. That is the correct fail-open, but it was undocumented.The Architectural Reality
findSessionsToSummarizebuilds per-sessionlastActivityviaresolveGraphTimestampMs(returnsnullfor unparseable). The churn-gate comparesnowMs - lastActivityagainstswarmHeartbeat.idleThresholdMs.The Fix
idleMs >= 0guard so a future-skewed timestamp is treated as eligible (summarize once) rather than perpetually gated.lastActivity = 0→ bypass).Decision Record impact
none— pure correctness hardening of the existing gate; no config/API change.Acceptance Criteria
lastActivity > now) is eligible, not perpetually gated.SessionService.ChurnCooldown.spec.mjs.Out of Scope
Related
Parent: #13647. Epic: #13624. The gate: #13637 (delivered by #13645).
Origin Session ID: c4fcedd0-c449-4f8c-b368-e3ac0c0509ff Retrieval Hint: "findSessionsToSummarize churn-gate future-skew idleMs guard unparseable timestamp fail-open #13647"