Skip to content

feat: autoCaptureContextTurns rolling context window for extraction#966

Draft
gorkem2020 wants to merge 3 commits into
CortexReach:masterfrom
gorkem2020:feat/autocapture-context-turns
Draft

feat: autoCaptureContextTurns rolling context window for extraction#966
gorkem2020 wants to merge 3 commits into
CortexReach:masterfrom
gorkem2020:feat/autocapture-context-turns

Conversation

@gorkem2020

Copy link
Copy Markdown
Contributor

Problem

In steady state (history-carrying sessions extract every turn) each extraction transcript contains only that call's own turns. The extractor never has the surrounding conversation, so it cannot resolve references ("yes exactly, that one", "make it the second option") and either drops the fact or stores a hollow one.

Change

A rolling pair window retains conversational context across extractions:

  • The last N user turns, with their assistant replies interleaved in true order, stay in the transcript across extraction calls. Retained turns are context for the extractor; the existing watermark keeps them from re-becoming extraction sources.
  • N = autoCaptureContextTurns (new knob): 0 (the default) disables retention entirely and preserves stock behavior byte-for-byte; 1 to 10 sets the window size, decoupled from the extractMinMessages warm-up gate.
  • The window is bounded at set time by trimTurnsToUserCap, which never trims this call's own unextracted turns out of their transcript and never leaves an orphan assistant turn ahead of the window's first user turn.
  • dedupePairWindow repairs double-included pairs: a below-threshold deferral keeps content alive on two paths (the rolling buffer and the watermark rollback or ingress re-queue), and the repair collapses duplicate exchanges at pair granularity while keeping legitimately repeated user messages whose replies differ.

Tests

test/pair-window-retention.test.mjs (full-pipeline harness over a mock LLM and embedding server): retention across successful extractions, window bounding, knob-0 wipe, absent-knob default. Unit coverage for trimTurnsToUserCap and dedupePairWindow in test/auto-capture-cleanup.test.mjs; manifest schema checks pin the 0 default. Registered in the test chain and CI manifest.

Stacked on #965; the diff includes its predecessors until they merge.

…ant misattribution

With "User:"/"Assistant:" line prefixes only the first line of a message
carries a speaker marker, so a multi-paragraph assistant reply sheds its
marker after the first paragraph and the extractor attributes
assistant-authored plans and preferences to the user. Wrap every message
wholly in <user_message>/<assistant_message> blocks built from the hook's
role-tagged message-loop order, neutralize literal speaker tags typed inside
message content, and snap extractMaxChars truncation to a tag boundary so a
sliced transcript never leads with headless text.

The extraction prompt becomes a {system, user} split so the format teaching
and grounding rules ride the system half while the transcript rides the user
half: captureAssistant=false grounds memories exclusively in user blocks
(assistant lines never enter the transcript); captureAssistant=true keeps
assistant blocks as attributable sources with explicit attribution rules.
completeJson gains an optional per-call system prompt to carry the split.
Port the extraction lane's speaker-tagged conversation structure into the
reflection distiller input: session messages render as <user_message>/
<assistant_message> blocks instead of role-colon lines, and the INPUT code
fence is removed (any code block inside the conversation terminated the
fence early and leaked the rest of the transcript out of the input frame).
Clipping now snaps to whole tagged blocks via trimTranscriptToTagBoundary
instead of slicing mid-message, and the prompt teaches the tag grammar up
front.

Stored session-summary rows keep the legacy labeled role-colon shape via an
explicit format switch: a stored row must never carry literal speaker tags
that a later recall could replay into a prompt as fake transcript structure.
…r extraction

In steady state (history-carrying sessions extracting every turn) each
extraction transcript contains only that call's own turns, so the extractor
never has the conversational context to resolve references ("yes exactly,
that one"). Add a rolling pair window: the last N user turns, with their
assistant replies interleaved in true order, stay in the transcript across
extractions. Retained turns are context for the extractor; the watermark
keeps them from re-becoming extraction sources.

N = autoCaptureContextTurns: 0 (the default) disables retention entirely and
preserves stock behavior; 1-10 sets the window size, decoupled from the
extractMinMessages warm-up gate. The window is bounded at set time by
trimTurnsToUserCap (never trimming this call's own unextracted turns out of
their transcript), and dedupePairWindow repairs double-included pairs when a
below-threshold deferral preserves the same exchange on two paths.
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.

1 participant