LearnNewsExamplesServices
Frontmatter
id17731
titleExpose the miniSummary generation window as one actuator knob
stateClosed
labels
enhancementaiarchitectureagent-os
assigneesneo-opus-vega
createdAtAug 24, 2026, 9:50 PM
updatedAtAug 24, 2026, 10:11 PM
githubUrlhttps://github.com/neomjs/neo/issues/17731
authorneo-opus-vega
commentsCount1
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtAug 24, 2026, 10:11 PM

Expose the miniSummary generation window as one actuator knob

Closed Backlog/active-chunk-19 enhancementaiarchitectureagent-os
neo-opus-vega
neo-opus-vega commented on Aug 24, 2026, 9:50 PM

Context

Bounded leaf for #16223 AC-1 + AC-2, filed because those two ACs are the only one-PR-resolvable piece of that ticket and they are a hard prerequisite for #14418. #16223 itself is a seven-AC consumer ticket whose restore obligation it describes as "currently unimplementable as specified" — it cannot close on this work, and a PR claiming otherwise would be false.

The harm this eventually unblocks is measured, not hypothetical: on CPU-only hardware the miniSummary backfill deferred ~100% of items and burned ~2.3 CPU-cores average for days producing zero summaries, because a generation window calibrated on GPU hardware straddles the whole corpus-size distribution on CPU. #14418 (graduated from D#13873) owns the controller that widens such a window. This leaf gives that controller something to actuate.

Live latest-open sweep: checked the latest 20 open issues at 2026-08-24T19:47Z; no equivalent found. A2A in-flight claim sweep over the last 30 messages at the same time: no [lane-claim] on this scope. resources/content grep for the env names returns only #16223, #14418, and #16374 (an unrelated, closed action-set ticket).

The Problem

The controller cannot reach this window, and the reason is a missing surface rather than a missing mechanism.

reconfigure shipped — RecoveryActuatorService lists it in DEFAULT_ACTIONS and routes it to reconfigureComposeService({knob, knobValues, …}). What it moves is a knob from a closed registry, and it moves it by delivering leaf→env bindings into a compose service. Both halves of that path are absent for this window:

  1. No registry entry. RECOVERY_KNOBS in ai/services/memory-core/helpers/recoveryKnobRegistry.mjs is the closed set of knobs the actuator may turn; the miniSummary window is not in it, so isKnownKnob refuses it and no prescription can name it.
  2. No compose surface. Neither env name appears anywhere under ai/deploy/ — verified with a positive control: NEO_KB_ASK_MODEL resolves in five compose files by the same search, so the absence is a measurement rather than a search artifact.

The Architectural Reality

  • ai/configBase.mjs — the two leaves exist with env bindings: miniSummaryTimeoutMs (30000, NEO_MC_MINI_SUMMARY_TIMEOUT_MS) and generateMiniSummaryTimeoutMs (20000, NEO_MC_GENERATE_MINI_SUMMARY_TIMEOUT_MS). Binding without surface.
  • ai/services/memory-core/helpers/recoveryKnobRegistry.mjs — its own module docstring already anticipates this exact case: "A knob is the unit, not a config leaf. Several leaves can only move together — a nested timeout…". This window is that sentence's referent, which is strong evidence the registry is the right home rather than a new mechanism.
  • container-memory-ceiling is the precedent entry to follow in shape: description, a single declared serviceKey the actuator matches against to refuse a knob/target mismatch, requires for runtime-resolved context, a selector that proposes values keyed by registry leaf path, and the leaf→env bindings the delivery reads. The controller names a semantic knob and never learns which leaf moves.
  • The nesting is load-bearing and is why the pair cannot be two knobs. Per #16223: the inner leaf sits inside buildMiniSummary, whose try/catch swallows its rejection into a falsy return and the sweep's deferred branch; the outer leaf wraps summarize(…) from outside that guard, so its rejection escapes to the sweep's catch. Widening only the inner leaf is a silent no-op at the outer bound, and crossing the outer bound flips every item from the falsy path to the thrown path — blinding any detector keyed to one branch at exactly the moment the actuation is working hardest.

The Fix

  1. One RECOVERY_KNOBS entry for the window, declaring both leaves in application order with their env bindings, serviceKey: 'mc-server', and the ordered-pair invariant: the inner leaf stays strictly below the outer, and the bound is declared against the outer.
  2. The ceiling is relative to a measured baseline, not an absolute constant — an absolute ceiling needs recalibration on every hardware change, which is the defect #16223 exists to remove.
  3. The compose surface for both env names on the mc-server service, following the existing NEO_MC_* passthrough idiom, across the compose files that already carry that service's knobs.

Deliberately NOT here: any detector, any controller, any widening policy. Those are #14418's, and building them here would duplicate a graduated design.

Contract Ledger Matrix

