Skip to content

fix(memory): search memory and wiki concurrently for corpus=all (#92633)#92833

Closed
openperf wants to merge 1 commit into
openclaw:mainfrom
openperf:fix/92633-memory-search-corpus-all-concurrent
Closed

fix(memory): search memory and wiki concurrently for corpus=all (#92633)#92833
openperf wants to merge 1 commit into
openclaw:mainfrom
openperf:fix/92633-memory-search-corpus-all-concurrent

Conversation

@openperf

Copy link
Copy Markdown
Member

Summary

  • memory_search with corpus=all ran the builtin memory/sessions branch and the wiki/supplement branch sequentially under one 15s tool deadline. Two searches that each finished well under 15s individually summed past the deadline, so corpus=all consistently returned results: [] with disabled: true while corpus=memory, corpus=sessions, corpus=wiki, and the CLI all succeeded.
  • This change starts the wiki/supplement search concurrently with the memory/sessions search inside the same deadline. The combined wall time drops from memory + wiki to roughly max(memory, wiki), so corpus=all fits the deadline and returns merged results.
  • The two branches share no mutable state, so overlapping them is safe; result merging, corpus balancing, the cooldown decision, and paused-index handling are unchanged.

Root cause

In the memory_search tool runner, the supplement branch was awaited only after the memory branch fully resolved (manager fetch → vector search → optional forced resync → visibility filtering → decoration). The wiki/supplement branch then performed its own independent embedding and search. Under a single shared 15s deadline the two latencies added together, so an aggregation that was healthy per-corpus timed out as a whole and was misreported as an embedding/provider failure.

Fix

  • Kick off the supplement-search promise before the memory branch begins and await it at the existing merge point, so both branches run within the same deadline window concurrently.
  • Keep the supplement branch out of the memory cooldown phase tracker so the corpus=all cooldown attribution stays single-writer and deterministic: a wiki failure can no longer race a real memory-backend failure into skipping the cooldown.
  • Guard the hoisted promise so an early paused-index return cannot leave it rejected-but-unobserved.
  • No change to result merging, corpus balancing, cooldown recording semantics, or the unavailable/paused result shapes.

Real behavior proof

Behavior addressed: memory_search({ corpus: "all" }) no longer times out and returns empty when the memory and wiki branches each complete within the deadline but sum past it; it now returns merged memory + wiki results, and a real memory-backend failure still records the cooldown even when the wiki branch fails too.

Real environment tested (memory-core extension Vitest suite, Linux, Node 24): a deterministic concurrency regression test drives the real tool runner with a memory search and a registered wiki supplement that each take 9s under fake timers, plus a both-branches-throw test for the cooldown attribution.

Exact steps or command run after this patch (pnpm test extensions/memory-core/src/tools.citations.test.ts extensions/memory-core/src/tools.test.ts): the new cases runs the memory and wiki branches concurrently for corpus=all (#92633) and records the memory cooldown when corpus=all memory and wiki both fail (#92633), plus the full files.

Evidence after fix (advancing fake time by 9s resolves the tool with both corpora): corpus=all returns [["wiki","entities/alpha.md"],["memory","MEMORY.md"]] with disabled undefined; the both-fail case still records the memory cooldown so the next memory search is suppressed. All 39 cases across the two suites pass.

Observed result after fix (the same two 9s branches that summed to 18s sequentially now complete at ~9s): with the production change reverted, the identical concurrency test hangs until the 120s test timeout because the wiki branch only starts after the memory branch finishes; with the change it resolves at 9s.

What was not tested (a live gateway against a real OpenAI-compatible embedding endpoint, text-embedding-v4, and a real compiled-wiki supplement on Windows Server): the reporter's exact environment was not reproduced; proof is the deterministic two-slow-branch simulation of the shared-deadline path.

Reproduction

  1. Configure memory_search with a healthy embedding provider and at least one registered wiki/compiled-wiki supplement, where the builtin memory/sessions search and the wiki search each take several seconds.
  2. Call memory_search({ query, corpus: "memory" }), corpus: "sessions", and corpus: "wiki" — each succeeds within the 15s deadline.
  3. Call memory_search({ query, corpus: "all" }).
  4. Before this PR: the memory and wiki branches run one after the other, their latencies add up past 15s, and the tool returns results: [], disabled: true, error: "memory_search timed out after 15s".
  5. After this PR: both branches run concurrently within the deadline, the tool returns the merged memory + wiki results.

Risk / Mitigation

  • Risk: concurrent execution could race shared per-call state. Mitigation: the branches write disjoint locals (memory result/provider/debug vs. supplement results), and the supplement branch is deliberately kept out of the cooldown phase tracker so that tracker has a single writer.
  • Risk: a hoisted supplement promise could become an unobserved rejection if the memory branch returns early (paused index). Mitigation: the promise is guarded with a no-op catch, and the real rejection still surfaces at the awaited merge point on the normal path.
  • Risk: a genuinely hung wiki supplement could still trip the deadline. Mitigation: unchanged from today — a non-resolving branch still times out, and the existing stall tests continue to pass.

Change Type (select all)

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Refactor / internal change

Scope (select all touched areas)

  • Memory / dreaming (extensions/memory-core)
  • Core runtime / gateway
  • Channels / plugins
  • Config / migrations
  • Docs

Linked Issue/PR

Fixes #92633

…claw#92633)

corpus=all awaited the memory/sessions branch fully before starting the
wiki/supplement branch, so two searches that each fit the 15s tool
deadline summed past it and the tool returned empty with disabled=true.
Start the supplement search concurrently with the memory branch within
the same deadline; combined wall time drops to ~max(branch).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
@clawsweeper

clawsweeper Bot commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed June 21, 2026, 3:36 PM ET / 19:36 UTC.

Summary
This PR starts the memory-core wiki/supplement search concurrently with the memory/session search for memory_search corpus=all and adds regression tests for concurrent timing and memory cooldown attribution.

PR surface: Source +9, Tests +98. Total +107 across 2 files.

Reproducibility: yes. Current main and v2026.6.9 await the memory/session branch before the wiki/supplement branch under the same 15s wrapper, so two individually sub-deadline branches can exceed the deadline when summed.

Review metrics: none identified.

Stored data model
Persistent data-model change detected: unknown-data-model-change: extensions/memory-core/src/tools.citations.test.ts, unknown-data-model-change: extensions/memory-core/src/tools.ts, vector/embedding metadata: extensions/memory-core/src/tools.citations.test.ts, vector/embedding metadata: extensions/memory-core/src/tools.ts. Confirm migration or upgrade compatibility proof before merge.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #92633
Summary: This PR is a candidate fix for the additive-latency root cause in the canonical all-corpus memory_search timeout issue; the attribution PR overlaps but does not replace it.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🌊 off-meta tidepool
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • Decide whether to narrow the PR body closing reference or keep the linked issue open for attribution/debug follow-up.

Risk before merge

Maintainer options:

  1. Narrow Issue Closure Before Merge (recommended)
    Change the closing wording or add a maintainer note so this PR lands the concurrency fix without automatically closing the broader timeout-attribution/debug report.
  2. Accept Scoped Closure
    Maintainers can intentionally treat the concurrency fix as closing the central user problem and keep attribution/debug behavior in the adjacent PR.
  3. Pause For Coordination
    Pause this PR if maintainers want one coordinated merge path for both concurrency and timeout-attribution behavior.

Next step before merge

  • [P2] No repair lane is needed; remaining action is maintainer judgment on linked issue closure scope before merge.

Security
Cleared: The diff only changes memory-core TypeScript runtime/tests and does not touch dependencies, workflows, secrets, package metadata, downloads, or release scripts.

Review details

Best possible solution:

Land the concurrency fix after maintainers decide issue-closure scope, and keep timeout attribution/debug behavior in #92647 or another canonical follow-up.

Do we have a high-confidence way to reproduce the issue?

Yes. Current main and v2026.6.9 await the memory/session branch before the wiki/supplement branch under the same 15s wrapper, so two individually sub-deadline branches can exceed the deadline when summed.

Is this the best way to solve the issue?

Yes for the narrow additive-latency bug. Starting the independent supplement branch earlier is the owner-local fix; warning attribution and partial/debug semantics remain separate work.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 6daf9307e0b9.

Label changes

Label justifications:

  • P2: The PR addresses a valid memory retrieval bug with limited blast radius in memory-core all-corpus aggregation.
  • merge-risk: 🚨 other: The PR can close a broader linked issue before separately requested timeout-attribution and debug-detail work is resolved.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🌊 off-meta tidepool and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Not applicable: The external-contributor proof gate does not apply because the PR author is a repository member; the PR body still includes deterministic after-fix tool-runner proof.
Evidence reviewed

PR surface:

Source +9, Tests +98. Total +107 across 2 files.

View PR surface stats
Area Files Added Removed Net
Source 1 24 15 +9
Tests 1 98 0 +98
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 2 122 15 +107

What I checked:

  • Root repository policy read: Root AGENTS.md was read fully and applied to the review-depth, PR-risk, extension-boundary, and maintainer-authored cleanup rules. (AGENTS.md:1, 6daf9307e0b9)
  • Scoped extension policy read: extensions/AGENTS.md was read fully; the PR stays inside the bundled plugin boundary and does not add public SDK/config surface. (extensions/AGENTS.md:1, 6daf9307e0b9)
  • Current main is still sequential: Current main awaits the memory branch and paused-index handling before calling searchMemoryCorpusSupplements, so memory and wiki latency can still add under the same 15s tool deadline. (extensions/memory-core/src/tools.ts:602, 6daf9307e0b9)
  • Latest release is still sequential: Tag v2026.6.9 contains the same memory-then-supplement ordering and generic provider warning, so the central behavior is not already shipped fixed. (extensions/memory-core/src/tools.ts:602, c645ec4555c0)
  • PR head starts supplements concurrently: The PR head hoists supplementResultsPromise before the memory branch and awaits it at the existing merge point, while keeping the unavailable phase tracker memory-only. (extensions/memory-core/src/tools.ts:443, bed7b4ec660b)
  • Regression coverage added: The PR adds a two-9s-branch fake-timer regression test for corpus=all concurrency and a both-branches-fail test proving memory cooldown attribution remains memory-owned. (extensions/memory-core/src/tools.citations.test.ts:498, bed7b4ec660b)

Likely related people:

  • vincentkoc: Authored the memory-core wiki corpus bridge and restored the memory-wiki stack that supplies the supplement branch used by corpus=all; current blame also carries the present supplement block through a recent forward commit. (role: wiki corpus feature-history owner; confidence: high; commits: 2f72363984b9, 5716d83336fd, 63fdc57b3ac2; files: extensions/memory-core/src/tools.ts, extensions/memory-core/src/tools.shared.ts, extensions/memory-wiki/index.ts)
  • dreamhunter2333: Authored the merged memory_search deadline/abort work that defines the current 15s wrapper and timeout behavior involved in this report. (role: deadline behavior introducer; confidence: high; commits: 8d72cb9401e5; files: extensions/memory-core/src/tools.ts, extensions/memory-core/src/tools.test.ts, extensions/memory-core/src/memory/manager-embedding-timeout.test.ts)
  • steipete: Recent memory-core history includes fail-open work around embedding recall stalls on the same memory search and provider-error surface. (role: recent memory search contributor; confidence: medium; commits: 9e2bd8b2f7eb; files: extensions/memory-core/src/tools.ts, extensions/memory-core/src/tools.citations.test.ts, extensions/memory-core/src/memory/manager-embedding-ops.ts)
  • TurboTheTurtle: Recently merged qmd-mode work touched nearby memory_search flow and tests shortly before this timeout report cluster. (role: recent adjacent contributor; confidence: medium; commits: ddacb7ba39d4; files: extensions/memory-core/src/tools.ts, extensions/memory-core/src/tools.shared.ts, extensions/memory-core/src/tools.citations.test.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. P2 Normal backlog priority with limited blast radius. labels Jun 14, 2026
@clawsweeper clawsweeper Bot added the merge-risk: 🚨 other 🚨 Merging this PR has meaningful risk outside the owned taxonomy. label Jun 20, 2026
@openclaw-barnacle

Copy link
Copy Markdown

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@openclaw-barnacle

Copy link
Copy Markdown

Closing due to inactivity.
If you believe this PR should be revived, post in #clawtributors on Discord to talk to a maintainer.
That channel is the escape hatch for high-quality PRs that get auto-closed.

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

Labels

extensions: memory-core Extension: memory-core merge-risk: 🚨 other 🚨 Merging this PR has meaningful risk outside the owned taxonomy. P2 Normal backlog priority with limited blast radius. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. size: S stale Marked as stale due to inactivity status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

memory_search corpus=all times out while individual corpora succeed

1 participant