Skip to content

Make the hourly sweep reflection's only driver, with a drain loop - #466

Merged
sysread merged 1 commit into
mainfrom
claude/hourly-memory-worker-6fvkwm
Jul 30, 2026
Merged

Make the hourly sweep reflection's only driver, with a drain loop#466
sysread merged 1 commit into
mainfrom
claude/hourly-memory-worker-6fvkwm

Conversation

@sysread

@sysread sysread commented Jul 30, 2026

Copy link
Copy Markdown
Owner

SYNOPSIS

Reflection (memory formation) drops its chat-turn-tail driver and becomes sweep-only: the hourly cron tick now drains the queue one thread at a time until empty, capped, or out of time budget.

PURPOSE

Currently reflection has two drivers: the completed-turn waitUntil tail (primary) and an hourly one-thread-per-tick catch-up sweep. Bad because throughput is coupled to chat activity - a user must keep conversing to drain their own queue - and because the moment of memory formation is unpredictable: it can land seconds after any turn, unlike every other background pipeline with a fixed cadence.

DESCRIPTION

Existing behavior: getStreamingResponse's tail fired reflectOneThread (per-user claim RPC) after each completed turn; runReflectionSweepTick claimed exactly one most-overdue thread across all users per hour.

This PR: the tail call is deleted (second-thoughts, curation, and samskara stay - samskara must remain tail-driven for its 1-10 minute reaction-classify window). runReflectionSweepTick becomes a sequential drain loop: claim most-overdue eligible thread -> reflect -> claim next, stopping on empty queue, a 5-thread cap, or a 180s budget for starting new claims (hosted isolate dies ~400s; a thread claimed at the cutoff still has 200+ seconds, and the existing 3-attempt cap backstops overruns). The now-orphaned per-user claim_next_thread_for_reflection RPC is dropped from the schema; mark_thread_reflected_if_claimed and the sweep claim stay. Eligibility gates unchanged (prior-calendar-day newest message, >= 2 user messages).

Result: memory formation has a fixed, predictable cadence - the user can edit or retry a settled conversation any time before the first hourly tick after the day gate opens and reflection only ever sees the corrected thread - and queue drain no longer depends on the owner conversing.

Notes:

  • no new singleton guard on purpose: the atomic per-thread claim RPC already makes overlapping ticks safe (they claim different threads), and the in-tick loop is strictly sequential
  • an error cycle stops the drain loop deliberately (no hot-looping a broken dependency); claim-lost continues
  • docs/dev, docs/user, the reflection-drain QA walkthrough, and the dev cron shim comments follow the new drive shape; old QA results rows are annotated as pre-rework baselines
  • dropping the schema RPC is idempotent (drop function if exists, all historical signatures)

Generated by Claude Code

Reflection previously rode the chat turn's waitUntil tail as its
primary driver, with the hourly cron sweep as a one-thread-per-tick
catch-up. That coupled memory-formation throughput to how much the
user happens to converse, and made the moment of formation
unpredictable relative to the rest of the background fleet.

Remove the tail call and its per-user claim path entirely, and turn
runReflectionSweepTick into a sequential drain loop: claim the
most-overdue eligible thread across all users, reflect it, claim the
next - until the queue is empty, the per-tick cap (5 threads) is hit,
or the time budget (180s of new claims) is spent. The next hourly
tick resumes the drain, so throughput no longer depends on chat
activity, and the strictly sequential loop keeps at most one
reflection agent writing to the memory store per tick. The eligibility
gates (prior-calendar-day, >= 2 user messages) are unchanged; the
fixed cadence gives the user a predictable window to edit or retry a
settled conversation before reflection reads it.

The per-user claim_next_thread_for_reflection RPC loses its only
caller and is dropped from the schema; mark_thread_reflected_if_claimed
stays (the sweep's mark path). Docs, the QA walkthrough, and the dev
cron shim comments follow the new drive shape.
@sysread
sysread merged commit a3fe320 into main Jul 30, 2026
1 check passed
@sysread
sysread deleted the claude/hourly-memory-worker-6fvkwm branch July 30, 2026 19:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants