@nowledge/openclaw-nowledge-mem 0.8.16 → 0.8.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,31 @@ All notable changes to the Nowledge Mem OpenClaw plugin will be documented in th
4
4
 
5
5
  ## Unreleased
6
6
 
7
+ ## [0.8.19] - 2026-04-21
8
+
9
+ ### Fixed
10
+
11
+ - `corpusSupplement` fallback now preserves the user's configured intent when host registration is unavailable. The plugin keeps its own recall path active instead of silently mutating config state.
12
+ - `nowledge_mem_status` now reports `corpusSupplement` as configured vs runtime-active, including fallback reason details when OpenClaw does not expose supplement registration in the current runtime.
13
+ - Context Engine recall now follows **runtime supplement activation** instead of static config. If `corpusSupplement` is configured but host registration fails, prompt-time recall no longer gets skipped.
14
+ - `nowledge_mem_status` no longer claims prompt-time fallback recall when `sessionContext=false`; status text now reflects the real runtime path.
15
+
16
+ ## [0.8.18] - 2026-04-20
17
+
18
+ ### Fixed
19
+
20
+ - OpenClaw installs no longer break when the installer writes `plugins.slots.contextEngine: "openclaw-nowledge-mem"` instead of the canonical manual id `nowledge-mem`. The plugin now registers a compatibility alias for that slot value, so users do not need to patch local config after install just to activate the Context Engine.
21
+
22
+ ### Changed
23
+
24
+ - `nowledge_mem_status` now explains when OpenClaw selected the plugin id as a context-engine compatibility alias, while still treating `nowledge-mem` as the canonical manual config value.
25
+
26
+ ## [0.8.17] - 2026-04-16
27
+
28
+ ### Fixed
29
+
30
+ - ClawHub installs no longer ship the plugin test suite inside the published code-plugin artifact. The package now uses an explicit `.clawhubignore`, so OpenClaw's security scanner no longer blocks install or update on harmless test-only `child_process` and `process.env + fetch` patterns.
31
+
7
32
  ## [0.8.16] - 2026-04-15
8
33
 
9
34
  ### Fixed
package/CLAUDE.md CHANGED
@@ -9,7 +9,7 @@ Continuation guide for `community/nowledge-mem-openclaw-plugin`.
9
9
  - Memory backend: `nmem` CLI (fallback: `uvx --from nmem-cli nmem`)
10
10
  - OpenClaw minimum: `2026.4.5` (`registerMemoryCorpusSupplement` for dreaming integration)
11
11
  - Architecture: **CLI-first via OpenClaw runtime** - all CLI execution goes through `api.runtime.system.runCommandWithTimeout`, not direct `child_process`
12
- - Context engine: registered via `api.registerContextEngine("nowledge-mem", factory)`. Activated when user sets `plugins.slots.contextEngine: "nowledge-mem"`. Falls back to hooks when CE is not active.
12
+ - Context engine: registered under the canonical id `nowledge-mem` plus the compatibility alias `openclaw-nowledge-mem`. Activated when OpenClaw sets either value in `plugins.slots.contextEngine`. Manual config should still prefer `nowledge-mem`. Falls back to hooks when CE is not active.
13
13
  - Remote mode: `~/.nowledge-mem/config.json` (shared) or OpenClaw dashboard. Legacy `openclaw.json` still honored.
14
14
  - Ambient space lane: prefer plugin config `space` or `spaceTemplate`. Use `NMEM_SPACE` only when OpenClaw is launched in one stable lane and there is no better profile-owned config surface. Legacy `NMEM_SPACE_ID` still works for older setups.
15
15
 
@@ -85,7 +85,7 @@ Enable when memory-core is the memory slot and you want cross-tool knowledge to
85
85
  The plugin is published as a dual-role OpenClaw plugin (`kind: ["memory", "context-engine"]`). These roles remain independent at runtime:
86
86
 
87
87
  - **Memory slot**: provides `memory_search` + `memory_get` and activates OpenClaw's "Memory Recall" system prompt section only when `plugins.slots.memory = "openclaw-nowledge-mem"`. In supplement mode with `memory-core`, these compatibility tools stay off so memory-core keeps owning that surface.
