You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Re-attach the L2/L3 summarization pipeline (recovered from the removed
chat.cpp Chat::summarize_turn) to turn capture. v1.0 "rebuild/summarize" half.
Agreed architecture
Daemon owns summarization — one background summarizer reuses the loaded
embedder + memory model (avoids reloading the 90 MB ONNX model per turn,
which a naive per-turn thread/fork would do now that the chat fork model is
gone).
Priority work-queue of summary requests: turns (L2) > sessions (L3) >
projects (L4). Order fixed for now (not user-configurable), but structured
so order / option-handling can change.
L2 (immediate): each captured turn is summarized in the background.
HTTP /turn captures → daemon summarizes directly.
MCP capture_turn (separate process) → poke the daemon via the existing SIGUSR1 after writing the turn → near-instant L2.
L3 (running session summary): fired when a session has been idle ≥ [housekeeping] summary_pause_minutes (default 20), per session_id, via
the housekeeping heartbeat (fires at the pause mark, so the rollup is ready
before the next turn — rather than next-turn-triggered, which would lag).
summarize_turn: L2 = one-sentence memory-model summary → store_summary(turn);
L3 = fold L2 into running session summary via a merge prompt that replies NO_MERGE on a topic shift (→ complete the old running summary, start a new
one), else updates it. Uses store_summary / current_session_summary /
update_summary_text / set_summary_status / chat_memory — all still present.
Daemon-less / cron-driven mode. Because every process shares the same DB,
the housekeeping+summarization pass can run as a one-shot invocation under cron/at instead of the resident daemon. To support cleanly: make ragger housekeeping (or a --once / ragger summarize verb) do the pass
directly when no daemon is running, rather than only signalling SIGUSR1.
Tradeoff: the daemon keeps the embedder+model loaded once, while a cron one-shot
reloads them per run (fine at 20-min cadence, wasteful at 1-min); cron-only also
means no immediate L2 — turns summarize on the cron tick. Offer both modes.
L3 every turn (vs on-pause). The original chat.cpp folded each L2 into the
running session summary every turn, keeping it always-current for the next
turn's context — at the cost of a merge call per turn. Current design fires L3
on the pause to save calls. The priority-queue makes this a when-to-enqueue
toggle (on capture vs on heartbeat), revisitable without restructuring. Deferred.
Correction — restore the ORIGINAL chat pipeline behavior (UI removed only)
Intent clarified: keep chat.cpp's summarization engine verbatim, just drive it
from turn capture instead of the REPL and drop the user interface. So:
L3 folds EVERY turn (not deferred to the pause). Each turn: L2 summary →
fold into the running session summary via the NO_MERGE merge prompt. Running
summary stays always-current for the next turn's context. Accepts the
per-turn merge call cost (memory model is cheap/local; daemon keeps it loaded).
Pause = close-out, not create.summary_pause_minutes (default 20)
repurposes the old quit_summary: after X min idle, mark the running session
summary complete so the next turn starts a fresh one. Fired by the heartbeat.
Port check_orphaned_turns too — crash recovery for captured-but-unsummarized turns.
Net deltas from a literal port: fork→daemon worker thread; REPL/quit→capture/pause;
per-session L3 scoping (foundation done). Supersedes the earlier "L3 on pause only"
note — that was the wrong read of intent.
Activity
diskerror commentedon Jun 3, 2026
Future considerations (captured, not scheduled)
Daemon-less / cron-driven mode. Because every process shares the same DB,
the housekeeping+summarization pass can run as a one-shot invocation under
cron/atinstead of the resident daemon. To support cleanly: makeragger housekeeping(or a--once/ragger summarizeverb) do the passdirectly when no daemon is running, rather than only signalling SIGUSR1.
Tradeoff: the daemon keeps the embedder+model loaded once, while a cron one-shot
reloads them per run (fine at 20-min cadence, wasteful at 1-min); cron-only also
means no immediate L2 — turns summarize on the cron tick. Offer both modes.
L3 every turn (vs on-pause). The original chat.cpp folded each L2 into the
running session summary every turn, keeping it always-current for the next
turn's context — at the cost of a merge call per turn. Current design fires L3
on the pause to save calls. The priority-queue makes this a when-to-enqueue
toggle (on capture vs on heartbeat), revisitable without restructuring. Deferred.
diskerror commentedon Jun 3, 2026
Correction — restore the ORIGINAL chat pipeline behavior (UI removed only)
Intent clarified: keep chat.cpp's summarization engine verbatim, just drive it
from turn capture instead of the REPL and drop the user interface. So:
fold into the running session summary via the NO_MERGE merge prompt. Running
summary stays always-current for the next turn's context. Accepts the
per-turn merge call cost (memory model is cheap/local; daemon keeps it loaded).
summary_pause_minutes(default 20)repurposes the old
quit_summary: after X min idle, mark the running sessionsummary
completeso the next turn starts a fresh one. Fired by the heartbeat.check_orphaned_turnstoo — crash recovery for captured-but-unsummarized turns.Net deltas from a literal port: fork→daemon worker thread; REPL/quit→capture/pause;
per-session L3 scoping (foundation done). Supersedes the earlier "L3 on pause only"
note — that was the wrong read of intent.