openclaw - ✅(Solved) Fix memory-wiki bridge still returns 0 after #72615 due to split memory-state singleton in plugin-runtime-deps [1 pull requests, 2 comments, 3 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#74981Fetched 2026-05-01 05:39:18
View on GitHub
Comments
2
Participants
3
Timeline
11
Reactions
2
Author
Timeline (top)
mentioned ×4subscribed ×4commented ×2cross-referenced ×1

memory-wiki bridge still imports 0 artifacts on OpenClaw 2026.4.27 even though PR #72615 is installed and memory-core does register publicArtifacts correctly.

The remaining bug appears to be a split singleton between the installed OpenClaw dist and the managed plugin-runtime-deps dist mirror:

  • memory-core registers publicArtifacts into the canonical installed dist/memory-state-*.js module.
  • memory-wiki bridge gateway method runs from the managed plugin-runtime-deps/openclaw-2026.4.27-*/dist/... mirror and calls listActiveMemoryPublicArtifacts() from the mirrored dist/memory-state-*.js module.
  • That mirrored module has a separate empty memoryPluginState, so wiki.bridge.import sees hasCapability=false and returns artifactCount: 0.

So #72615 fixed CLI → Gateway routing, but the Gateway bridge path can still read the wrong memory-state singleton.

Root Cause

A local workaround would be to make the mirrored memory-state-*.js re-export the canonical installed module, but that is fragile because plugin-runtime-deps is regenerated.

Fix Action

Fix / Workaround

A local workaround would be to make the mirrored memory-state-*.js re-export the canonical installed module, but that is fragile because plugin-runtime-deps is regenerated.

PR fix notes

PR #75064: fix(memory): share plugin state across runtime mirrors

Description (problem / solution / changelog)

Summary

Refs #74981.

Memory plugin state was module-local, so mirrored runtime chunks in the same Gateway process could observe different memory capability registries. Memory Wiki bridge/status can then see zero public artifacts even after memory-core registered them.

This moves the existing memory plugin state object into OpenClaw's shared createPluginRuntimeStore mechanism so duplicate module instances observe the same in-process registry.

Changes

  • Reuse createPluginRuntimeStore for memory-state registry storage.
  • Preserve the existing memory plugin SDK API and in-place clear/restore behavior.
  • Add mirrored-runtime regression coverage for memory-state, Memory Wiki bridge import, and Memory Wiki status artifact counting.

Validation

Local validation was intentionally light on this constrained VPS:

  • git diff --check

Please rely on CI/Testbox for full test/typecheck validation.

Possible durable follow-up

A broader follow-up could move memory capabilities behind a canonical host-owned capability service so plugin registration and artifact reads never depend on which SDK/runtime chunk imported memory-state.

Suggested prompt for a coding agent:

# Task
Design and implement a durable host-owned memory capability registry for OpenClaw plugin runtime boundaries.

## Goal
Memory plugins should register capabilities through one canonical host-owned service, and all consumers should read active memory capabilities/artifacts through that service. The result should not depend on whether code is loaded from canonical dist, plugin-runtime-deps, a runtime mirror, or an extension bundle.

## Constraints
- Keep the existing public plugin SDK API backward compatible unless a small documented migration is clearly necessary.
- Avoid broad refactors. Prefer a narrow host capability seam with focused adapter changes.
- Do not special-case Memory Wiki, memory-core, or any local filesystem path.
- Preserve plugin disablement, memory-slot selection, and dual-kind memory plugin guardrails.
- Do not expand filesystem, network, or secret access.
- Add regression coverage for canonical-vs-mirrored runtime module instances.

## Starting points
- `src/plugins/memory-state.ts`
- `src/plugins/registry.ts`
- `src/plugin-sdk/memory-core-host-runtime-core.ts`
- `src/plugin-sdk/runtime-store.ts`
- `extensions/memory-wiki/src/bridge.ts`
- `extensions/memory-wiki/src/status.ts`
- plugin/runtime mirror tests around `src/plugins/loader.test.ts` and `src/plugin-sdk/runtime-store.test.ts`

## Acceptance criteria
1. A memory capability registered by the selected memory plugin is visible to all host and extension consumers in the same Gateway process, even when they load through mirrored runtime chunks.
2. Memory Wiki bridge/status read artifacts through the canonical host-owned seam, not incidental module-local state.
3. Existing memory plugin APIs remain source-compatible.
4. Tests cover duplicate module instance behavior and the Memory Wiki bridge/status artifact-count regression.
5. Full changed-surface validation passes in CI/Testbox.

## Output
Return a concise summary of the architecture, files changed, compatibility notes, and verification evidence.

Changed files

  • extensions/memory-wiki/src/bridge.test.ts (modified, +50/-0)
  • extensions/memory-wiki/src/status.test.ts (modified, +65/-1)
  • src/plugins/memory-state.test.ts (modified, +38/-0)
  • src/plugins/memory-state.ts (modified, +17/-4)

Code Example

