Skip to content

fix: keep QMD session search paths roundtrip-safe#43523

Closed
holgergruenhagen wants to merge 2 commits into
openclaw:mainfrom
holgergruenhagen:fix/qmd-session-roundtrip-paths
Closed

fix: keep QMD session search paths roundtrip-safe#43523
holgergruenhagen wants to merge 2 commits into
openclaw:mainfrom
holgergruenhagen:fix/qmd-session-roundtrip-paths

Conversation

@holgergruenhagen

@holgergruenhagen holgergruenhagen commented Mar 11, 2026

Copy link
Copy Markdown

Summary

Closes #43519.

When an agent workspace lives under the OpenClaw state directory, exported QMD session markdown files can end up inside the workspace under qmd/sessions/....
In that case, memory_search was returning the workspace-relative path:

  • qmd/sessions/<file>.md

But memory_get treats the qmd/<collection>/... prefix as a virtual QMD path and therefore expects a real collection name such as:

  • qmd/sessions-coder/<file>.md

That made memory_search -> memory_get non-roundtrip-safe for session hits.

Fix

If a workspace-relative QMD hit would serialize to the reserved qmd/ prefix, return the collection-scoped virtual path instead:

  • qmd/<real-collection>/<file>.md

This preserves roundtrip safety while keeping normal in-workspace paths unchanged.

Tests

Added a regression test covering the exact case where session exports live under the workspace qmd/ directory and verifying that:

  • search returns qmd/sessions-<agentId>/...
  • read succeeds with that exact returned path

Verification

  • pnpm -s exec vitest run src/memory/qmd-manager.test.ts -t 'returns collection-scoped qmd paths when session exports live under the workspace qmd directory'
  • pnpm -s exec vitest run src/memory/qmd-manager.test.ts -t 'returns collection-scoped qmd paths when session exports live under the workspace qmd directory|diversifies mixed session and memory search results so memory hits are retained|blocks non-markdown or symlink reads for qmd paths'

@greptile-apps

greptile-apps Bot commented Mar 11, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a roundtrip-safety bug where memory_search followed by memory_get would fail when QMD session exports lived under the workspace's qmd/ subdirectory. Because qmd/ is a reserved virtual-path prefix, memory_search was returning the raw workspace-relative path (e.g. qmd/sessions/session-1.md) which memory_get could not resolve — it expected a collection-scoped form like qmd/sessions-<agentId>/session-1.md.

The fix is minimal and targeted:

  • In buildSearchPath, a new guard detects when the workspace-relative path equals "qmd" or starts with "qmd/" and redirects to the collection-scoped virtual form qmd/<collection>/<collectionRelativePath>, matching what resolveReadPath already expects.
  • The sanitized variable was moved above the insideWorkspace branch so both code paths share the same leading-slash-stripped value without duplication.
  • A regression test verifies the end-to-end roundtrip: search returns the collection-scoped path, and readFile succeeds with that exact path.

No logic errors or security concerns were found. The change is well-scoped, correct, and the accompanying test directly covers the reported failure mode.

Confidence Score: 5/5

  • This PR is safe to merge — it is a minimal, well-tested bug fix with no regressions or side effects.
  • The change is small (two files, ~20 lines of production code), correctly addresses the described root cause, does not weaken any security boundary in resolveReadPath (path-escape checks are unaffected), and is backed by a focused regression test that validates both the search path and the read-back roundtrip.
  • No files require special attention.

Last reviewed commit: 8543f21

@holgergruenhagen

Copy link
Copy Markdown
Author

Follow-up on the earlier red CI:

  • the previously failing jobs were rerun by pushing an empty retrigger commit
  • the failures did not reproduce
  • all relevant PR checks are now green, including:
    • check
    • build-artifacts
    • checks (node, test, ...)
    • checks (bun, test, ...)
    • checks (node, extensions, ...)
    • checks (node, protocol, ...)
    • all checks-windows shards
    • install-smoke

This looks like transient CI / setup-install flakiness rather than something caused by the QMD roundtrip fix itself.

@vincentkoc

Copy link
Copy Markdown
Member

Thanks for the original fix attempt here, @holgergruenhagen.

I reworked this on top of current main in #57560. The underlying bug is still real, but the current code path now lives in the QMD manager's workspace-path translation logic, so the narrow current fix needed a fresh port rather than landing this branch directly.

Closing this as superseded by #57560 to keep the queue clean while preserving attribution.

@vincentkoc vincentkoc closed this Mar 30, 2026
@holgergruenhagen

Copy link
Copy Markdown
Author

Thanks for the rework in #57560, @vincentkoc! Makes total sense to port it fresh given the code path has moved since. Appreciate you confirming the root cause and keeping the fix alive — looking forward to seeing it land. 🙌

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.

QMD session recall roundtrip breaks because memory_search returns source alias instead of real collection name

2 participants