Skip to content

feat(retain): add opt-in source lookback for extraction - #4751

Closed
divideby0 wants to merge 5 commits into
vectorize-io:mainfrom
divideby0:feat/2551-retain-context-window
Closed

divideby0 wants to merge 5 commits into
vectorize-io:mainfrom
divideby0:feat/2551-retain-context-window

Conversation

@divideby0

@divideby0 divideby0 commented Sep 25, 2026 •

Copy link
Copy Markdown

A reply such as “I approve option 2” can lose its meaning when the options fall in the preceding extraction chunk. This draft adds an opt-in window of previous source text so extraction can resolve that reference while keeping the reply as its source chunk.

Related to #2551. The wider speaker and quoted-author attribution problem remains open. The counterbalanced reproduction and raw outputs motivated this candidate.

  • Add retain_context_chars, default 0, bounded at 32000. It can be set globally, per bank, or in a named retain strategy for selected items.
  • Build windows from raw source before parallel extraction. Prompts label supporting text separately and ask the model to extract only facts grounded in the target. Stored source text, chunk indices, and source hashes keep their existing meaning.
  • Carry the window through normal retain, dry-run, provider batch extraction, internal sub-batches, and output-length retry splits. Independent items do not share context, even under the same document ID. Append can use the stored body. Prior attachment bytes are omitted.
  • Re-extract the full document while lookback is enabled. A persisted marker also forces one refresh when it is disabled, including for store-owned documents. This avoids stale target facts after earlier source or strategy changes without redefining source hashes. Provider batches reject resume when their submitted prompts no longer match; implicit event dates survive a valid resume.
  • Preserve the setting when editing or renaming a strategy in the control plane, with a numeric control for the window.
  • Expose the setting in Python and TypeScript bank-config convenience wrappers, including forwarding an explicit zero to disable it. Include configuration/docs updates, the generated bank-template schema and documentation skill, and regenerated OpenAPI/SDK models. The Rust client builds from the updated spec.

The main tradeoff for review is full re-extraction, including repeated identical submissions and appends. Fine-grained context-dependent reuse is deferred. The window can begin mid-chunk, cannot resolve distant references outside its budget, and prompt instructions cannot guarantee zero prior-only fact leakage. The synthetic test does not establish broader attribution accuracy or production cost.

Validation of 339b165860e587a6af40fb9be3021923038e60f9:

  • 373 affected API tests passed, including PostgreSQL-backed worker recovery for keyed and legacy checkpoints with lookback off/on, ordinary retry limits, and identical context windows across text/JSON slice sizes.
  • Both SDK system stories passed against a real API process and scripted provider, covering append isolation, context edits, disabling lookback and original source/chunk preservation.
  • Required scripts/hooks/lint.sh and API ty check hindsight_api passed. The advisory unused-code scan completed with findings outside these changes.
  • At the previous head e78ceb632, all 265 control-plane tests passed under UTC and the production build passed. This follow-up changes Python only; those local UI checks were not repeated.
  • The final four-engine review completed at this head with no further required PR-introduced fixes. Its coordinator reran 51 focused extraction tests and 18 PostgreSQL worker recovery tests, plus API lint and types; all passed. These overlap the implementation tests above and are not added to their count.

CI for this head completed: 21 checks passed, 78 were skipped, and the sole failure is Hermes compatibility. Its log confirms the same missing ruamel import as on the baseline, before Hindsight is exercised. The blackbox system suite and generated-file verification passed. This PR does not change the Hermes setup or dependencies.

Before implementation, the published experiment ran 24 dry-run extractions on Hindsight 0.10.1 with gpt-5.6-luna; Codex scored the results without a separate judge-model call. The linked gist preserves that experiment’s prompts, runner and outputs. During implementation, two additional counterbalanced real-model tests used gpt-5.6-luna extraction and a separate Gemini judge; both passed the day/owner, target commitment and prior-only leakage checks. These are distinct experiments from before the review fixes, not fresh model evaluations of the final commit.