88
- - **Context engine**: activated when user sets `plugins.slots.contextEngine: "nowledge-mem"`. Replaces hooks with richer CE lifecycle.
88
+ - **Context engine**: activated when OpenClaw sets `plugins.slots.contextEngine` to `nowledge-mem` or the compatibility alias `openclaw-nowledge-mem`. Manual config should still use `nowledge-mem`. Replaces hooks with richer CE lifecycle.
89
89
 
90
90
  ### CE vs Hooks (dual-path design)
91
91
 
package/README.md CHANGED
@@ -17,7 +17,14 @@ This is not a flat note store. Nowledge Mem links related knowledge into a graph
17
17
  openclaw plugins install clawhub:@nowledge/openclaw-nowledge-mem
18
18
  ```
19
19
 
20
- OpenClaw's installer writes the install record, enables the plugin, and switches the `memory` slot to `openclaw-nowledge-mem`. Restart OpenClaw after install to load it.
20
+ OpenClaw's installer writes the install record, enables the plugin, and switches the `memory` slot to `openclaw-nowledge-mem`. On current OpenClaw builds, that same install flow may also set `plugins.slots.contextEngine` to `openclaw-nowledge-mem`. Plugin `0.8.18+` accepts that automatically as a compatibility alias, so you do not need to hand-edit the file after install. If you manage config manually, keep using the canonical context engine id `nowledge-mem`.
21
+
22
+ Restart OpenClaw after install to load it.
23
+
24
+ If OpenClaw previously blocked the ClawHub package with a warning about
25
+ `dangerous code patterns detected`, update to `0.8.17+`. That release removes
26
+ test-only files from the published ClawHub artifact, so the installer no longer
27
+ scans harmless development fixtures as if they were runtime plugin code.
21
28
 
22
29
  If you prefer the default resolver path, bare package names also work because OpenClaw resolves external plugins from ClawHub first and then falls back to npm:
23
30
 
@@ -560,6 +567,8 @@ If your config enables `plugins.slots.contextEngine: "nowledge-mem"`:
560
567
  - on `0.8.6+`, Context Engine capture stays active and hooks remain enabled as a safety net
561
568
  - on `0.8.5` and earlier, temporarily removing the `contextEngine` slot is a valid isolation step if thread sync stops while tools still work
562
569
 
570
+ If OpenClaw selected `plugins.slots.contextEngine: "openclaw-nowledge-mem"` during install, plugin `0.8.18+` treats that as the same engine. You only need to rewrite it to `"nowledge-mem"` if you want the config to use the canonical manual id.
571
+
563
572
  Remember: OpenClaw applies plugin setting changes after restart. If you turned `sessionDigest` off earlier but had not restarted yet, thread sync could appear to keep working until the next restart, then stop.
564
573
 
565
574
  What healthy OpenClaw thread sync looks like:
@@ -2,7 +2,7 @@
2
2
  "id": "openclaw-nowledge-mem",
3
3
  "name": "Nowledge Mem",
4
4
  "description": "Cross-tool knowledge graph memory for OpenClaw with Working Memory, graph search, and session distillation.",
5
- "version": "0.8.16",
5
+ "version": "0.8.19",
6
6
  "kind": ["memory", "context-engine"],
7
7
  "skills": [
8
8
  "skills/memory-guide"
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@nowledge/openclaw-nowledge-mem",
3
3
  "displayName": "Nowledge Mem for OpenClaw",
4
- "version": "0.8.16",
4
+ "version": "0.8.19",
5
5
  "type": "module",
6
6
  "description": "Nowledge Mem memory plugin for OpenClaw, local-first personal knowledge base",
7
7
  "author": {
@@ -25,7 +25,9 @@
25
25
  "openclaw.plugin.json"
26
26
  ],
27
27
  "openclaw": {
28
- "extensions": ["./src/index.js"],
28
+ "extensions": [
29
+ "./src/index.js"
30
+ ],
29
31
  "install": {
30
32
  "npmSpec": "@nowledge/openclaw-nowledge-mem"
31
33
  },
@@ -0,0 +1,15 @@
1
+ export const NOWLEDGE_MEM_CONTEXT_ENGINE_ID = "nowledge-mem";
2
+ export const NOWLEDGE_MEM_CONTEXT_ENGINE_COMPAT_ALIAS =
3
+ "openclaw-nowledge-mem";
4
+
5
+ export const NOWLEDGE_MEM_CONTEXT_ENGINE_IDS = [
6
+ NOWLEDGE_MEM_CONTEXT_ENGINE_ID,
7
+ NOWLEDGE_MEM_CONTEXT_ENGINE_COMPAT_ALIAS,
8
+ ];
9
+
10
+ export function isNowledgeMemContextEngineSlot(value) {
11
+ return (
12
+ typeof value === "string" &&
13
+ NOWLEDGE_MEM_CONTEXT_ENGINE_IDS.includes(value.trim())
14
+ );
15
+ }
@@ -3,7 +3,9 @@
3
3
  *
4
4
  * Registers alongside the memory slot (plugin kind includes both "memory" and
5
5
  * "context-engine"). When users activate
6
- * this CE via `plugins.slots.contextEngine: "nowledge-mem"`, it takes over
6
+ * this CE via `plugins.slots.contextEngine: "nowledge-mem"` (or the
7
+ * compatibility alias `openclaw-nowledge-mem` written by current installer
8
+ * builds), it takes over
7
9
  * prompt assembly and adds richer lifecycle behavior:
8
10
  *
9
11
  * assemble() — behavioral guidance + recalled memories via systemPromptAddition
@@ -164,9 +166,15 @@ function getSessionState(key) {
164
166
  * @param {import('./client.js').NowledgeMemClient} client
165
167
  * @param {object} cfg Parsed plugin config
166
168
  * @param {object} logger OpenClaw logger
169
+ * @param {object} runtime Runtime state helpers supplied by register()
167
170
  * @returns {() => object} Factory that creates the engine instance
168
171
  */
169
- export function createNowledgeMemContextEngineFactory(client, cfg, logger) {
172
+ export function createNowledgeMemContextEngineFactory(
173
+ client,
174
+ cfg,
175
+ logger,
176
+ runtime = {},
177
+ ) {
170
178
  return () => {
171
179
  ceState.active = true;
172
180
  logger.info("nowledge-mem: context engine activated");
@@ -240,8 +248,12 @@ export function createNowledgeMemContextEngineFactory(client, cfg, logger) {
240
248
  }
241
249
 
242
250
  // 3. Recalled memories (when sessionContext enabled)
243
- // Skipped when corpus supplement handles search-based recall via memory-core.
244
- if (cfg.sessionContext && !cfg.corpusSupplement) {
251
+ // Skip only when corpus supplement is actually active at runtime.
252
+ const corpusSupplementActive =
253
+ typeof runtime.isCorpusSupplementActive === "function"
254
+ ? runtime.isCorpusSupplementActive() === true
255
+ : cfg.corpusSupplement === true;
256
+ if (cfg.sessionContext && !corpusSupplementActive) {
245
257
  const query = buildAssembleSearchQuery(prompt, messages);
246
258
  if (query) {
247
259
  try {
@@ -177,13 +177,16 @@ export function buildRecalledKnowledgeBlock(
177
177
  * When the context engine is active, this hook is a no-op —
178
178
  * assemble() handles recall via systemPromptAddition.
179
179
  */
180
- export function buildRecallHandler(client, cfg, logger) {
180
+ export function buildRecallHandler(client, cfg, logger, runtime = {}) {
181
181
  const minScore = (cfg.recallMinScore ?? 0) / 100; // config is 0-100, API is 0-1
182
182
 
183
183
  // When corpus supplement is active, memory-core's recall pipeline searches
184
184
  // Nowledge Mem via the supplement. We still inject Working Memory (only we
185
185
  // know about WM), but skip our own search-based recall to avoid duplicates.
186
- const skipSearchRecall = cfg.corpusSupplement;
186
+ const skipSearchRecall =
187
+ typeof runtime.skipSearchRecall === "boolean"
188
+ ? runtime.skipSearchRecall
189
+ : cfg.corpusSupplement;
187
190
 
188
191
  return async (event) => {
189
192
  if (ceState.active) return;
package/src/index.js CHANGED
@@ -6,6 +6,10 @@ import {
6
6
  createRememberCommand,
7
7
  } from "./commands/slash.js";
8
8
  import { isDefaultApiUrl, parseConfig } from "./config.js";
9
+ import {
10
+ NOWLEDGE_MEM_CONTEXT_ENGINE_ID,
11
+ NOWLEDGE_MEM_CONTEXT_ENGINE_IDS,
12
+ } from "./context-engine-ids.js";
9
13
  import { createNowledgeMemContextEngineFactory } from "./context-engine.js";
10
14
  import { createNowledgeMemCorpusSupplement } from "./corpus-supplement.js";
11
15
  import { buildBehavioralHook } from "./hooks/behavioral.js";
@@ -76,18 +80,29 @@ export default {
76
80
  const pluginsAllow = api.config?.plugins?.allow;
77
81
  let contextEngineRegistered = false;
78
82
  let contextEngineRegistrationError = null;
83
+ let corpusSupplementActive = false;
84
+ let corpusSupplementRegistrationError = null;
79
85
 
80
86
  // --- Context Engine registration ---
81
- // When the user sets `plugins.slots.contextEngine: "nowledge-mem"`,
82
- // this CE takes over prompt assembly from the hooks below (assemble
83
- // replaces behavioral + recall prompt injection). Capture hooks remain
84
- // enabled as a reliability backstop because thread sync is idempotent.
85
- // When the CE slot points elsewhere, hooks continue working as before.
87
+ // When the user sets `plugins.slots.contextEngine: "nowledge-mem"` —
88
+ // or OpenClaw auto-selects the plugin id compatibility alias
89
+ // `openclaw-nowledge-mem` during install — this CE takes over prompt
90
+ // assembly from the hooks below (assemble replaces behavioral + recall
91
+ // prompt injection). Capture hooks remain enabled as a reliability
92
+ // backstop because thread sync is idempotent. When the CE slot points
93
+ // elsewhere, hooks continue working as before.
86
94
  try {
87
- api.registerContextEngine(
88
- "nowledge-mem",
89
- createNowledgeMemContextEngineFactory(client, cfg, logger),
95
+ const contextEngineFactory = createNowledgeMemContextEngineFactory(
96
+ client,
97
+ cfg,
98
+ logger,
99
+ {
100
+ isCorpusSupplementActive: () => corpusSupplementActive,
101
+ },
90
102
  );
103
+ for (const contextEngineId of NOWLEDGE_MEM_CONTEXT_ENGINE_IDS) {
104
+ api.registerContextEngine(contextEngineId, contextEngineFactory);
105
+ }
91
106
  contextEngineRegistered = true;
92
107
  } catch (err) {
93
108
  // OpenClaw < CE support — degrade gracefully to hooks-only mode
@@ -97,16 +112,6 @@ export default {
97
112
  );
98
113
  }
99
114
 
100
- api.registerTool(
101
- createStatusTool(client, logger, cfg, {
102
- memorySlot,
103
- contextEngineSlot,
104
- pluginsAllow,
105
- contextEngineRegistered,
106
- contextEngineRegistrationError,
107
- }),
108
- );
109
-
110
115
  // --- Corpus Supplement (when memory-core is the memory slot) ---
111
116
  // Makes Nowledge Mem's knowledge graph searchable through memory-core's
112
117
  // recall pipeline and dreaming promotion. Memories participate in
@@ -116,18 +121,32 @@ export default {
116
121
  api.registerMemoryCorpusSupplement(
117
122
  createNowledgeMemCorpusSupplement(client, cfg, logger),
118
123
  );
124
+ corpusSupplementActive = true;
119
125
  logger.info(
120
126
  "nowledge-mem: registered as MemoryCorpusSupplement for memory-core recall",
121
127
  );
122
128
  } catch (err) {
123
129
  // OpenClaw < corpus supplement support — fall back to normal recall
124
- cfg.corpusSupplement = false;
130
+ corpusSupplementRegistrationError = String(err);
125
131
  logger.info?.(
126
132
  `nowledge-mem: corpus supplement unavailable, falling back to normal recall (${err})`,
127
133
  );
128
134
  }
129
135
  }
130
136
 
137
+ api.registerTool(
138
+ createStatusTool(client, logger, cfg, {
139
+ memorySlot,
140
+ contextEngineSlot,
141
+ contextEngineIds: NOWLEDGE_MEM_CONTEXT_ENGINE_IDS,
142
+ pluginsAllow,
143
+ contextEngineRegistered,
144
+ contextEngineRegistrationError,
145
+ corpusSupplementActive,
146
+ corpusSupplementRegistrationError,
147
+ }),
148
+ );
149
+
131
150
  // --- Hooks ---
132
151
  // Behavioral + recall hooks defer to the active CE to avoid duplicate
133
152
  // prompt injection. Capture hooks remain enabled as a backstop because
@@ -140,7 +159,12 @@ export default {
140
159
 
141
160
  // Session context: inject Working Memory + recalled memories at prompt time.
142
161
  if (cfg.sessionContext) {
143
- api.on("before_prompt_build", buildRecallHandler(client, cfg, logger));
162
+ api.on(
163
+ "before_prompt_build",
164
+ buildRecallHandler(client, cfg, logger, {
165
+ skipSearchRecall: corpusSupplementActive,
166
+ }),
167
+ );
144
168
  }
145
169
 
146
170
  // Session digest: capture threads + LLM distillation at lifecycle events.
@@ -171,7 +195,7 @@ export default {
171
195
 
172
196
  const remoteMode = !isDefaultApiUrl(cfg.apiUrl);
173
197
  logger.info(
174
- `nowledge-mem: initialized (memorySlotSelected=${memorySlotSelected}, context=${cfg.sessionContext}, digest=${cfg.sessionDigest}, corpus=${cfg.corpusSupplement}, mode=${remoteMode ? `remote → ${cfg.apiUrl}` : "local"})`,
198
+ `nowledge-mem: initialized (memorySlotSelected=${memorySlotSelected}, context=${cfg.sessionContext}, digest=${cfg.sessionDigest}, corpusConfigured=${cfg.corpusSupplement}, corpusActive=${corpusSupplementActive}, mode=${remoteMode ? `remote → ${cfg.apiUrl}` : "local"}, contextEngineIds=${NOWLEDGE_MEM_CONTEXT_ENGINE_ID}|${api.id})`,
175
199
  );
176
200
  },
177
201
  };
@@ -6,6 +6,11 @@
6
6
  * Shows where each config value comes from (file, pluginConfig, env, default).
7
7
  */
8
8
  import { isDefaultApiUrl } from "../config.js";
9
+ import {
10
+ NOWLEDGE_MEM_CONTEXT_ENGINE_COMPAT_ALIAS,
11
+ NOWLEDGE_MEM_CONTEXT_ENGINE_ID,
12
+ isNowledgeMemContextEngineSlot,
13
+ } from "../context-engine-ids.js";
9
14
 
10
15
  export function createStatusTool(client, _logger, cfg, runtimeInfo = {}) {
11
16
  return {
@@ -62,35 +67,62 @@ export function createStatusTool(client, _logger, cfg, runtimeInfo = {}) {
62
67
  // 0b. Memory slot check — show current mode and options
63
68
  const memorySlot = runtimeInfo.memorySlot;
64
69
  const contextEngineSlot = runtimeInfo.contextEngineSlot;
65
- const contextEngineRegistered = runtimeInfo.contextEngineRegistered === true;
66
- const contextEngineRegistrationError =
67
- typeof runtimeInfo.contextEngineRegistrationError === "string" &&
68
- runtimeInfo.contextEngineRegistrationError.trim()
69
- ? runtimeInfo.contextEngineRegistrationError.trim()
70
- : null;
71
- details.memorySlot = memorySlot ?? "(unknown)";
72
- const ceSlot =
73
- typeof contextEngineSlot === "string" && contextEngineSlot.trim()
74
- ? contextEngineSlot.trim()
75
- : "legacy";
76
- details.contextEngineSlot = ceSlot;
77
- details.contextEngineRegistered = contextEngineRegistered;
70
+ const contextEngineRegistered =
71
+ runtimeInfo.contextEngineRegistered === true;
72
+ const contextEngineRegistrationError =
73
+ typeof runtimeInfo.contextEngineRegistrationError === "string" &&
74
+ runtimeInfo.contextEngineRegistrationError.trim()
75
+ ? runtimeInfo.contextEngineRegistrationError.trim()
76
+ : null;
77
+ const corpusSupplementConfigured = cfg.corpusSupplement === true;
78
+ const corpusSupplementActive =
79
+ runtimeInfo.corpusSupplementActive === true;
80
+ const corpusSupplementRegistrationError =
81
+ typeof runtimeInfo.corpusSupplementRegistrationError === "string" &&
82
+ runtimeInfo.corpusSupplementRegistrationError.trim()
83
+ ? runtimeInfo.corpusSupplementRegistrationError.trim()
84
+ : null;
85
+ details.memorySlot = memorySlot ?? "(unknown)";
86
+ details.corpusSupplementConfigured = corpusSupplementConfigured;
87
+ details.corpusSupplementActive = corpusSupplementActive;
88
+ if (corpusSupplementRegistrationError) {
89
+ details.corpusSupplementRegistrationError =
90
+ corpusSupplementRegistrationError;
91
+ }
92
+ const ceSlot =
93
+ typeof contextEngineSlot === "string" && contextEngineSlot.trim()
94
+ ? contextEngineSlot.trim()
95
+ : "legacy";
96
+ details.contextEngineSlot = ceSlot;
97
+ details.contextEngineRegistered = contextEngineRegistered;
78
98
  if (memorySlot && memorySlot !== "openclaw-nowledge-mem") {
79
- const corpusOn = cfg.corpusSupplement === true;
80
- if (corpusOn) {
81
- lines.push(
82
- `Memory slot: "${memorySlot}" + corpus supplement active`,
83
- );
99
+ if (corpusSupplementConfigured && corpusSupplementActive) {
100
+ lines.push(`Memory slot: "${memorySlot}" + corpus supplement active`);
84
101
  lines.push(
85
102
  " Nowledge Mem feeds into memory-core's recall and dreaming pipeline. All tools available.",
86
103
  );
87
- } else {
104
+ } else if (corpusSupplementConfigured && !corpusSupplementActive) {
105
+ lines.push(`ℹ Memory slot: "${memorySlot}"`);
88
106
  lines.push(
89
- `ℹ Memory slot: "${memorySlot}"`,
90
- );
91
- lines.push(
92
- " Two options:",
107
+ " corpusSupplement is configured, but host registration is unavailable in this runtime.",
93
108
  );
109
+ if (cfg.sessionContext) {
110
+ lines.push(
111
+ " Fallback active: Nowledge Mem still injects Working Memory and uses its own recall path.",
112
+ );
113
+ } else {
114
+ lines.push(
115
+ " Fallback: Nowledge Mem tools remain available. Enable sessionContext for prompt-time Working Memory and recall.",
116
+ );
117
+ }
118
+ if (corpusSupplementRegistrationError) {
119
+ lines.push(
120
+ ` Supplement registration detail: ${corpusSupplementRegistrationError}`,
121
+ );
122
+ }
123
+ } else {
124
+ lines.push(`ℹ Memory slot: "${memorySlot}"`);
125
+ lines.push(" Two options:");
94
126
  lines.push(
95
127
  ' - Full mode: set plugins.slots.memory to "openclaw-nowledge-mem" for the complete tool surface',
96
128
  );
@@ -104,23 +136,50 @@ export function createStatusTool(client, _logger, cfg, runtimeInfo = {}) {
104
136
  }
105
137
 
106
138
  // 0c. Capture routing — hooks vs context engine
107
- const ceActive = ceSlot === "nowledge-mem" && contextEngineRegistered;
139
+ const ceActive =
140
+ isNowledgeMemContextEngineSlot(ceSlot) && contextEngineRegistered;
108
141
  const captureMode = !cfg.sessionDigest
109
142
  ? "disabled"
110
- : ceActive ? "context-engine+hooks" : "hooks";
143
+ : ceActive
144
+ ? "context-engine+hooks"
145
+ : "hooks";
111
146
  details.captureMode = captureMode;
112
147
  if (ceActive) {
113
- lines.push("Context Engine slot: nowledge-mem (active)");
148
+ if (ceSlot === NOWLEDGE_MEM_CONTEXT_ENGINE_COMPAT_ALIAS) {
149
+ lines.push(
150
+ `Context Engine slot: ${NOWLEDGE_MEM_CONTEXT_ENGINE_COMPAT_ALIAS} (active via compatibility alias)`,
151
+ );
152
+ lines.push(
153
+ ` OpenClaw selected the plugin id for the context-engine slot. ${NOWLEDGE_MEM_CONTEXT_ENGINE_ID} remains the canonical manual setting.`,
154
+ );
155
+ } else {
156
+ lines.push(
157
+ `Context Engine slot: ${NOWLEDGE_MEM_CONTEXT_ENGINE_ID} (active)`,
158
+ );
159
+ }
114
160
  lines.push(
115
161
  " Thread capture runs through Context Engine afterTurn with hook fallback (agent_end, after_compaction, before_reset).",
116
162
  );
117
- } else if (ceSlot === "nowledge-mem") {
118
- lines.push("Context Engine slot: nowledge-mem (configured, fallback to hooks)");
163
+ } else if (isNowledgeMemContextEngineSlot(ceSlot)) {
164
+ if (ceSlot === NOWLEDGE_MEM_CONTEXT_ENGINE_COMPAT_ALIAS) {
165
+ lines.push(
166
+ `Context Engine slot: ${NOWLEDGE_MEM_CONTEXT_ENGINE_COMPAT_ALIAS} (compatibility alias, fallback to hooks)`,
167
+ );
168
+ lines.push(
169
+ ` OpenClaw selected the plugin id for the context-engine slot. ${NOWLEDGE_MEM_CONTEXT_ENGINE_ID} remains the canonical manual setting.`,
170
+ );
171
+ } else {
172
+ lines.push(
173
+ `Context Engine slot: ${NOWLEDGE_MEM_CONTEXT_ENGINE_ID} (configured, fallback to hooks)`,
174
+ );
175
+ }
119
176
  lines.push(
120
177
  " The slot points to Nowledge Mem, but Context Engine registration is not active in this runtime. Thread capture is using hooks only.",
121
178
  );
122
179
  if (contextEngineRegistrationError) {
123
- lines.push(` CE registration detail: ${contextEngineRegistrationError}`);
180
+ lines.push(
181
+ ` CE registration detail: ${contextEngineRegistrationError}`,
182
+ );
124
183
  }
125
184
  } else {
126
185
  lines.push(
@@ -242,6 +301,14 @@ export function createStatusTool(client, _logger, cfg, runtimeInfo = {}) {
242
301
  lines.push(
243
302
  ` corpusSupplement: ${cfg.corpusSupplement} (${sources.corpusSupplement || "?"})`,
244
303
  );
304
+ if (corpusSupplementConfigured) {
305
+ const fallbackText = cfg.sessionContext
306
+ ? "configured but unavailable (fallback to plugin recall)"
307
+ : "configured but unavailable (sessionContext disabled)";
308
+ lines.push(
309
+ ` corpusSupplement runtime: ${corpusSupplementActive ? "active" : fallbackText}`,
310
+ );
311
+ }
245
312
 
246
313
  details.config = {
247
314
  sessionContext: {
@@ -271,6 +338,7 @@ export function createStatusTool(client, _logger, cfg, runtimeInfo = {}) {
271
338
  corpusSupplement: {
272
339
  value: cfg.corpusSupplement,
273
340
  source: sources.corpusSupplement,
341
+ active: corpusSupplementActive,
274
342
  },
275
343
  apiUrl: { value: cfg.apiUrl || "(local)", source: sources.apiUrl },
276
344
  apiKey: {