Files
openclaw/extensions/memory-wiki
Peter Steinberger da4a656cdb improve: doctor migration checks no longer load every bundled plugin runtime (#120678)
* perf(plugins): declare doctor contract surfaces

* perf(doctor): slim migration import closures

* perf(plugins): narrow doctor declaration record surface and wire owner-test lane

Registry records carry only the doctorContract declaration instead of the whole
parsed manifest, and check:changed now selects the src/plugins-owned declaration
honesty and closure-guard tests for extension module/manifest changes so
cross-lane drift cannot pass PR classification.

* fix(doctor): keep control-plane dist imports require-safe

Keep doctor and channel control-plane chunks off exec-class dependencies, and enforce native require(esm) loading during postbuild.

* chore(plugin-sdk): regenerate API baseline

* chore(plugin-sdk): sync export ordering

* fix(plugins): satisfy doctor contract CI boundaries

* perf(doctor): make qqbot doctor closure dependency-light

qqbot was the last plugin above 5s in doctor state-migration enumeration
(~8s under tsx/jiti). The cost was not the state-key builder (already a
leaf): its doctor closure value-imported the runtime-doctor SDK barrel,
whose plugin-state-store/state-db re-exports pull kysely (~330 modules),
plus security-runtime for one fileExists (~200 modules), all resolved
per-module by jiti during enumeration.

Split the migration-define helpers and light re-exports into a new
private-local plugin-sdk/runtime-doctor-migrations subpath; runtime-doctor
re-exports it so its public surface is byte-identical (API baseline hash
unchanged). qqbot's doctor-contract and state-migrations now import only
the light subpath, swapping fileExists for the equivalent async
legacyStateFileExists already in the closure.

qqbot enumeration: ~8.0s/531 modules -> ~0.25s/18 modules.

* chore(plugin-sdk): drop private-local subpath from API baseline

runtime-doctor-migrations is private-local-only; the baseline tracks public
modules, and the earlier line was generated before the classification.

* fix(plugins): register runtime-doctor-migrations boundary paths

The private-local subpath list feeds the extension package boundary map;
the shared paths config and xai's derived overrides must carry the same
entry or the boundary contract test fails.
2026-08-08 13:29:18 -07:00
..
2026-06-04 21:33:54 -04:00

@openclaw/memory-wiki

Persistent wiki compiler and Obsidian-friendly knowledge vault for OpenClaw.

This plugin is separate from the active memory plugin. The active memory plugin still handles recall, promotion, and dreaming. memory-wiki compiles durable knowledge into a navigable markdown vault with deterministic indexes, provenance, structured claim/evidence metadata, and optional Obsidian CLI workflows.

When the active memory plugin exposes shared recall, agents can use memory_search with corpus=all to search durable memory and the compiled wiki in one pass, then fall back to wiki_search / wiki_get when wiki-specific ranking or provenance matters.

Modes

  • isolated: own vault, own sources, no dependency on memory-core
  • bridge: reads public memory artifacts and memory events through public seams
  • unsafe-local: explicit same-machine escape hatch for private local paths

Default mode is isolated.

vaultMode controls the wiki's inputs. vault.scope separately controls whether agents share one vault (global, the default) or resolve separate vaults (agent).

Config

Put config under plugins.entries.memory-wiki.config:

{
  vaultMode: "isolated",

  vault: {
    scope: "global", // or "agent"
    path: "~/.openclaw/wiki/main",
    renderMode: "obsidian", // or "native"
  },

  obsidian: {
    enabled: true,
    useOfficialCli: true,
    vaultName: "OpenClaw Wiki",
    openAfterWrites: false,
  },

  bridge: {
    enabled: false,
    readMemoryArtifacts: true,
    indexDreamReports: true,
    indexDailyNotes: true,
    indexMemoryRoot: true,
    followMemoryEvents: true,
  },

  unsafeLocal: {
    allowPrivateMemoryCoreAccess: false,
    paths: [],
  },

  ingest: {
    autoCompile: true,
    maxConcurrentJobs: 1,
    allowUrlIngest: true,
  },

  search: {
    backend: "shared", // or "local"
    corpus: "wiki", // or "memory" | "all"
  },

  context: {
    includeCompiledDigestPrompt: false, // opt in to append a compact compiled digest snapshot to memory prompt sections
  },

  render: {
    preserveHumanBlocks: true,
    createBacklinks: true, // writes managed ## Related blocks with sources, backlinks, and related pages
    createDashboards: true,
  },
}

Per-agent vaults

In agent scope, vault.path is a parent directory. OpenClaw appends the normalized agent id:

{
  vaultMode: "bridge",
  vault: {
    scope: "agent",
    path: "~/.openclaw/wiki",
  },
  bridge: {
    enabled: true,
    readMemoryArtifacts: true,
  },
  obsidian: {
    useOfficialCli: false,
  },
}

This resolves agents such as support and marketing to ~/.openclaw/wiki/support and ~/.openclaw/wiki/marketing. With no explicit path, the parent defaults to ~/.openclaw/wiki; the default main agent therefore keeps the existing ~/.openclaw/wiki/main path. In global scope, vault.path remains the exact shared vault path.

Wiki tools and compiled prompt/corpus supplements resolve the active runtime agent on each call. In bridge mode, an agent vault imports only public memory artifacts whose agentIds includes that agent; unowned and other-agent artifacts are skipped. CLI operations use the configured default agent unless the command passes --agent <agentId>; Gateway operations in multi-agent setups require agentId on the wiki.* RPC request.

Configuration validation rejects agent scope with either vaultMode: "unsafe-local" or obsidian.useOfficialCli: true. Obsidian-friendly Markdown rendering still works with agent vaults when official CLI actions are disabled.

Changing scope does not copy or split existing pages. Back up the vault and move or import content deliberately. Per-agent paths are a same-process knowledge boundary, not an operating-system security boundary; unsandboxed plugins and tools can still access another agent's host files.

Vault shape

The plugin initializes a vault like this:

<vault>/
  AGENTS.md
  WIKI.md
  index.md
  inbox.md
  entities/
  concepts/
  syntheses/
  sources/
  reports/
  _attachments/
  _views/
  .openclaw-wiki/

Generated content stays inside managed blocks. Human note blocks are preserved.

Key beliefs can live in structured claims frontmatter with per-claim evidence, confidence, and status. Compile also persists a machine-readable snapshot in OpenClaw plugin state so agent/runtime consumers do not have to scrape markdown pages.

When render.createBacklinks is enabled, compile adds deterministic ## Related blocks to pages. Those blocks list source pages, pages that reference the current page, and nearby pages that share the same source ids.

When render.createDashboards is enabled, compile also maintains report dashboards under reports/ for open questions, contradictions, low-confidence pages, and stale pages.

Unmanaged raw Markdown can live under sources/ without OpenClaw page frontmatter. Add <!-- openclaw:wiki:raw-source --> near the top of the page body to opt it out of wiki page metadata and freshness lint; generated or source-sync tracked imports still require their structured metadata.

CLI

openclaw wiki status
openclaw wiki doctor
openclaw wiki init
openclaw wiki ingest ./notes/alpha.md
openclaw wiki compile
openclaw wiki lint
openclaw wiki search "alpha"
openclaw wiki get entity.alpha --from 1 --lines 80

openclaw wiki apply synthesis "Alpha Summary" \
  --body "Short synthesis body" \
  --source-id source.alpha

openclaw wiki apply metadata entity.alpha \
  --source-id source.alpha \
  --status review \
  --question "Still active?"

openclaw wiki bridge import
openclaw wiki unsafe-local import

openclaw wiki obsidian status
openclaw wiki obsidian search "alpha"
openclaw wiki obsidian open syntheses/alpha-summary.md
openclaw wiki obsidian command workspace:quick-switcher
openclaw wiki obsidian daily

# Agent-scoped vault
openclaw wiki status --agent support
openclaw wiki search "refund policy" --agent support

Agent tools

  • wiki_status
  • wiki_lint
  • wiki_apply
  • wiki_search
  • wiki_get

The plugin also registers a non-exclusive memory corpus supplement, so shared memory_search / memory_get flows can reach the wiki when the active memory plugin supports corpus selection.

wiki_apply accepts structured claims payloads for synthesis and metadata updates, so the wiki can store claim-level evidence instead of only page-level prose.

When context.includeCompiledDigestPrompt is enabled, the memory prompt supplement also appends a compact snapshot from the lifecycle-owned in-memory cache. Legacy prompt assembly sees that automatically, and non-legacy context engines can pick it up when they explicitly consume memory prompt supplements via buildActiveMemoryPromptSection(...).

Gateway RPC

Read methods:

  • wiki.status
  • wiki.doctor
  • wiki.search
  • wiki.get
  • wiki.obsidian.status
  • wiki.obsidian.search

Write methods:

  • wiki.init
  • wiki.compile
  • wiki.ingest
  • wiki.lint
  • wiki.bridge.import
  • wiki.unsafeLocal.import
  • wiki.apply
  • wiki.obsidian.open
  • wiki.obsidian.command
  • wiki.obsidian.daily

For agent-scoped vaults, pass agentId to vault-backed RPC methods. Missing or unknown ids fail in multi-agent setups.

Notes

  • unsafe-local is intentionally experimental and non-portable.
  • Bridge mode reads the active memory plugin through public seams only.
  • Agent scope is incompatible with unsafe-local and official Obsidian CLI actions.
  • Wiki pages are compiled artifacts, not the ultimate source of truth. Keep provenance attached to raw sources, memory artifacts, and daily notes.
  • The compiled snapshot in shared SQLite plugin state is the stable machine-facing view of the wiki.
  • After editing or restoring vault files, compile again before expecting tools or prompts to use that source state. Lifecycle refresh rejects SQLite snapshots newer than a restored vault, and causal publication chaining rejects compilers started before the restore, without polling or watching files.
  • Rollback quarantine clears immediately for an in-process compile. After a separate compiler process publishes, refresh the plugin lifecycle so the daemon can validate that durable publication.
  • Pre-publication-epoch cache rows are rebuildable misses, not migrated state; the next compile replaces them.
  • Obsidian CLI support requires the official obsidian CLI to be installed and available on PATH.