AI assistance: task and verification

This disclosure covers the complete PR: investigating context loss in selected transcript/chat retains, testing the idea before implementation, building the default-off feature, completing its SDK/schema integration, and fixing regressions found by independent review. It follows the prompt-request disclosure pattern. The edited excerpts below show key instructions and decisions; other prose summarizes the work.

The user set the problem, requested the experiment and extraction model, directed the dedicated implementation handoff, flagged CI failures, and requested independent review restricted to PR-introduced defects. Codex proposed the supporting-context design and conservative full-re-extraction policy, wrote the implementation and tests, generated dependent artifacts, and applied the fixes. The planning and implementation session records identify their model as gpt-6-astra. The extraction model and judge described above had separate evaluation roles.

evie-kit is a toolkit for coordinating AI-assisted development across coding and review sessions. Here, its Hindsight client supplied the original experiment runner’s HTTP calls; its handoffs carried the task, constraints and evidence into the dedicated implementation session; and its review runner coordinated Codex and Claude Code alongside SonarQube and CodeRabbit and collected their reports. The coding-agent reviewers received separate contexts without each other’s findings. The coordinating agent reproduced and reconciled the findings before handing the confirmed regressions back for implementation.

evie-kit’s humanizer skill and deterministic style linter helped edit the public prose for clarity and remove formulaic wording. The toolkit ran from an external checkout; this PR adds no evie-kit dependency or project configuration to Hindsight. Implementation and follow-up verification used Git/GitHub CLI, pytest, Vitest, the project’s lint/type/build tools, and direct CodeRabbit reviews from the Codex session.

Authorized changes covered retain/storage/checkpoint behavior, configuration and UI mapping, regression tests and dependent SDK/schema/docs artifacts. Existing lint debt, the unrelated Hermes setup failure and a broad cache redesign stayed outside scope. The PR remains a bounded-context candidate for #2551; the wider attribution problem and maintainer design approval remain open.

Edited conversation excerpts (24–25 September 2026, UTC). Wording and punctuation have been adjusted for clarity and sentence case, preserving the original meaning and sequence. Labels identify the planning and implementation sessions.

1. Problem and proposed approach

User:

How much work would it take to add optional chunk overlap to selected Hindsight retain operations? I’m thinking of meeting transcripts and chats, where earlier messages can change the meaning of a later chunk.

Agent (planning session):

I recommend supplying previous turns as context, with facts extracted from the current chunk.

2. Test the idea before implementation

User:

Could we use the dry-run extraction endpoint to test a synthetic chat, following the conversation best practices, and post the experiment to the issue?

User:

Use gpt-5.6-luna for extraction.

Agent (planning session):

I’ll test two versions of a synthetic chat. The final reply will stay identical, while the preceding message swaps the meanings of “option 1” and “option 2.”

3. Move to a focused draft and choose the reuse policy

User:

Do we have enough evidence to build a PR, or is the implementation too complicated?

Agent (planning session):

Yes, we have enough to build a focused draft PR. I’d call it medium complexity. The experiment supports trying bounded lookback; the broader attribution problem remains open.

Agent (implementation session):

The current reuse check compares source text only. For this draft, documents with lookback enabled will be fully re-extracted. A saved marker will trigger one refresh when lookback is disabled. This handles changes to supporting context or the retain strategy without changing source hashes.

4. Correct omissions found by CI

User:

Some CI tests appear to have failed.

Agent (implementation session):

Two failures came from omissions in my PR: I missed the new setting in the Python and TypeScript convenience wrappers, along with the generated bank-template schema and documentation copies. I’m fixing both.

5. First independent review and scope of fixes

User:

Please review the PR using Codex Astra, Claude Code Fable, SonarQube, and CodeRabbit.

User:

We’re limiting required fixes to issues introduced by this PR, correct?

Agent (planning session):

Yes. Required fixes are limited to regressions introduced by this PR. Existing SonarQube warnings and broader redesign suggestions are outside scope.