{
  "plugins": {
    "slots": { "memory": "memory-core" },
    "entries": {
      "memory-core": { "config": { "dreaming": { "enabled": true } } },
      "memory-wiki": {
        "enabled": true,
        "config": {
          "vaultMode": "bridge",
          "bridge": {
            "enabled": true,
            "readMemoryArtifacts": true,
            "indexDailyNotes": true,
            "indexMemoryRoot": true,
            "indexDreamReports": true,
            "followMemoryEvents": true
          }
        }
      }
    }
  }
}

---

openclaw gateway call wiki.bridge.import --json --timeout 60000

---

{
  "importedCount": 0,
  "updatedCount": 0,
  "skippedCount": 0,
  "removedCount": 0,
  "artifactCount": 0,
  "workspaces": 0,
  "pagePaths": [],
  "indexesRefreshed": false,
  "indexUpdatedFiles": [],
  "indexRefreshReason": "no-import-changes"
}

---

{
  "vaultMode": "bridge",
  "bridgePublicArtifactCount": 0,
  "warnings": [
    {
      "code": "bridge-artifacts-missing",
      "message": "Bridge mode is enabled but the active memory plugin is not exporting any public memory artifacts yet."
    }
  ]
}

---

{
  "registered": true,
  "keys": ["promptBuilder", "flushPlanResolver", "runtime", "publicArtifacts"]
}
{
  "artifactCount": 118,
  "workspaces": [
    "<workspace-1>",
    "<workspace-2>",
    "<workspace-3>",
    "<workspace-4>"
  ]
}

---

{
  "event": "registerMemoryCapability",
  "pluginId": "memory-core",
  "keys": ["promptBuilder", "flushPlanResolver", "runtime", "publicArtifacts"],
  "hasPublicArtifacts": true,
  "stack": [
    "<installed-openclaw>/dist/memory-state-*.js",
    "<installed-openclaw>/dist/loader-*.js",
    "<plugin-runtime-deps>/dist/extensions/memory-core/index.js"
  ]
}

---

{
  "event": "listActiveMemoryPublicArtifacts:start",
  "hasCapability": false,
  "keys": [],
  "hasPublicArtifacts": false,
  "cfgHasAgents": true,
  "agentCount": 4,
  "stack": [
    "<plugin-runtime-deps>/dist/memory-state-*.js",
    "<plugin-runtime-deps>/dist/cli-*.js",
    "<plugin-runtime-deps>/dist/extensions/memory-wiki/index.js"
  ]
}
RAW_BUFFERClick to expand / collapse

Summary

memory-wiki bridge still imports 0 artifacts on OpenClaw 2026.4.27 even though PR #72615 is installed and memory-core does register publicArtifacts correctly.

The remaining bug appears to be a split singleton between the installed OpenClaw dist and the managed plugin-runtime-deps dist mirror:

  • memory-core registers publicArtifacts into the canonical installed dist/memory-state-*.js module.
  • memory-wiki bridge gateway method runs from the managed plugin-runtime-deps/openclaw-2026.4.27-*/dist/... mirror and calls listActiveMemoryPublicArtifacts() from the mirrored dist/memory-state-*.js module.
  • That mirrored module has a separate empty memoryPluginState, so wiki.bridge.import sees hasCapability=false and returns artifactCount: 0.

So #72615 fixed CLI → Gateway routing, but the Gateway bridge path can still read the wrong memory-state singleton.

Environment

  • OpenClaw: 2026.4.27 (cbc2ba0)
  • OS: Linux x64
  • Node: v22.22.2
  • Install: npm global
  • Runtime mirror involved: managed plugin-runtime-deps/openclaw-2026.4.27-*
  • Memory slot: plugins.slots.memory = "memory-core"
  • memory-wiki enabled; bridge migration was rolled back after the zero-artifact result for safety.

Relevant config shape

{
  "plugins": {
    "slots": { "memory": "memory-core" },
    "entries": {
      "memory-core": { "config": { "dreaming": { "enabled": true } } },
      "memory-wiki": {
        "enabled": true,
        "config": {
          "vaultMode": "bridge",
          "bridge": {
            "enabled": true,
            "readMemoryArtifacts": true,
            "indexDailyNotes": true,
            "indexMemoryRoot": true,
            "indexDreamReports": true,
            "followMemoryEvents": true
          }
        }
      }
    }
  }
}