Target Surface Source of Authority Proposed Behavior Fallback Docs Evidence
RECOVERY_KNOBS (new entry) ADR-0026 closed-set discipline; #16223 AC-2 one knob moving both leaves as an ordered pair; inner strictly below outer; bound declared against the outer; ceiling relative to a measured baseline an out-of-band or inverted proposal is refused by validation, never clamped — a clamp turns a terminal into an endless stream of fake-success raises registry JSDoc unit spec: ordered-pair invariant, refusal on inversion, refusal above ceiling
mc-server compose env (NEO_MC_MINI_SUMMARY_TIMEOUT_MS, NEO_MC_GENERATE_MINI_SUMMARY_TIMEOUT_MS) existing NEO_MC_* passthrough idiom both names reach the container so reconfigureComposeService can deliver them absent env ⇒ the leaf default stands, unchanged from today compose comment grep asserting both names present, with a positive control
isKnownKnob / knobLeafPaths / knob env bindings existing registry readers accept the new knob and return its ordered leaf pair unknown knob still returns empty and callers still gate on isKnownKnob spec asserting the readers resolve the new knob
the actuator's action set ADR-0026 AC-9 unchanged — this adds a knob, never an action spec asserts DEFAULT_ACTIONS is byte-identical

Decision Record impact

aligned-with ADR 0026 — this adds one entry to the actuator's closed knob registry, which ADR-0026 provides for explicitly; no action class is added, removed, or re-routed, and the §2.4 actuator matrix is untouched. aligned-with ADR 0019 — no leaf is declared, moved, or re-derived; the two leaves already exist and only gain a compose surface.

⚠️ Scope corrected 2026-08-24, twenty minutes after filing — SIX of seven ACs were already shipped

I filed this after a design sweep and the sweep was wrong. RECOVERY_KNOBS already contains 'minisummary-generation-window', with both leaves carrying role: 'inner' / role: 'outer' and their env bindings, an inner-strictly-below-outer invariant whose stated reason is the branch-flip this ticket describes, and a second invariant — outer-leaves-room-for-a-draining-sweep — that expresses the ceiling relative to memoryService.miniSummaryBackfillMaxRunMs and refuses on an unresolvable budget. It is covered by recoveryKnobRegistry.spec.mjs, recoveryOverrideStore.spec.mjs, and RecoveryActuatorService.spec.mjs.

So the original AC-2 through AC-6 were already satisfied, some of them more thoroughly than I specified them.

Why my sweep missed it, because the mechanism is reusable and it is not "I did not look". I grepped RECOVERY_KNOBS, opened the container-memory-ceiling entry, read it closely — and never enumerated the object's keys. One grep -oE "^ '[a-z-]+':" returns both entries. I read the first member of a collection and generalised to the collection. That is the same failure as searching a mechanism's vocabulary instead of the mechanism, one level down: the check was precise and the population was one element.

What is actually left — and it is real, verified twice: neither env name appears anywhere under ai/deploy/, positive control NEO_KB_ASK_MODEL resolving in five compose files by the same search. The knob is fully declared and fully bounded, and reconfigureComposeService still cannot deliver it, because the container never receives the variables.

This ticket is reshaped to that one deliverable. The ACs below replace the original seven.

Acceptance Criteria

  • Both NEO_MC_MINI_SUMMARY_TIMEOUT_MS and NEO_MC_GENERATE_MINI_SUMMARY_TIMEOUT_MS reach the mc-server container, declared in the compose files that already carry that service's other NEO_MC_* knobs, following the existing passthrough idiom.
  • A check asserts both names are present and carries a positive control, so a passing assertion cannot be a search artifact. NEO_KB_ASK_MODEL is the control used to establish the current absence.
  • Absent env still resolves to the existing leaf defaults — this exposes the knob and does not turn it. Asserted, because a compose default that silently overrides a leaf would move production behaviour under cover of a plumbing change.
  • Nothing in recoveryKnobRegistry.mjs changes. The knob is already declared, bounded and spec-covered; a diff there would mean this ticket re-derived what it should have read.

Out of Scope

  • The homeostatic controller, its setpoint, and any widening policy — #14418.
  • The detector that must count a timeout on both branches — #16223 AC-3.
  • The reason-scoped restore and its tally reset — #16223 AC-4/5/6, which that ticket records as currently unimplementable as specified.
  • Provider-side cancellation of timed-out requests — #16223 AC-7.
  • Any change to the leaves' default values. This exposes the knob; it does not turn it.

Avoided Traps

  • Two knobs instead of one. The registry keys by knob precisely because these leaves cannot move independently; splitting them reintroduces the silent-no-op and branch-flip failure #16223 documents.
  • An absolute ceiling. Cheaper to write and wrong on the next hardware change — the exact defect the parent ticket exists to remove.
  • Clamping an out-of-band proposal. Clamping hides the terminal; refusal makes it observable. The container-memory-ceiling entry states this reasoning for its own cap and it transfers.
  • Building the detector here because it is adjacent. #14418 graduated with a cross-family disposition; duplicating it would be a parallel implementation of a decided design.

Related

#16223 (parent — this closes its AC-1 and AC-2) · #14418 (the controller that consumes this knob) · D#13873 (its graduation) · ADR 0026 · ADR 0019

Origin Session ID: cad88c79-073f-4816-aaa7-e779224f2af3

Retrieval Hint: miniSummary generation window knob registry compose surface ordered pair inner below outer relative ceiling