Agent (planning session):

All four regressions were reproduced. The targeted tests passed but missed these cases. Existing SonarQube warnings and the documented cost of full re-extraction are not blockers.

The excerpts end with the first review, which found four regressions despite passing targeted tests. At 5e0b48f, independent Codex Astra (gpt-6-astra, high), Claude Code Fable (claude-fable-5-1, high), SonarQube and CodeRabbit runs completed; the reconciled verdict requested changes for R1–R4. A second four-engine round at e78ceb632 confirmed those fixes at the tested boundaries but found R5 (worker discovery/retry handling) and R6 (context windows changing with internal packing).

The third round reviewed the full PR at 339b16586, prioritizing the latest fixes. All four engines completed, and reconciliation found no further required PR-introduced fixes. Astra established no actionable introduced defects; Fable’s remaining candidates were nonblocking or lacked a reachable supported failure; CodeRabbit reported no new findings. Sonar had zero open in-diff findings after the earlier reasoned acceptances, while its project-wide quality gate remained ERROR. This is an automated review result, not a GitHub approval or maintainer sign-off.

Remaining review notes: legacy batches without fingerprints require fresh submission because checkpoint ownership cannot be proved safely. A warning and an exact older-checkpoint fixture would improve visibility, but the review found no resulting data-correctness defect. The full-base context-scanning performance suggestion and a Rust CLI convenience flag remain optional follow-ups. The earlier direct CodeRabbit concern about worker selection and reset races was confirmed at the PR base and remains outside the agreed scope.

Fixes and committed acceptance tests at 339b165860e587a6af40fb9be3021923038e60f9:

  • R1: decode the store's JSON retain parameters; ordinary disabled retains still reuse unchanged chunks and disabling lookback refreshes them. Storage regression.
  • R2: give each extraction its own checkpoint. Restart after A commits and B remains pending reuses both batches without duplicate facts; changed source/settings still fail, implicit dates survive, and document/slice identities remain distinct. Legacy checkpoints resume only when their fingerprint matches; unclaimed legacy accounts cannot block another chunk, while owned checkpoints keep their account guard. Streaming recovery regressions.
  • R3: merge the stored JSON body while preserving independent extraction inputs. Caller regression, SDK system stories.
  • R4: preserve nonzero, zero and omitted context settings through strategy edits and renames. UI round-trip regressions.
  • R5: persist a provider-batch discovery marker separately from per-chunk identity. Repeated startup/shutdown recovery preserves keyed and legacy checkpoints without spending retries, including with lookback disabled. Ordinary retains still hit their retry limit. PostgreSQL worker regressions.
  • R6: advance the carried window through native chunks, preserving reconstructed target/body text. Text with large separators and JSON arrays get the same targets and windows across slice budgets. Window equivalence regressions.

The focused regressions can be rerun from hindsight-api-slim with pytest -n 0 tests/test_retain_source_context.py tests/test_retain_context_append.py tests/test_retain_context_batch_recovery.py tests/test_worker.py. SDK stories use pytest -c hindsight-system-tests/pyproject.toml hindsight-system-tests/tests/test_93_retain_source_context.py with the suite's documented setup.

Extraction recovery tests stub provider/storage boundaries. Worker recovery tests use real PostgreSQL and a stubbed provider; SDK stories exercise API persistence with a scripted LLM. No OS-level worker restart, live-provider batch, fresh Oracle or rendered-browser test was run in the final review. Legacy checkpoints without a fingerprint or an available serving account cannot establish ownership and require fresh submission. The full project suite and fresh real-model evaluation were not rerun for these mechanical fixes. Prompt-only leakage and full re-extraction cost remain limitations. All six required findings have regression coverage and passed the final review’s scoped checks. The PR is ready for maintainer review and remains a draft.

@nicoloboschi

Copy link
Copy Markdown
Collaborator

stale, please open an issue with the problem instead

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants