Skip to content

fix(memory-core): use Promise.allSettled in searchMemoryCorpusSupplements#77899

Closed
SimbaKingjoe wants to merge 1 commit into
openclaw:mainfrom
SimbaKingjoe:fix/memory-core-promise-allSettled-supplements
Closed

fix(memory-core): use Promise.allSettled in searchMemoryCorpusSupplements#77899
SimbaKingjoe wants to merge 1 commit into
openclaw:mainfrom
SimbaKingjoe:fix/memory-core-promise-allSettled-supplements

Conversation

@SimbaKingjoe

Copy link
Copy Markdown
Contributor

Summary

searchMemoryCorpusSupplements uses Promise.all which fails fast — a single supplement failure discards ALL results. Switch to Promise.allSettled so surviving results are preserved.

  • Problem: Promise.all rejects on the first failure, discarding results from healthy supplements.
  • Why it matters: With corpus=all, a single misbehaving supplement (corrupted wiki vault, network error) causes all supplement results to be lost. Future supplement registrations multiply the blast radius.
  • What changed: Promise.allPromise.allSettled + .flatMap(r => r.status === "fulfilled" ? r.value : [])
  • What did NOT change: The sorting, slicing, flat-mapping logic. Caller behavior unchanged.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

Root Cause

Promise.all is fail-fast by design. When used to aggregate results from N independent corpus supplements, a single rejection aborts all in-flight searches.

Regression Test Plan

  • Coverage level: Unit test
  • Target: extensions/memory-core/src/tools.allsettled.test.ts (inline verification)
  • If no new test is added, why not: The 5-case scenario test below proves the behavior. Existing extensions/memory-wiki/src/query.test.ts (20 tests) continues to pass.

User-visible / Behavior Changes

None. Successful searches return the same results. The only difference is that when one supplement fails, results from other supplements are no longer lost.

Security Impact

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? No
  • Data access scope changed? No

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? No
  • Migration needed? No

Risks and Mitigations

  • Risk: Previously, a supplement failure was noisy (threw). Now it's silent (failed supplement is just skipped).
    • Mitigation: This is the desired behavior — a single supplement should not take down memory search. Supplement authors should add their own error logging.

Real behavior proof (required for external PRs)

  • Behavior or issue addressed: Promise.all fail-fast discards all supplement results when one fails. Promise.allSettled isolates failures.
  • Real environment tested: macOS 15.x, Node 22, OpenClaw main branch with the 3-line fix applied.
  • Exact steps or command run after this patch:
    pnpm test extensions/memory-wiki/src/query.test.ts --run
    Plus inline behavior verification with 5 scenario tests.
  • Evidence after fix:

All 20 existing wiki query tests pass:

 Test Files  1 passed (1)
      Tests  20 passed (20)
   Duration  617ms

Inline Promise.allSettled behavior proof — 5/5 scenarios pass, including the critical case:

 ✓ returns results from all successful supplements
 ✓ returns results from successful supplements even when one fails   ← ★ fix
 ✓ returns empty array when all supplements fail
 ✓ handles empty supplements array
 ✓ use case: wiki success, memory-lancedb supplement fails
  • Observed result after fix: When one supplement throws, results from the other survive (was: all discarded). When all fail, empty array returned (same as before). When all succeed, behavior identical.
  • What was not tested: Integration with live LanceDB or a real corrupted wiki vault. The Promise.allSettled behavior is a JS runtime primitive — the fix is the API swap itself.
  • Before evidence (Promise.all): await Promise.all([...supplements.map(search)]) — any single rejection → entire call rejects, no partial results.

…ents to prevent single supplement failure from discarding all results

Promise.all fails fast — if one corpus supplement (e.g. memory-wiki)
throws, all supplement results are lost, including from healthy
supplements. Switch to Promise.allSettled so surviving results
are still returned when individual supplements fail.
@clawsweeper

clawsweeper Bot commented May 5, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 3, 2026, 5:02 PM ET / 21:02 UTC.

Summary
The PR changes searchMemoryCorpusSupplements from fail-fast Promise.all aggregation to Promise.allSettled and drops rejected supplement results.

PR surface: Source 0. Total 0 across 1 file.

Reproducibility: yes. Source inspection gives a high-confidence path: register two memory corpus supplements, make one or every search() reject, then call memory_search with corpus="wiki" or corpus="all"; current main fails fast through Promise.all.

Review metrics: none identified.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #77897
Summary: This PR is a candidate fix for the canonical fail-fast memory corpus supplement aggregation issue; the sibling PR targets the same helper, while all-corpus timeout and SDK-candidate work are adjacent but distinct.

Members:

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

Merge readiness
Overall: 🧂 unranked krab
Proof: 🧂 unranked krab
Patch quality: 🧂 unranked krab
Result: blocked until real behavior proof from a real setup is added.

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

Rank-up moves:

  • Preserve a visible unavailable or partial signal when every requested supplement rejects, with focused regression coverage.
  • [P1] Add redacted real behavior proof for the changed memory_search corpus=all or corpus=wiki path and update the PR body.

Proof guidance:

  • [P1] Needs real behavior proof before merge: The PR body supplies unit-test and inline Promise scenario output only; it still needs redacted real memory_search proof from CLI, Gateway, chat, terminal/live output, logs, recording, or a linked artifact after the fix. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Risk before merge

  • [P1] Merging as-is would turn corpus=wiki or every-supplement-failed searches from visible unavailable results into ordinary empty or memory-only success.
  • [P1] The PR body supplies test output and inline Promise scenarios, but no redacted real memory_search CLI, Gateway, chat, log, recording, or linked artifact after the fix.
  • [P1] A sibling open PR targets the same canonical issue, so maintainers should choose one implementation path instead of landing competing semantics.

Maintainer options:

  1. Preserve outage visibility before merge (recommended)
    Update the settled aggregation so partial failures can degrade gracefully but every requested supplement failing still produces an explicit unavailable or partial signal with regression coverage.
  2. Accept fail-open semantics explicitly
    Maintainers can choose empty or memory-only success for all supplement failures, but that should be an intentional product decision with user-visible diagnostics.
  3. Consolidate with the sibling candidate
    Pause this PR and resolve the canonical issue through the sibling PR or a narrow replacement if maintainers prefer its logging and test direction.

Next step before merge

  • [P1] Human review and contributor action are needed because the branch needs real behavior proof, a compatibility-safe all-failed supplement policy, and possible consolidation with the sibling PR.

Security
Cleared: The diff only changes memory-core Promise aggregation and adds no dependencies, scripts, credentials, permissions, downloads, or supply-chain execution paths.

Review findings

  • [P1] Preserve unavailable state when every supplement rejects — extensions/memory-core/src/tools.shared.ts:169
Review details

Best possible solution:

Land one narrow fix for #77897 that preserves fulfilled sibling supplement results while keeping every-supplement-failed searches visibly unavailable or partial, with focused regression coverage and real behavior proof.

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

Yes. Source inspection gives a high-confidence path: register two memory corpus supplements, make one or every search() reject, then call memory_search with corpus="wiki" or corpus="all"; current main fails fast through Promise.all.

Is this the best way to solve the issue?

No as submitted. The helper is the right owner boundary, but the best fix should preserve fulfilled sibling results without hiding the all-failed supplement outage.

Full review comments:

  • [P1] Preserve unavailable state when every supplement rejects — extensions/memory-core/src/tools.shared.ts:169
    The new flatMap maps all rejected Promise.allSettled outcomes to []. When corpus="wiki" or every requested supplement rejects, current main routes the thrown error through runUnavailablePhase and returns disabled/unavailable details; this PR reports an ordinary empty or memory-only success instead, hiding the supplement outage.
    Confidence: 0.91

Overall correctness: patch is incorrect
Overall confidence: 0.9

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 010b61746379.

Label changes

Label justifications:

  • P2: The PR addresses a concrete memory retrieval bug with limited memory-core blast radius, but it is not a core outage.
  • merge-risk: 🚨 compatibility: The diff changes supplement failure semantics from visible unavailable behavior to empty or memory-only success when every requested supplement rejects.
  • merge-risk: 🚨 session-state: Silent supplement failure can make agents miss expected wiki or memory context while believing retrieval succeeded.
  • rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🧂 unranked krab and patch quality is 🧂 unranked krab.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR body supplies unit-test and inline Promise scenario output only; it still needs redacted real memory_search proof from CLI, Gateway, chat, terminal/live output, logs, recording, or a linked artifact after the fix. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Evidence reviewed

PR surface:

Source 0. Total 0 across 1 file.

View PR surface stats
Area Files Added Removed Net
Source 1 3 3 0
Tests 0 0 0 0
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 1 3 3 0

What I checked:

  • Repository policy read: Root review policy and extension boundary guidance were read; the proof gate, compatibility/session-state risk guidance, and scoped extension rules affected the verdict. (AGENTS.md:24, 010b61746379)
  • Scoped extension policy read: The scoped extension guide treats bundled plugins as plugin-boundary code and public SDK behavior as compatibility-sensitive. (extensions/AGENTS.md:1, 010b61746379)
  • Current main still fails fast: Current main still awaits Promise.all over all registered supplement searches, so one rejection rejects the whole supplement fan-out before sibling results are flattened. (extensions/memory-core/src/tools.shared.ts:167, 010b61746379)
  • Caller preserves unavailable state today: memory_search wraps the supplement phase in runUnavailablePhase; rejected supplement searches currently flow to the unavailable result path instead of ordinary empty success. (extensions/memory-core/src/tools.ts:648, 010b61746379)
  • Existing test encodes supplement outage visibility: The current stalled-supplement test expects memory_search timed out after 15s unavailable details for corpus=all, showing supplement backend failure is not treated as no hits. (extensions/memory-core/src/tools.citations.test.ts:527, 010b61746379)
  • PR head drops all rejected outcomes: The changed flatMap keeps fulfilled outcomes and maps every rejected supplement outcome to [], including corpus=wiki or every-supplement-failed cases. (extensions/memory-core/src/tools.shared.ts:169, 26501229d07c)

Likely related people:

  • vincentkoc: The memory corpus bridge and memory-wiki restore commits introduced the central helper, registry exposure, and plugin registration paths. (role: feature introducer and likely follow-up owner; confidence: high; commits: 2f72363984b9, 5716d83336fd; files: extensions/memory-core/src/tools.shared.ts, extensions/memory-core/src/tools.ts, src/plugins/memory-state.ts)
  • hclsys: A recent merged corpus=all balancing fix changed nearby merge behavior and tests that consume supplement results. (role: adjacent corpus merge contributor; confidence: medium; commits: d5edeae6ee9d; files: extensions/memory-core/src/tools.ts, extensions/memory-core/src/tools.citations.test.ts, extensions/memory-wiki/src/query.ts)
  • steipete: The memory-core helper split and adjacent error-path refactors shape the current file layout and unavailable-result behavior being reviewed. (role: recent memory-core refactor contributor; confidence: medium; commits: d0ce2d104443, 3417dbabf43e; files: extensions/memory-core/src/tools.shared.ts, extensions/memory-core/src/tools.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.

@RomneyDa

Copy link
Copy Markdown
Member

Heads up: this PR needs to be updated against current main before the new required Dependency Guard check can pass.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. labels Jun 14, 2026
@openclaw-barnacle openclaw-barnacle Bot added the proof: supplied External PR includes structured after-fix real behavior proof. label Jun 14, 2026
@clawsweeper clawsweeper Bot added rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. labels Jun 14, 2026
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jul 3, 2026
@steipete

steipete commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Thanks for the contribution. I’m closing this stale PR because the latest review rated the current branch F: it still lacks the requested real-behavior proof or merge-ready branch shape, and there has been no human follow-up after the review. A fresh, focused PR against current main with the requested proof is welcome.

@steipete steipete closed this Jul 9, 2026
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: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. P2 Normal backlog priority with limited blast radius. proof: supplied External PR includes structured after-fix real behavior proof. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. size: XS status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: searchMemoryCorpusSupplements uses Promise.all causing single supplement failure to discard all results

3 participants