Skip to content

perf(rag): parallelise independent retrieval hydration - #1474

Merged
BigSimmo merged 13 commits into
mainfrom
codex/parallelise-safe-retrieval-stages
Jul 30, 2026
Merged

perf(rag): parallelise independent retrieval hydration#1474
BigSimmo merged 13 commits into
mainfrom
codex/parallelise-safe-retrieval-stages

Conversation

@BigSimmo

@BigSimmo BigSimmo commented Jul 30, 2026

Copy link
Copy Markdown
Owner

Motivation

  • Reduce latency by overlapping independent retrieval reads (document metadata and memory-card hydration) while preserving deterministic candidate assembly and existing caching semantics.
  • Enable safe, auditable changes to retrieval timing that must remain protected by the repo's RAG canary policies.

Description

  • Split memory evidence loading out of withMemoryBoostedCandidates into loadMemoryBoostArtifacts and applyMemoryBoostArtifacts in src/lib/rag/rag-candidate-sources.ts so memory reads can run independently of metadata reads.
  • Add hydrateCandidatesWithMetadataAndMemory in src/lib/rag/rag-hydration.ts which runs metadata and memory reads concurrently with Promise.all and then applies memory boosts deterministically after both settle.
  • Replace serial metadata+memory sequences on three post-gate branches (document-lookup, hybrid, and vector-fallback) to use the new helper while preserving the pre-memory text-fast path behavior.
  • Add a focused contract test tests/rag-retrieval-parallelism.test.ts that asserts the concurrency boundary and that the helper is invoked at the three migrated call sites.
  • RAG impact: behaviour change — live canary pair 30578169116 -> 30579534353 completed with identical retrieval metrics.

Testing

  • Ran formatting with npm run format and npm run format:changed (passed).
  • Ran typecheck with npm run typecheck (passed).
  • Ran the focused Vitest run for the new contract test and related retrieval budget tests via node scripts/run-vitest.mjs run tests/rag-retrieval-parallelism.test.ts tests/rag-round-trip-budget.test.ts and full unit suite via npm run test as part of verify:pr-local (all executed tests passed).
  • Ran offline RAG verification npm run eval:rag:offline (36 golden cases, 22 suites; 572 tests passed).
  • Completed protected live canary pair 30578169116 -> 30579534353: 36/36 golden retrieval cases, document/content recall@5 1.0, identical aggregate MRR, and zero per-case document/content reciprocal-rank regressions. Both workflow runs were red only on separate answer-latency thresholds, not retrieval correctness.

Files changed (high level): src/lib/rag/rag-candidate-sources.ts, src/lib/rag/rag.ts, and new test tests/rag-retrieval-parallelism.test.ts.


Codex Task

Summary by CodeRabbit

  • Performance
    • Improved retrieval speed by loading document metadata and memory-based results in parallel.
    • Reused cached memory results more efficiently across retrieval flows.
  • Bug Fixes
    • Preserved consistent memory boosting and metadata hydration across document lookup, hybrid search, and fallback retrieval paths.
  • Tests
    • Added coverage verifying parallel retrieval hydration and consistent processing across supported search paths.

RAG impact: behaviour change — canary pair 30578169116 -> 30579534353

Risk and rollout

Retrieval candidate ordering is protected by the measured baseline/post pair. Roll back the squash commit if production latency or retrieval telemetry regresses; no provider configuration or production data is changed.

Clinical Governance Preflight

  • Source-backed claims still require linked source verification before clinical use.
  • No patient-identifiable document workflow was introduced or expanded.
  • Supabase target remains Clinical KB Database (sjrfecxgysukkwxsowpy).
  • Service-role keys and private document access remain server-only.
  • Demo/synthetic content remains clearly separated from real clinical sources.
  • Source metadata, review status, and outdated/unknown-source behavior remain conservative.
  • Deployment classification/TGA SaMD impact is unchanged; this changes retrieval scheduling, not clinical decision-support semantics.

@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 4 minutes

Your organization has reached its usage spending cap. Adjust your spending cap in the billing tab.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e67bdd6a-205c-4dc5-a0bd-6d8586f2e21e

📥 Commits

Reviewing files that changed from the base of the PR and between b55f9b5 and 05f1fee.

