Skip to content

Auto-search warm pool is lost when the search worker idles out after 5 minutes; no-hint decisions aren't logged #773

Open

Description

@null-axiom

Update: measured afterwards, the 5-minute worker idle-out is not what suppresses hints (attach rate is the same either side of 5 minutes); most no-hint turns are below the relevance threshold. See this comment.

Magic Context: 0.49.20, OpenCode 2.1.4, macOS, Voyage embeddings, memory disabled. Follow-up to #762 — thanks for the fix.

The warm pool now survives the 1 s deadline, but it lives in the search worker, which is disposed after SEARCH_WORKER_IDLE_MS = 5 * 60_000. With a long cache TTL our turns are often more than 5 minutes apart, so the next turn starts cold, warmOnly skips the chunk lane, and the vector side rarely contributes to hints. A cold turn also pays ~270–350 ms for worker startup.

Evidence is circumstantial: after restart, a turn at 20:28:18 (cold) and the next at 20:33:32 (5 min 14 s later, past the idle timer) both ended empty. I can't prove the pool state because:

  • No-hint decisions (empty, too-short, below-threshold) write no log line on the writeNoHintAndReconcile path; only session_meta records them.
  • The successful path never logs chunkPool state; the new per-step timing line only appears on a missed deadline.

Asks:

  • Log the no-hint reason and pool state (warm/cold, rows loaded) on every decision, at least at debug.
  • Keep the decoded pool past the worker's idle timeout (share it outside the worker, or a longer/idle-aware timeout for sessions with a pool), or warm it in the background after a turn so the next one finds it ready.

Activity

  1. magic-alfonso commented on Oct 23, 2026

    @magic-alfonso

    Thanks for the follow-up and for being clear about what the evidence does and doesn't show.

    Both points make sense. The decoded pool lives inside the search worker, so it goes when the worker's idle timer disposes the worker. And the no-hint outcomes are recorded in session state without a log line, so a cold turn and a below-threshold turn look the same from the log.

    We're in the middle of a larger internal change, so this one is queued rather than started. We'll post here when we pick it up.

  2. null-axiom commented on Oct 24, 2026

    @null-axiom
    Author

    Correction after measuring: the 5-minute worker idle-out isn't what suppresses hints.

    Over Oct 20–23 (353 decisions across two sessions, gap measured to the previous decision): attach rate 21.7% for gaps ≤5 min vs 20.7% for >5 min. The dominant outcome is below threshold (163 of 266 non-timeout decisions, top scores mostly 0.3–0.6 against 0.6). Cold starts do show in timeouts: 34% after >5 min vs 18% within. The frozen OpenCode 2 message index (#772) leaves about 6–11% of compacted history out of the message lane.

    peek also misses whenever the session's chunk-row signature changes (e.g. a new compartment), another cold trigger I didn't measure.

    What would help most: log per-lane top scores and near-misses (0.5–0.6) on each decision, plus pool state, so threshold tuning can be done from data.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions