Skip to content

fix(memory): preserve shared qmd collection names#57628

Merged
vincentkoc merged 3 commits into
mainfrom
fix/qmd-binary-warning
Mar 30, 2026
Merged

fix(memory): preserve shared qmd collection names#57628
vincentkoc merged 3 commits into
mainfrom
fix/qmd-binary-warning

Conversation

@vincentkoc

Copy link
Copy Markdown
Member

Summary

  • Problem: OpenClaw was suffixing explicit custom memory.qmd.paths[*].name collections with -<agentId>, so shared external QMD collections like notion-mirror were queried as notion-mirror-main and missed entirely.
  • Why it matters: memory_search could not hit externally managed shared QMD collections even when users configured the correct collection name.
  • What changed: preserve explicit custom collection names for paths outside the agent workspace, while keeping OpenClaw-owned default collections and unnamed extra paths agent-scoped.
  • What did NOT change (scope boundary): workspace-local named paths, default memory collections, session collections, and unnamed memorySearch.extraPaths still keep current agent scoping.

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 / Regression History (if applicable)

  • Root cause: packages/memory-host-sdk/src/host/backend-config.ts ran custom memory.qmd.paths[*].name entries through the same scopeCollectionBase(...) path as OpenClaw-owned collections, so the configured external collection identity was rewritten before search execution.
  • Missing detection / guardrail: resolver coverage verified agent scoping, but did not distinguish shared external custom collections from workspace-owned collections.
  • Prior context (git blame, prior PR, issue, or refactor if known): the current behavior lives in the post-refactor SDK host resolver path.
  • Why this regressed now: shared external QMD collections became a real user path, but the config layer still assumed every custom collection should be isolated per agent.
  • If unknown, what was ruled out: N/A.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: packages/memory-host-sdk/src/host/backend-config.test.ts, extensions/memory-core/src/memory/qmd-manager.test.ts
  • Scenario the test should lock in: explicit named custom paths outside the workspace keep their configured collection name verbatim and QMD search uses that exact name.
  • Why this is the smallest reliable guardrail: the bug starts in config resolution but only matters once the manager issues search calls.
  • Existing test that already covers this (if any): N/A.
  • If no new test is added, why not: N/A.

User-visible / Behavior Changes

  • Explicit named memory.qmd.paths[*] entries that point outside the agent workspace now keep their configured collection name instead of gaining -<agentId>.
  • Unnamed extra paths and OpenClaw-owned workspace/session collections keep current per-agent scoping.

Diagram (if applicable)

Before:
[external named collection notion-mirror] -> [resolver rewrites to notion-mirror-main] -> [QMD search misses collection]

After:
[external named collection notion-mirror] -> [resolver keeps notion-mirror] -> [QMD search hits shared collection]

Security Impact (required)

  • 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)
  • If any Yes, explain risk + mitigation:

Repro + Verification

Environment

  • OS: macOS host
  • Runtime/container: local repo dev runtime
  • Model/provider: N/A
  • Integration/channel (if any): QMD backend
  • Relevant config (redacted): memory.backend=qmd, explicit memory.qmd.paths[*].name, path outside workspace

Steps

  1. Configure memory.backend=qmd with an explicit named custom path outside the agent workspace, for example name: notion-mirror.
  2. Run memory_search from an agent using that QMD backend.
  3. Inspect the resolved collection names / QMD CLI search calls.

Expected

  • OpenClaw searches notion-mirror exactly.

Actual

  • Before this fix, OpenClaw searched notion-mirror-main and missed the real shared collection.

Evidence

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

  • Verified scenarios: resolver preserves explicit names for external custom paths; unnamed extra paths remain agent-scoped; QMD manager search calls use notion-mirror verbatim.
  • Edge cases checked: workspace-local named paths still scope; default memory collections still scope; unnamed extra paths outside workspace still scope.
  • What you did not verify: live QMD daemon against a real external mirror collection.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? (Yes)
  • Config/env changes? (No)
  • Migration needed? (No)
  • If yes, exact upgrade steps:

Risks and Mitigations

  • Risk: users relying on agent-suffixed names for explicitly named external collections could see collection selection change.
    • Mitigation: the change is narrowed to explicit names outside the workspace, which is the shared-collection case that was already broken; workspace-local named paths and unnamed paths keep prior behavior.

@vincentkoc vincentkoc self-assigned this Mar 30, 2026
@vincentkoc vincentkoc added the bug Something isn't working label Mar 30, 2026
@openclaw-barnacle openclaw-barnacle Bot added the maintainer Maintainer-authored PR label Mar 30, 2026
@vincentkoc vincentkoc marked this pull request as ready for review March 30, 2026 10:13
@greptile-apps

greptile-apps Bot commented Mar 30, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a bug in packages/memory-host-sdk/src/host/backend-config.ts where every memory.qmd.paths[*].name entry — including explicitly named external/shared QMD collections — was being run through scopeCollectionBase(...), appending -<agentId> to the configured name. This caused memory_search to query e.g. notion-mirror-main instead of the real notion-mirror collection, silently missing all results.

Key changes:

  • New isPathInsideRoot(candidate, root) helper uses path.relative + path.resolve to determine whether a configured path lives inside the agent workspace directory.
  • resolveCustomPaths now branches on explicitName && !isPathInsideRoot(resolved, workspaceDir): external paths with an explicit name keep that name verbatim (no agent suffix); all other cases (unnamed paths, workspace-local named paths) retain prior agent-scoping behavior.
  • Two new unit tests in backend-config.test.ts cover the new branch and the unnamed-external-path boundary.
  • One new integration test in qmd-manager.test.ts verifies the QMD spawn call uses the exact configured collection name end-to-end.
  • CHANGELOG entry added.

The change is minimal and well-scoped. No issues were found.

Confidence Score: 5/5

Safe to merge — targeted one-line logic change backed by comprehensive unit and integration tests, with no new permissions or network calls.

The fix is narrow and correct: isPathInsideRoot handles all POSIX and Windows cross-drive edge cases via path.relative/path.resolve, the four-quadrant branching (internal/external × named/unnamed) maps cleanly onto the stated scope boundary, and both the resolver-level unit tests and the end-to-end spawn-assertion integration test lock in the new behaviour. No P0 or P1 issues were found.

No files require special attention.

Important Files Changed

Filename Overview
packages/memory-host-sdk/src/host/backend-config.ts Core fix: adds isPathInsideRoot helper and updates resolveCustomPaths to skip agent-scoping when a path entry has an explicit name and lives outside the workspace. Logic is correct across all four cases.
packages/memory-host-sdk/src/host/backend-config.test.ts Two new unit tests: one verifying explicit external named paths produce verbatim collection names for all agents, one confirming unnamed extraPaths entries remain agent-scoped even when outside the workspace.
extensions/memory-core/src/memory/qmd-manager.test.ts Integration test added verifying the QMD spawn call uses -c notion-mirror verbatim, covering the full path from config resolution through search invocation.
CHANGELOG.md Entry added to current beta section describing the fix and crediting contributors. No issues.

Reviews (1): Last reviewed commit: "Merge branch 'main' into fix/qmd-binary-..." | Re-trigger Greptile

@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: d1dc7dbfbc

ℹ️ 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 packages/memory-host-sdk/src/host/backend-config.ts Outdated
@vincentkoc vincentkoc merged commit b7de04f into main Mar 30, 2026
9 checks passed
@vincentkoc vincentkoc deleted the fix/qmd-binary-warning branch March 30, 2026 10:29
pgondhi987 pushed a commit to pgondhi987/openclaw that referenced this pull request Mar 31, 2026
* fix(memory): preserve shared qmd collection names

* fix(memory): canonicalize qmd path containment
pgondhi987 pushed a commit to pgondhi987/openclaw that referenced this pull request Mar 31, 2026
* fix(memory): preserve shared qmd collection names

* fix(memory): canonicalize qmd path containment
lovewanwan pushed a commit to lovewanwan/openclaw that referenced this pull request Apr 28, 2026
* fix(memory): preserve shared qmd collection names

* fix(memory): canonicalize qmd path containment
Tardisyuan pushed a commit to Tardisyuan/openclaw that referenced this pull request Apr 30, 2026
* fix(memory): preserve shared qmd collection names

* fix(memory): canonicalize qmd path containment
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
* fix(memory): preserve shared qmd collection names

* fix(memory): canonicalize qmd path containment
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
* fix(memory): preserve shared qmd collection names

* fix(memory): canonicalize qmd path containment
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 24, 2026
* fix(memory): preserve shared qmd collection names

* fix(memory): canonicalize qmd path containment
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working extensions: memory-core Extension: memory-core maintainer Maintainer-authored PR size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

memory_search fails: agent ID suffix appended to custom QMD collection names

1 participant