LearnNewsExamplesServices
Frontmatter
id13647
titleRe-scope pending-session-summary marker to the drainable set
stateClosed
labels
enhancementaiarchitectureperformancemodel-experience
assigneesneo-opus-vega
createdAtJun 20, 2026, 7:38 PM
updatedAtJun 21, 2026, 5:58 AM
githubUrlhttps://github.com/neomjs/neo/issues/13647
authorneo-opus-vega
commentsCount5
parentIssue13624
subIssues
13667 Exclude archived/orphaned sessions from the session-summary-pending count
13672 Harden the session-summary churn-gate timestamp edges (future-skew + unparseable-ts)
subIssuesCompleted2
subIssuesTotal2
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtJun 21, 2026, 5:58 AM

Re-scope pending-session-summary marker to the drainable set

Closed v13.1.0/archive-v13-1-0-chunk-4 enhancementaiarchitectureperformancemodel-experience
neo-opus-vega
neo-opus-vega commented on Jun 20, 2026, 7:38 PM

Context

AC2 of #13637 (session-summary drift churn-gate), carved out at PR #13645 (which Resolves #13637's AC1 — the gate that stops re-summarizing active sessions). The gate fixes the behavior; this ticket fixes the measurement: getPendingSessionSummaryCount still counts the all-time pending set (the epic's 283→284 stuck symptom), so it never reaches 0 / signals "done." Design pre-converged with @neo-opus-ada in the #13645 review.

Live latest-open sweep: checked latest 20 open issues at 2026-06-20T17:36Z — no equivalent found (#13637 / #13638 / #13592 are distinct slices; #12435 is adjacent test-isolation). A2A in-flight claim sweep (last 30 msgs): no marker-rescope claim.

The Problem

getPendingSessionSummaryCount (ai/daemons/orchestrator/scheduling/summary.mjs:80) counts ALL sessions with AGENT_MEMORY turns but no SESSION_SUMMARY — including the non-drainable population (per #13624 DB evidence: 283/285 are >2d old, 172/285 are ≤2-turn). Its own JSDoc admits it is "a proxy, not a claim that Chroma drift has drainable work." So the marker is flat-forever (no "done" signal) even while the drift drain is actively working — the operator's "14h, backlog 283→284" symptom. Goal: after a heavy-maintenance window the orchestrator reaches a stable "backlog resolved" state — the marker must be able to reach 0.

The Architectural Reality

Two different surfaces: the marker getPendingSessionSummaryCount (graph SQL over Nodes, summary.mjs:80) vs the drift drain findSessionsToSummarize (Chroma, ai/services/memory-core/SessionService.mjs) — now gated on swarmHeartbeat.idleThresholdMs (PR #13645). For the marker to equal the drainable set it must apply the SAME idle criterion the gate uses, plus the tiny-session exclusion.

The Fix

Re-scope getPendingSessionSummaryCount to count only sessions that are (a) idle past idleThresholdMs (the gate's drainable criterion — reuse the leaf, no new config) AND (b) above a tiny-turn floor (≤N-turn excluded). Reaches 0 = "done." If a clean SQL re-scope proves too costly, the converged fallback is to re-label the marker as explicit static observability (the #13637 AC2 "OR re-labeled" clause).

Folded-in (ada's #13645 review flags on the gate, same drift code): (c) future-skewed ts (lastActivity > now) → add a >= 0 guard in findSessionsToSummarize so a clock-skewed session can't be perpetually gated; (d) unparseable-ts fail-open → documenting comment (corrupt-ts is rare + self-heals via Case-A/B).

Contract Ledger

Target Surface Source of Authority Proposed Behavior Fallback Docs Evidence
getPendingSessionSummaryCount + the pending-session-summary log marker summary.mjs:80 count only the drainable set (idle-past-window + non-tiny) re-label as static observability function JSDoc #13624 DB analysis (issuecomment-4758667977)

Decision Record impact

aligned-with ADR-0019 — reuses the resolved idleThresholdMs leaf at the use site; introduces no new config leaf.

Acceptance Criteria

  • getPendingSessionSummaryCount counts only the drainable set (idle past idleThresholdMs + above the tiny floor) and can reach 0 once the drain has cleared it — OR is explicitly re-labeled as static observability.
  • Confirm the tiny-session hypothesis (≤2-turn sessions don't warrant a summary) before excluding them, or make the floor documented/configurable.
  • Gate hardening (c): a future-skewed lastActivity is not perpetually gated (>= 0 guard).
  • Gate hardening (d): unparseable-ts fail-open is documented.
  • Unit test: marker counts drainable-only; a future-skewed session is eligible.

Out of Scope

  • The churn-gate itself (delivered by PR #13645).
  • miniSummary backfill throughput (#13638).
  • The process-termination integrity daemon (#13624 axis-3 (b)).

Related

Parent epic: #13624. Sibling: #13637 (delivered by PR #13645). #13638 (miniSummary). #12435 (test-isolation, adjacent). ADR-0019.

Release classification: post-release (Approve+Follow-Up follow-up of #13637 — non-blocking; boardless).

Origin Session ID: 9ecfc519-a1c5-4153-872c-1e8ad69ed7f2 Retrieval Hint: "session-summary marker re-scope drainable getPendingSessionSummaryCount idleThresholdMs gate timestamp future-skew #13637 AC2"

tobiu referenced in commit b662a8b - "fix(ai): exclude archived/orphaned sessions from session-summary-pending marker (#13647) (#13668)" on Jun 20, 2026, 11:19 PM
tobiu referenced in commit 0307bca - "fix(ai): harden session-summary churn-gate timestamp edges — future-skew + unparseable-ts fail-open (#13647) (#13673)" on Jun 20, 2026, 11:46 PM