Repro

  1. Configure memory-core as the selected memory slot.
  2. Configure memory-wiki bridge with readMemoryArtifacts=true.
  3. Ensure the configured workspace(s) contain MEMORY.md and memory/*.md files.
  4. Restart Gateway.
  5. Run:
openclaw gateway call wiki.bridge.import --json --timeout 60000

Actual result

{
  "importedCount": 0,
  "updatedCount": 0,
  "skippedCount": 0,
  "removedCount": 0,
  "artifactCount": 0,
  "workspaces": 0,
  "pagePaths": [],
  "indexesRefreshed": false,
  "indexUpdatedFiles": [],
  "indexRefreshReason": "no-import-changes"
}

openclaw wiki status --json in bridge mode also reports:

{
  "vaultMode": "bridge",
  "bridgePublicArtifactCount": 0,
  "warnings": [
    {
      "code": "bridge-artifacts-missing",
      "message": "Bridge mode is enabled but the active memory plugin is not exporting any public memory artifacts yet."
    }
  ]
}

Expected result

Bridge import should see the artifacts exported by memory-core.publicArtifacts.listArtifacts() and import source pages from MEMORY.md, daily notes, dream reports, etc.

In a standalone harness, invoking the bundled memory-core plugin registration captures publicArtifacts and returns non-zero artifacts across the configured workspaces.

Example harness shape:

{
  "registered": true,
  "keys": ["promptBuilder", "flushPlanResolver", "runtime", "publicArtifacts"]
}
{
  "artifactCount": 118,
  "workspaces": [
    "<workspace-1>",
    "<workspace-2>",
    "<workspace-3>",
    "<workspace-4>"
  ]
}

Diagnosis evidence

Temporary instrumentation of both copies of dist/memory-state-*.js showed the singleton split.

During Gateway startup, memory-core registered public artifacts into the canonical installed module:

{
  "event": "registerMemoryCapability",
  "pluginId": "memory-core",
  "keys": ["promptBuilder", "flushPlanResolver", "runtime", "publicArtifacts"],
  "hasPublicArtifacts": true,
  "stack": [
    "<installed-openclaw>/dist/memory-state-*.js",
    "<installed-openclaw>/dist/loader-*.js",
    "<plugin-runtime-deps>/dist/extensions/memory-core/index.js"
  ]
}

But when calling wiki.bridge.import, the bridge code used the mirrored module and found no capability:

{
  "event": "listActiveMemoryPublicArtifacts:start",
  "hasCapability": false,
  "keys": [],
  "hasPublicArtifacts": false,
  "cfgHasAgents": true,
  "agentCount": 4,
  "stack": [
    "<plugin-runtime-deps>/dist/memory-state-*.js",
    "<plugin-runtime-deps>/dist/cli-*.js",
    "<plugin-runtime-deps>/dist/extensions/memory-wiki/index.js"
  ]
}

That explains the 0 artifact result: memory-core and memory-wiki are not sharing the same memoryPluginState singleton.

Why this is different from the closed bridge issues

Related historical issues were closed as fixed/superseded by #72615. This install has #72615 behavior: bridge CLI routes through Gateway. The remaining failure is not CLI-local routing; it is the Gateway/plugin-runtime-deps mirror reading a different memory-state module instance.

Likely related closed/superseded issues:

  • #68828
  • #65722
  • #63157
  • #65092
  • #63092

Closest active adjacent issue found:

  • #74777 (plugin-runtime-deps memory runtime dependencies not retained/resolved), but this report is specifically about the memory capability singleton split causing bridge artifact export to be invisible.

Suggested fix directions

One of these should fix it:

  1. Make memory-wiki bridge obtain public memory artifacts through an injected host/runtime API rather than importing listActiveMemoryPublicArtifacts() from the mirrored dist bundle.
  2. Ensure singleton core modules such as memory-state-* are externalized/shared-resolved from the canonical Gateway runtime, not duplicated into plugin-runtime-deps.
  3. Pass a canonical listPublicArtifacts dependency into syncMemoryWikiImportedSources() / bridge Gateway methods from the host runtime.

A local workaround would be to make the mirrored memory-state-*.js re-export the canonical installed module, but that is fragile because plugin-runtime-deps is regenerated.

Safety note

Bridge mode was not left enabled after the zero-artifact result, to avoid an empty bridge sync/prune risk.

extent analysis

TL;DR

The most likely fix is to ensure the memory-wiki bridge obtains public memory artifacts through an injected host/runtime API or shares the same memoryPluginState singleton as memory-core.

Guidance

  • Investigate modifying the memory-wiki bridge to use an injected host/runtime API to access public memory artifacts, rather than relying on the mirrored dist bundle.
  • Consider externalizing/shared-resolving singleton core modules like memory-state-* from the canonical Gateway runtime to avoid duplication in plugin-runtime-deps.
  • Verify that the memory-core plugin is correctly registering public artifacts and that the memory-wiki bridge is using the correct memoryPluginState singleton.
  • Review the suggested fix directions provided in the issue, including injecting a canonical listPublicArtifacts dependency into bridge Gateway methods.

Example

No code example is provided as the issue requires a deeper understanding of the OpenClaw and plugin architecture.

Notes

The issue is specific to the OpenClaw 2026.4.27 version and the memory-wiki bridge. The suggested fix directions may require modifications to the plugin code or the OpenClaw runtime.

Recommendation

Apply a workaround by modifying the memory-wiki bridge to use an injected host/runtime API to access public memory artifacts, as this approach is less invasive and may be easier to implement than modifying the OpenClaw runtime or plugin architecture.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix memory-wiki bridge still returns 0 after #72615 due to split memory-state singleton in plugin-runtime-deps [1 pull requests, 2 comments, 3 participants]