📒 Files selected for processing (5)
  • docs/branch-review-ledger.md
  • src/lib/rag/rag-hydration.ts
  • src/lib/rag/rag.ts
  • tests/eval-retrieval.test.ts
  • tests/rag-retrieval-parallelism.test.ts
📝 Walkthrough

Walkthrough

Memory artifact loading and application are extracted into reusable functions. RAG retrieval now overlaps memory loading with document metadata hydration across three branches, with tests verifying concurrency and call-site coverage.

Changes

RAG memory hydration

Layer / File(s) Summary
Extract memory artifact pipeline
src/lib/rag/rag-candidate-sources.ts
Adds reusable artifact loading and application functions, including scoped card-cache lookup, chunk hydration, candidate merging, and boost application.
Parallel retrieval hydration
src/lib/rag/rag.ts
Adds shared concurrent hydration and uses it in document lookup, hybrid reranking, and vector fallback paths.
Validate hydration parallelism
tests/rag-retrieval-parallelism.test.ts
Verifies the parallel Promise.all structure, post-load boost application, and three helper call sites.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Retrieval as RAG retrieval path
  participant Metadata as attachDocumentRankingMetadata
  participant Memory as loadMemoryBoostArtifacts
  participant Applier as applyMemoryBoostArtifacts
  par Metadata hydration
    Retrieval->>Metadata: hydrate candidate metadata
    Metadata-->>Retrieval: metadataCandidates
  and Memory artifact loading
    Retrieval->>Memory: load memory artifacts
    Memory-->>Retrieval: memory artifacts
  end
  Retrieval->>Applier: merge and apply memory boosts
  Applier-->>Retrieval: boosted candidates
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly matches the PR's main change: parallelizing independent RAG retrieval hydration for latency reduction.
Description check ✅ Passed The description is mostly complete: it covers motivation, implementation, testing, risk/rollout, and governance checks, though it doesn't use the template's exact Summary heading.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Comment @coderabbitai help to get the list of available commands.

@supabase

supabase Bot commented Jul 30, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project sjrfecxgysukkwxsowpy because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f5d19f013d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/lib/rag/rag.ts Outdated
@BigSimmo

Copy link
Copy Markdown
Owner Author

@codex resolve actionable Codex review findings for this pull request and current head using the repository instructions. This is the pull request's single automatic repair pass: do not perform a fresh review, create new standalone findings, or request another review. Work only the existing unresolved Codex threads on the current head. Always fix P0 and P1 findings. For P2 and lower findings, fix only clear, scoped, low-risk issues; otherwise disposition them with a concise reason. After fixing or dispositioning a thread, reply in that thread with as the first line, followed by a concise summary; that marker authorizes the workflow to close that exact thread. If human input or new authorization is required, do not use the marker and leave the thread open with the blocker. Finish only after every actionable thread is fixed or dispositioned and closed, or explicitly left open for a human decision. Do not update the branch from main, address unrelated reviews, broaden scope, or create more than one scoped fix commit. Do not use external APIs, paid services, credentials, dependency changes, or broad refactors unless explicitly authorized. Add targeted tests where behavior changes and run the narrowest relevant validation.

@github-actions

github-actions Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

CI triage

CI failed on this PR. Automated classification of the 3 failed job(s):

  • Unit coverageneeds investigation: inspect the failing step and uploaded diagnostics; rerun only after classifying the cause.
  • Static PR checksneeds investigation: inspect the failing step and uploaded diagnostics; rerun only after classifying the cause.
  • PR requiredneeds investigation: inspect the failing step and uploaded diagnostics; rerun only after classifying the cause.

Compared with main CI run #7178 (cancelled).

Classification is evidence routing, not permission to ignore a failure. Exact quarantined Playwright identities remain governed by the flake ledger.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🎉

Reviewed commit: f5d19f013d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
tests/rag-retrieval-parallelism.test.ts (1)

1-25: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Source-text assertions don't actually verify concurrency or correctness.

