LearnNewsExamplesServices
Frontmatter
id12872
titleProvider-class split for the session-summary synthesis timeout
stateClosed
labels
enhancementaiperformancemodel-experience
assigneesneo-opus-vega
createdAtJun 11, 2026, 12:15 AM
updatedAtJun 11, 2026, 2:14 AM
githubUrlhttps://github.com/neomjs/neo/issues/12872
authorneo-opus-vega
commentsCount2
parentIssue12065
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtJun 11, 2026, 12:24 AM

Provider-class split for the session-summary synthesis timeout

Closed v13.0.0/archive-v13-0-0-chunk-17 enhancementaiperformancemodel-experience
neo-opus-vega
neo-opus-vega commented on Jun 11, 2026, 12:15 AM

Context

#12833 / PR #12837 (merged today, b6273b086) bounded summarizeSession's synthesis with sessionSummaryTimeoutMs (flat 180s) + a degrade-on-timeout fallback — killing the unbounded ~30-min stall. This is its calibration follow-up: 180s is a single flat value, but the synthesis runs on either a local or a remote provider with wildly different latency profiles.

The sibling ask path already solved this (#12868): askSynthesis.{timeoutMs: 300s (local), timeoutMsRemote: 60s}, selected at the use-site by provider class — "no single value can serve both a 10-second remote and a 5-minute local synthesis" (its JSDoc, ai/mcp/server/knowledge-base/config.template.mjs:196-204). The summary leaf has no such split. 180s sits below the 300s local ceiling that path established for a smaller synthesis, so on local gemma a session summary will routinely time out and drop to the degraded tier (full-fidelity summaries effectively never produced locally — an inference from the ~287s ask benchmark; the summary-specific latency is what epic Sub 8 / #12074 measures). @neo-opus-grace surfaced this and agreed the split is the right follow-up; the degrades-not-fails distinction (below) was reconciled in A2A.

The Problem (precise)

As of #12837 a too-slow synthesis degrades (provenance-labeled compact summary), it does not fail/null (SessionService.mjs:617-645). So this is a summary-quality (degraded-frequency) calibration, NOT a job-failure fix. A genuinely null summary post-#12837 would mean the degraded path also failed — a separate defect, out of scope here.

The Fix

Mirror the askSynthesis shape on the summary leaf:

  1. ai/mcp/server/memory-core/config.{template,}.mjs:145 — split sessionSummaryTimeoutMs into a local-class budget (keep NEO_MEMORY_SESSION_SUMMARY_TIMEOUT_MS; raise default 180s → 300s, the established local floor — defensible interim pending #12074) + a remote-class budget (*_REMOTE, ~60s fail-fast). No breaking change for deployments already setting the env var.
  2. ai/services/memory-core/SessionService.mjs:576 — select the budget by provider class, reusing the existing :570-573 modelProvider branch.
  3. Keep the degraded retry (:635) on a tight cap (the compact prompt clears fast) so worst-case lease hold isn't 2× localRaw — protects the HeavyMaintenanceLease / REM cycle from longer starvation.

Contract Ledger

Surface Authority Behavior Fallback Evidence
sessionSummaryTimeoutMs (memory-core config) this ticket; mirrors #12868 split local (300s, env) + remote (~60s); use-site provider selection current: flat 180s for all providers config.template.mjs:145; cf. knowledge-base/config.template.mjs:195,206
degraded-retry timeout (SessionService.mjs:635) :584-589 shared closure tight cap independent of local raw budget current: inherits summaryTimeoutMs (2× worst case) both calls re-enter runGuardrailed

Decision Record impact

none — no ADR governs the summarization timeout (consistent with #12833); aligned-with the #12868 provider-class-timeout convention.

Acceptance Criteria

  • sessionSummaryTimeoutMs split into local + remote budgets, both env-overridable, mirroring askSynthesis; existing env var preserved (→ local-class). No breaking change.
  • summarizeSession selects the budget by provider class (reuse :570-573): local → generous, remote → ~60s fail-fast.
  • Degraded retry (:635) bounded by a tight cap independent of the local raw budget; worst-case lease hold documented and NOT 2× localRaw.
  • Unit regression (npm run test-unit): provider-class selection (local vs remote) + degraded tight cap + env-override resolution.
  • #12833 invariants preserved: a slow synthesis still degrades (never null); no SummarizationJobs lease held past expires_at.

Out of Scope

  • Final empirically-tuned local value — epic Sub 8 / #12074 (operator-run gemma4 benchmark); this ships the shape + a defensible 300s interim.
  • null/failed-summary investigation (degraded path itself failing post-#12837) — separate bug if observed.
  • GoldenPathSynthesizer.mjs:927 no-explicit-timeout consistency nit (flagged by @neo-opus-grace; small brief, 15-min-watchdog-covered) — fold here if trivial, else onto #12812.

Avoided Traps

  • Naive flat-value bump — raising the shared 180s leaf doubles worst-case lease hold (raw + degraded both inherit it). The split + tight degraded cap is the point.
  • Picking the local value blind — without the #12074 session-synthesis benchmark a too-high budget just burns lease time before degrading. Ship shape + 300s interim, calibrate later.
  • Reframing as a failed-jobs fix — as of #12837 a timeout degrades, not fails.

Related

  • #12065 — [Epic] Orchestrator-as-SSOT for the REM (Sandman) Pipeline (parent)
  • #12833 — the fix this calibrates (PR #12837, b6273b086)
  • #12868 — ask-synthesis provider-class split (pattern mirrored; resolved #12846)
  • #12074 — Sub 8 gemma4 benchmark (local-value calibration dependency)
  • #12812 — session-summary progress logs (observability sibling)

Release classification: post-v13 (calibration polish; non-blocking — the degraded tier still produces summaries, and the local budget is operator-mitigable today via NEO_MEMORY_SESSION_SUMMARY_TIMEOUT_MS). Boardless per ticket-create §4.

Origin Session ID: Claude Opus 4.8 / @neo-opus-vega nightshift, 2026-06-11 (post-sunset).

Handoff Retrieval Hints:

  • query_summaries(query='sessionSummaryTimeoutMs provider-class split local 300s 12833 12868')
  • File anchors: ai/services/memory-core/SessionService.mjs:570-645, ai/mcp/server/memory-core/config.template.mjs:145, ai/mcp/server/knowledge-base/config.template.mjs:157-206

Live latest-open sweep: latest 25 open issues checked 2026-06-11 (post-sunset); no equivalent (adjacent only: #12812, #12740, #12748). A2A in-flight claim sweep: no competing claim on this scope.

Authored by @neo-opus-vega (Claude Opus 4.8).