Both tests parse rag.ts as a string and check for literal substrings/regex matches rather than exercising the function. This provides weak guarantees:

  • expect(helper).toContain("await Promise.all([") passes even if that code is dead/unreachable, or if attachDocumentRankingMetadata/loadMemoryBoostArtifacts are actually awaited sequentially elsewhere while an unused Promise.all([...]) literal merely exists in the sliced text.
  • The slice end marker "/** Attach document ranking metadata. */" is a hardcoded comment string; if that docstring is ever reworded (e.g. by a formatter or doc pass), indexOf returns -1 and slice(start, -1) silently truncates to almost the entire file instead of failing loudly, defeating the purpose of the test.
  • callCount regex /await hydrateCandidatesWithMetadataAndMemory\(\{/g is brittle to formatting (e.g. object argument on its own line) and doesn't confirm the calls are on the branches they're meant to be on.

Consider replacing with a behavioral test that mocks attachDocumentRankingMetadata and loadMemoryBoostArtifacts (e.g. via vi.mock) with deferred promises, and asserts that both are invoked before either resolves — this actually protects the perf/correctness invariant this PR introduces, rather than the source layout.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/rag-retrieval-parallelism.test.ts` around lines 1 - 25, Replace the
source-text assertions in the retrieval hydration parallelism tests with a
behavioral test of hydrateCandidatesWithMetadataAndMemory. Mock
attachDocumentRankingMetadata and loadMemoryBoostArtifacts with deferred
promises, invoke the helper, and assert both operations are started before
either promise resolves; retain coverage that the helper is used across the
intended retrieval branches without brittle formatting or comment-string
matching.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/lib/rag/rag.ts`:
- Around line 1496-1531: Update hydrateCandidatesWithMetadataAndMemory so the
concurrently executed metadata and memory reads are timed as one combined
wall-clock phase rather than wrapping each branch with measureSearchPhase.
Preserve the existing parallel Promise.all behavior and result assembly, and
record the single elapsed duration under an appropriate shared phase while
avoiding separate metadata_hydration and memory_hydration latency charges.

---

Nitpick comments:
In `@tests/rag-retrieval-parallelism.test.ts`:
- Around line 1-25: Replace the source-text assertions in the retrieval
hydration parallelism tests with a behavioral test of
hydrateCandidatesWithMetadataAndMemory. Mock attachDocumentRankingMetadata and
loadMemoryBoostArtifacts with deferred promises, invoke the helper, and assert
both operations are started before either promise resolves; retain coverage that
the helper is used across the intended retrieval branches without brittle
formatting or comment-string matching.
🪄 Autofix (Beta)

✅ Autofix completed


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 32043fc7-ce75-4772-aa1c-06bbffa7da04

📥 Commits

Reviewing files that changed from the base of the PR and between 3054d68 and b55f9b5.

📒 Files selected for processing (3)
  • src/lib/rag/rag-candidate-sources.ts
  • src/lib/rag/rag.ts
  • tests/rag-retrieval-parallelism.test.ts

Comment thread src/lib/rag/rag.ts Outdated
@BigSimmo
BigSimmo enabled auto-merge (squash) July 30, 2026 19:10
@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Note

Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it.

Fixes Applied Successfully

Fixed 3 file(s) based on 1 unresolved review comment.

Files modified:

  • docs/outstanding-issues.md
  • src/lib/rag/rag.ts
  • tests/eval-retrieval.test.ts

Commit: 690f499a6d0265174d6a9959eca6130d8106a206

The changes have been pushed to the codex/parallelise-safe-retrieval-stages branch.

Time taken: 5m 8s

@BigSimmo
BigSimmo disabled auto-merge July 30, 2026 19:16
coderabbitai Bot and others added 3 commits July 30, 2026 19:17
Fixed 3 file(s) based on 1 unresolved review comment.

Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
# Conflicts:
#	docs/outstanding-issues.md
#	src/lib/rag/rag.ts
@BigSimmo BigSimmo added the skip-branch-sync Opt out of hosted pr-branch-sync / update-branch on this PR label Jul 30, 2026
@BigSimmo
BigSimmo enabled auto-merge (squash) July 30, 2026 21:10
@BigSimmo
BigSimmo disabled auto-merge July 30, 2026 21:13
@BigSimmo
BigSimmo enabled auto-merge (squash) July 30, 2026 21:14
@BigSimmo
BigSimmo disabled auto-merge July 30, 2026 21:15
@BigSimmo
BigSimmo requested a review from Copilot July 30, 2026 21:16
@BigSimmo
BigSimmo enabled auto-merge (squash) July 30, 2026 21:16
@BigSimmo
BigSimmo disabled auto-merge July 30, 2026 21:20
@BigSimmo
BigSimmo enabled auto-merge (squash) July 30, 2026 21:20
@BigSimmo
BigSimmo merged commit badcb36 into main Jul 30, 2026
24 of 25 checks passed
@BigSimmo
BigSimmo deleted the codex/parallelise-safe-retrieval-stages branch July 30, 2026 21:21

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR reduces RAG retrieval latency by overlapping two independent hydration reads—document ranking metadata and memory-card evidence—while keeping candidate assembly deterministic (memory boosts applied only after both reads complete) and maintaining existing caching semantics.

Changes:

  • Refactors memory-boost hydration to split “load artifacts” vs “apply artifacts”, enabling independent execution from metadata hydration (rag-candidate-sources.ts).
  • Introduces hydrateCandidatesWithMetadataAndMemory to run metadata + memory hydration concurrently and applies memory boosts deterministically afterward (rag-hydration.ts), then migrates three post-gate retrieval branches to use it (rag.ts).
  • Adds a focused contract test to assert the concurrency boundary and call-site adoption, and updates an eval test fixture to reflect the new phase key (tests/*).

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tests/rag-retrieval-parallelism.test.ts Adds a contract test asserting parallel hydration and verifying the helper is used at three call sites.
tests/eval-retrieval.test.ts Updates the latency telemetry fixture to use the new combined hydration phase key.
src/lib/rag/rag.ts Replaces three serial metadata→memory hydration sequences with the new parallel helper while preserving deterministic ordering.
src/lib/rag/rag-hydration.ts Adds hydrateCandidatesWithMetadataAndMemory, running metadata + memory reads concurrently and applying memory boosts after both settle.
src/lib/rag/rag-candidate-sources.ts Splits memory hydration into loadMemoryBoostArtifacts + applyMemoryBoostArtifacts, keeping withMemoryBoostedCandidates as a wrapper.
docs/branch-review-ledger.md Appends a review ledger entry for this PR’s review/run evidence.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1 to +25
import { readFileSync } from "node:fs";

import { describe, expect, it } from "vitest";

describe("retrieval hydration parallelism", () => {
it("overlaps only independent metadata and memory reads before deterministic assembly", () => {
const source = readFileSync("src/lib/rag/rag-hydration.ts", "utf8");
const helper = source.slice(
source.indexOf("export async function hydrateCandidatesWithMetadataAndMemory"),
source.indexOf("/** Attach document ranking metadata. */"),
);

expect(helper).toContain("Promise.all([");
expect(helper).toContain("attachDocumentRankingMetadata(");
expect(helper).toContain("loadMemoryBoostArtifacts({");
expect(helper.indexOf("applyMemoryBoostArtifacts(")).toBeGreaterThan(helper.indexOf("Promise.all(["));
});

it("uses the parallel helper on all post-gate vector and document-lookup branches", () => {
const source = readFileSync("src/lib/rag/rag.ts", "utf8");
const callCount = source.match(/await hydrateCandidatesWithMetadataAndMemory\(\{/g)?.length ?? 0;

expect(callCount).toBe(3);
});
});
Copilot AI added a commit that referenced this pull request Aug 12, 2026
fix #186 archive

- Restore #156 (read-modify-write race + Update-branch corruption) from
  archive back to the open issues section with its original full text; the
  underlying allocation race is not resolved by the conservative architecture
  decision described in the previous commit.
- Re-add #156 to the recommendations priority table as row 51 (between #101
  and #172, consistent with its original ordering).
- Correct #101 to credit only metadata and memory parallelisation
  (hydrateCandidatesWithMetadataAndMemory) from PR #1474; visual hydration
  (attachPageVisualEvidence) is still called serially after hydration on all
  six call sites and is explicitly listed as a remaining candidate.
- Update #186 archive text to reflect that only metadata+memory were updated
  in #101, not visual hydration.

Co-authored-by: BigSimmo <87357024+BigSimmo@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

codex skip-branch-sync Opt out of hosted pr-branch-sync / update-branch on this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants