cogmem 3.6.2 → 3.6.4

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
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.6.4
4
+
5
+ - Fixed OpenClaw/Hermes imports so empty imported episode boundaries are not batch-sealed into Dream work, and mature empty soft seals no longer abort `dream tick`.
6
+ - Added Dream queue cleanup for legacy empty episode jobs so one bad upgraded/imported episode is marked skipped and does not consume maintenance batch slots.
7
+ - Updated OpenClaw and Hermes auto-installed skills, runbooks, and README examples to prefer npm workspace-local installs, reserve `cogmem init` for interactive operator setup, and document the full import -> dream -> candidate governance -> `needs_confirmation` review flow.
8
+ - Standardized MCP guidance on `cogmem mcp` for new Hermes/OpenClaw host configs while keeping `cogmem-mcp` as a compatibility bin for existing configs.
9
+
10
+ ## 3.6.3
11
+
12
+ - Added a GitHub Release `published` workflow for npm Trusted Publishing with OIDC provenance, full tests, build, version-tag validation, and package dry-run verification before `npm publish`.
13
+ - Fixed `cogmem migrate --dry-run` so it opens SQLite read-only and plans legacy `_meta.schema_version` adoption without creating `_schema_migrations` or writing migration rows.
14
+ - Hardened `cogmem update` target resolution for npm global installs, one-line installer homes, local project dependencies, and source checkouts so `cogmem update --yes` does not silently install into an arbitrary current directory.
15
+ - Updated OpenClaw diagnostics and generated bridge behavior to propagate `rememberDrainTimeoutMs`, recover stale `.processing` queue files, and report pending/dead/lock/processing queue state.
16
+
3
17
  ## 3.6.2
4
18
 
5
19
  - Switched the public distribution channel to the npm registry while keeping GitHub as the source and review mirror.
package/CONTRIBUTING.md CHANGED
@@ -18,10 +18,10 @@ bun run typecheck
18
18
  bun test
19
19
  npm pack --dry-run --json
20
20
  npm publish --dry-run --access public
21
- npm publish --access public
21
+ npm publish --provenance --access public
22
22
  ```
23
23
 
24
- `cogmem` is distributed through the npm registry. Use `npm pack --dry-run --json` to verify package contents, then `npm publish --dry-run --access public` before `npm publish --access public`. Keep the GitHub branch or release synchronized for source review and for older GitHub-installed users migrating onto the npm-first updater.
24
+ `cogmem` is distributed through the npm registry. Use `npm pack --dry-run --json` to verify package contents. Normal publishing happens by creating a GitHub Release from the matching version tag; `.github/workflows/publish.yml` is intentionally triggered by the release `published` event, not by tag pushes. Use `npm publish --provenance --access public` only as an emergency manual fallback.
25
25
 
26
26
  ## API Discipline
27
27
 
package/README.md CHANGED
@@ -11,15 +11,24 @@ It is not a knowledge-base app, a note-taking app, a vector RAG wrapper, an Obsi
11
11
 
12
12
  ## Status
13
13
 
14
- Current version: `3.6.2`
14
+ Current version: `3.6.4`
15
15
 
16
16
  Distribution: npm registry. GitHub remains the source mirror and hosts this installer, but package install and upgrade resolve `cogmem` from npm by default.
17
17
 
18
+ Default workspace install:
19
+
20
+ ```bash
21
+ npm install cogmem@latest --save
22
+ ./node_modules/.bin/cogmem doctor
23
+ ```
24
+
25
+ One-line installer for machines that need Bun bootstrapping:
26
+
18
27
  ```bash
19
28
  curl -fsSL https://raw.githubusercontent.com/liuqin164/cogmem/main/install.sh | bash
20
29
  ```
21
30
 
22
- The installer:
31
+ The one-line installer:
23
32
 
24
33
  1. Ensures Bun is available.
25
34
  2. Installs `cogmem@latest` from the npm registry into `~/.cogmem/pkg`.
@@ -158,10 +167,11 @@ High-dimensional vectors grow quickly. Prefer `raw_then_dream` or `selective_com
158
167
 
159
168
  ## Quick Start
160
169
 
161
- Install globally:
170
+ Install into an agent workspace with npm:
162
171
 
163
172
  ```bash
164
- curl -fsSL https://raw.githubusercontent.com/liuqin164/cogmem/main/install.sh | bash
173
+ npm install cogmem@latest --save
174
+ ./node_modules/.bin/cogmem doctor
165
175
  ```
166
176
 
167
177
  Or install into an existing Bun workspace:
@@ -178,6 +188,26 @@ npm install cogmem@latest
178
188
  ./node_modules/.bin/cogmem init
179
189
  ```
180
190
 
191
+ Or install globally with npm when Bun is already on PATH:
192
+
193
+ ```bash
194
+ npm install -g cogmem@latest
195
+ cogmem init
196
+ ```
197
+
198
+ Or use the one-line installer for machines that do not already have Bun:
199
+
200
+ ```bash
201
+ curl -fsSL https://raw.githubusercontent.com/liuqin164/cogmem/main/install.sh | bash
202
+ ```
203
+
204
+ For agent-run installs, skip the interactive wizard and connect the host explicitly:
205
+
206
+ ```bash
207
+ COGMEM_SKIP_INIT=1 curl -fsSL https://raw.githubusercontent.com/liuqin164/cogmem/main/install.sh | bash
208
+ cogmem doctor
209
+ ```
210
+
181
211
  Validate configuration:
182
212
 
183
213
  ```bash
@@ -190,7 +220,7 @@ Upgrade from npm and migrate an existing database:
190
220
  cogmem update --yes
191
221
  ```
192
222
 
193
- `cogmem update --yes` installs `cogmem@latest` from npm, then runs the newly installed `cogmem migrate --yes --backup --config <resolved-config>`. If OpenClaw is configured, the updater also runs the newly installed plugin-only repair command so stale `index.js` and `bridge.mjs` files are refreshed before you restart the agent. To inspect changes without writing:
223
+ `cogmem update --yes` installs `cogmem@latest` from npm, then runs the newly installed `cogmem migrate --yes --backup --config <resolved-config>`. It updates npm-global installs with `npm install -g`, the one-line installer home under `~/.cogmem/pkg`, or the current workspace dependency when Cogmem is a project dependency. If OpenClaw is configured, the updater also runs the newly installed plugin-only repair command so stale `index.js` and `bridge.mjs` files are refreshed before you restart the agent. To inspect changes without writing:
194
224
 
195
225
  ```bash
196
226
  cogmem update --dry-run --json
@@ -199,7 +229,7 @@ cogmem migrate --dry-run --json
199
229
 
200
230
  For a manual migration, run `cogmem migrate --yes --backup`. The migration runner adopts the existing `_meta.schema_version`, applies only later idempotent migrations, preserves Raw Ledger rows, and creates a timestamped, transaction-consistent standalone database backup before changing an on-disk database. The backup includes committed SQLite WAL pages instead of copying only the main database file.
201
231
 
202
- Upgrade a 3.5.2 database, a 3.6.0 database, or a pre-release schema-25 test database into the 3.6.2 schema set with one command:
232
+ Upgrade a 3.5.2 database, a 3.6.0 database, or a pre-release schema-25 test database into the 3.6.4 schema set with one command:
203
233
 
204
234
  ```bash
205
235
  cogmem migrate --yes --backup --json
@@ -230,9 +260,14 @@ cogmem repair project-scope --from "" --to openclaw --apply --json
230
260
  Inspect and conditionally process sealed conversation episodes:
231
261
 
232
262
  ```bash
263
+ cogmem memory status --project my-agent --json
233
264
  cogmem episode status --project my-agent --json
234
- cogmem dream tick --project my-agent --mode auto --json
265
+ cogmem dream status --project my-agent --json
266
+ cogmem dream tick --project my-agent --mode auto --max-episodes 20 --json
267
+ cogmem memory candidates --project my-agent --status candidate --json
235
268
  cogmem memory govern --project my-agent --json
269
+ cogmem memory candidates --project my-agent --status needs_confirmation --json
270
+ cogmem memory review --project my-agent --id <candidate-id> --action approve --actor <operator> --reason "confirmed" --confirmation-event <user-event-id> --json
236
271
  ```
237
272
 
238
273
  For a host timer, call `dream tick`; the timer only wakes the scheduler. An empty backlog performs no Dream work:
@@ -241,9 +276,9 @@ For a host timer, call `dream tick`; the timer only wakes the scheduler. An empt
241
276
  cogmem dream tick --project my-agent --mode auto --max-episodes 10 --json
242
277
  ```
243
278
 
244
- Raw events are always written first. `KernelAgentMemoryBackend` and OpenClaw plugin 0.6.2 assemble live turns automatically. The foreground hook uses deterministic rules and previous assistant/user context; background import and repair paths may use the advisory hybrid classifier. Advisory output is allow-listed and cannot directly mutate durable memory. Unknown turns now fail closed as ambiguous. Continuation requires explicit continuation language or project/topic/entity/semantic overlap; Cogmem does not route domains with an expanding hard-coded keyword dictionary.
279
+ Raw events are always written first. `KernelAgentMemoryBackend` and OpenClaw plugin 0.6.3 assemble live turns automatically. The foreground hook uses deterministic rules and previous assistant/user context; background import and repair paths may use the advisory hybrid classifier. Advisory output is allow-listed and cannot directly mutate durable memory. Unknown turns now fail closed as ambiguous. Continuation requires explicit continuation language or project/topic/entity/semantic overlap; Cogmem does not route domains with an expanding hard-coded keyword dictionary.
245
280
 
246
- Hookless MCP agents can call `cogmem_episode_append` or bounded `cogmem_episode_import`. Existing OpenClaw/Hermes import commands use stable content identities and the same episode schema. Low-confidence imported groups soft-seal for review unless an operator explicitly forces sealing. Episode semantic summaries and closure receipts are control hints, never durable evidence; every Dream candidate must cite a non-empty subset of the episode's raw event IDs and still pass CPU governance.
281
+ Hookless MCP agents can call `cogmem_episode_append` or bounded `cogmem_episode_import`. Existing OpenClaw/Hermes import commands use stable content identities and the same episode schema. Low-confidence imported groups soft-seal for review unless an operator explicitly forces sealing. Cogmem 3.6.4 skips import batch sealing for empty episode boundaries and skips legacy empty Dream jobs so one bad imported episode cannot block the queue. Episode semantic summaries and closure receipts are control hints, never durable evidence; every Dream candidate must cite a non-empty subset of the episode's raw event IDs and still pass CPU governance.
247
282
 
248
283
  User-shaped topic state is project-scoped. Explicit user operations become active and auditable; model-proposed topics, aliases, and relations remain candidates. Use MCP `cogmem_topic_list` to inspect nodes, `cogmem_topic_operate` to create, rename, alias, move, merge, split, or relate topics, and `cogmem_topic_rollback` to reverse an audited operation. Alias collisions fail closed as `needs_review`; applications can also call `TopicGovernance.rollback()` through the public API.
249
284
 
@@ -337,7 +372,7 @@ cogmem strategy plan --project hermes --query "我当时的原话是什么?" -
337
372
  cogmem strategy outcomes --project hermes --json
338
373
  ```
339
374
 
340
- OpenClaw plugin 0.6.2 skips Cogmem entirely for greetings, uses only session state/turn bridge for short continuations, and applies Strategy Cortex before full recall. Navigation turns use one bridge/kernel lifecycle for Atlas exploration, evidence-bearing node/timeline drill-down, and recall. The bounded volatile `<COGMEM_MEMORY_ATLAS>` block includes evidence event IDs and drill-down commands; OpenClaw does not need MCP for this path.
375
+ OpenClaw plugin 0.6.3 skips Cogmem entirely for greetings, uses only session state/turn bridge for short continuations, and applies Strategy Cortex before full recall. Navigation turns use one bridge/kernel lifecycle for Atlas exploration, evidence-bearing node/timeline drill-down, and recall. The bounded volatile `<COGMEM_MEMORY_ATLAS>` block includes evidence event IDs and drill-down commands; OpenClaw does not need MCP for this path.
341
376
 
342
377
  `ProspectiveMemoryService` stores future intentions, commitments, reminders, open loops, and plans as candidates only. A candidate is not actionable until an explicit user event confirms it. Rejected candidates stay suppressed unless genuinely new evidence creates a new version. The service and `cogmem prospective` CLI manage state only; they expose no task or tool execution capability.
343
378
 
@@ -475,8 +510,8 @@ Hermes integration is MCP-based in this release. cogmem does not claim to be a n
475
510
  Install the skill and patch Hermes MCP config:
476
511
 
477
512
  ```bash
478
- cogmem init --agent hermes
479
- cogmem connect hermes --workspace /path/to/hermes/workspace --auto --force
513
+ npm install cogmem@latest --save
514
+ ./node_modules/.bin/cogmem connect hermes --workspace /path/to/hermes/workspace --auto --force
480
515
  ```
481
516
 
482
517
  This installs the agent-facing skill bundle at:
@@ -494,6 +529,8 @@ With `--auto`, it adds or updates a `cogmem` MCP server entry in:
494
529
  ~/.hermes/config.yaml
495
530
  ```
496
531
 
532
+ New Hermes configs start the server with `cogmem mcp`. Existing `cogmem-mcp` entries remain supported and are updated in place for tool allow-list changes.
533
+
497
534
  Then reload MCP inside Hermes:
498
535
 
499
536
  ```text
@@ -681,7 +718,7 @@ For Hermes after an update, reload the MCP server or restart the agent host. If
681
718
  cogmem connect hermes --workspace /path/to/hermes/workspace --auto --force
682
719
  ```
683
720
 
684
- This also updates existing Hermes `cogmem-mcp` blocks with missing strategy, episode, Dream, memory-map, maintenance, and prospective tools.
721
+ This also updates existing Hermes MCP blocks with missing strategy, episode, Dream, memory-map, maintenance, and prospective tools. New configs use `cogmem mcp`; `cogmem-mcp` remains a compatibility bin.
685
722
 
686
723
  ## Documentation
687
724
 
@@ -703,6 +740,7 @@ Installed OpenClaw and Hermes skills include their own `references/operations.md
703
740
  cogmem init
704
741
  cogmem doctor
705
742
  cogmem connect openclaw|hermes
743
+ cogmem mcp
706
744
  cogmem update
707
745
  cogmem memory recall|search|show|dream|govern|candidates|review|status|map|tick|bind
708
746
  cogmem memory graph|graph-search|graph-explore|graph-node|graph-neighbors|graph-path|graph-timeline
@@ -732,7 +770,15 @@ npm pack --dry-run --json
732
770
  npm publish --dry-run --access public
733
771
  ```
734
772
 
735
- Publish with `npm publish --access public` after the dry run and full tests pass. Keep GitHub branches/releases in sync so old GitHub-installed 3.6.1 users have a discoverable bridge to the npm-first 3.6.2 updater.
773
+ Create a GitHub Release from the matching version tag, for example `v3.6.4`. The `.github/workflows/publish.yml` workflow publishes to npm only when the release is published, not when a tag is pushed. The npm Trusted Publisher entry must match repository `liuqin164/cogmem`, workflow file `publish.yml`, and environment `npm publish`.
774
+
775
+ Publish manually only for emergency fallback:
776
+
777
+ ```bash
778
+ npm publish --provenance --access public
779
+ ```
780
+
781
+ Keep GitHub branches/releases in sync so old GitHub-installed users have a discoverable bridge to the npm-first updater.
736
782
 
737
783
  ## Security and Privacy
738
784
 
@@ -1,11 +1,11 @@
1
- # cogmem 3.6.2 Release Checklist
1
+ # cogmem 3.6.4 Release Checklist
2
2
 
3
3
  This release is distributed through the npm registry. GitHub remains the source and review mirror.
4
4
 
5
5
  ## Required Metadata
6
6
 
7
7
  - `package.json` name is `cogmem`.
8
- - `package.json` version is `3.6.2`.
8
+ - `package.json` version is `3.6.4`.
9
9
  - `package.json` has `publishConfig.access = public`.
10
10
  - Public export `.` points to `dist/public.js` and `dist/public.d.ts`.
11
11
  - Internal subpath `./internal` exists only as an explicit advanced subpath.
@@ -19,12 +19,13 @@ This release is distributed through the npm registry. GitHub remains the source
19
19
  - `cogmem doctor`
20
20
  - `cogmem connect`
21
21
  - `cogmem update`
22
+ - `cogmem mcp`
22
23
  - `cogmem openclaw diagnose`
23
24
  - `cogmem-compact`
24
25
  - `cogmem memory`
25
26
  - `cogmem repair`
26
27
  - `cogmem explain-recall`
27
- - `cogmem-mcp`
28
+ - `cogmem-mcp` compatibility bin for existing host configs
28
29
  - `cogmem import-openclaw`
29
30
  - `cogmem import-hermes`
30
31
  - `cogmem normalize-transcript`
@@ -43,6 +44,8 @@ MCP `tools/list` includes strategy, episode append/import/status/seal/repair, to
43
44
  ## Required Documentation
44
45
 
45
46
  - README explains the vision, architecture, limits, and one-line install command.
47
+ - README and skills document npm as the default install path: workspace-local `npm install cogmem@latest --save` for OpenClaw/Hermes projects, global npm only when the operator wants one shared CLI, and the one-line installer as compatibility.
48
+ - README and skills state that `cogmem init` is an interactive operator wizard and must not be scripted by an unattended agent; agents should use resolved `cogmem` commands, `cogmem doctor`, and `cogmem connect <agent>`.
46
49
  - README says this is a single-agent memory kernel, not an agent team shared brain.
47
50
  - README distinguishes embedding models from Dream Curator memory-model LLMs.
48
51
  - README and integration docs explain labeled `sourceContext`, strict before/after window metadata, `charRange` / `sourceRange`, and OpenClaw `sourceWindow` / `sourceTruncation` injection.
@@ -56,6 +59,9 @@ MCP `tools/list` includes strategy, episode append/import/status/seal/repair, to
56
59
  - README and skills explain that Prospective Memory is confirmed-only state with no task execution capability, and how to use BrainEval as a release gate.
57
60
  - README and skills explain Strategy Cortex templates, no-instruction-authority lifecycle, one-retry replanning, strategy-conditioned retrieval, offline-only rollout comparison, and read-only MemoryUseJudge telemetry.
58
61
  - README and skills explain Raw Ledger-first episode assembly, soft/hard sealing, explicit conditional Dream ticks, raw-event evidence grounding, repair/retry, and hookless Hermes MCP/import usage.
62
+ - README and skills give the full post-import maintenance sequence: status, episode status, Dream status, bounded Dream tick, candidate listing, govern candidate, needs-confirmation listing, explicit review, and recall verification.
63
+ - README and skills explain that 3.6.4 skips empty imported episode boundaries and legacy empty Dream jobs instead of letting them abort `dream tick`.
64
+ - README and skills document `cogmem mcp` as the preferred MCP server command for new configs while preserving `cogmem-mcp` as a compatibility bin.
59
65
  - README and skills explain CPU foreground versus hybrid background classification, contextual short replies, registry-aware topic boundaries, safe reopen, semantic-summary non-evidence status, per-job Dream modes/failures, stable import identity, and schema migration 24.
60
66
  - README and skills explain user-shaped topic operations, user-explicit versus model-candidate authority, alias collision review, operation rollback, and project isolation.
61
67
  - README, `MEMORY_ATLAS.md`, and skills distinguish the system anatomy map from the content Atlas; explain graph overview/search/explore/node/neighbors/path/timeline, generic multi-facet cold-memory resurrection, activation visibility, source drill-down, and project isolation.
@@ -85,8 +91,10 @@ npm publish --dry-run --access public
85
91
 
86
92
  The pack dry-run must include built public API files, CLI files, examples, docs, and `install.sh`. It must not include local databases or machine-specific files.
87
93
 
88
- After verification, publish with:
94
+ After verification, create a GitHub Release from the matching version tag, for example `v3.6.4`. The release workflow publishes through npm Trusted Publishing when the release is published. It must not publish on tag push alone.
95
+
96
+ Emergency manual fallback:
89
97
 
90
98
  ```bash
91
- npm publish --access public
99
+ npm publish --provenance --access public
92
100
  ```
@@ -92,19 +92,18 @@ function defaultSkillPath(agent, workspaceRoot) {
92
92
  function nextCommands(agent) {
93
93
  if (agent === 'openclaw') {
94
94
  return [
95
- './node_modules/.bin/cogmem-init --agent openclaw --scope project',
96
- './node_modules/.bin/cogmem-doctor',
97
- './node_modules/.bin/cogmem-import-openclaw --workspace . --project openclaw --dry-run',
98
- './node_modules/.bin/cogmem-import-openclaw --workspace . --project openclaw',
99
- './node_modules/.bin/cogmem-connect openclaw --workspace . --auto --force',
95
+ './node_modules/.bin/cogmem doctor',
96
+ './node_modules/.bin/cogmem openclaw diagnose --workspace . --json',
97
+ './node_modules/.bin/cogmem import-openclaw --workspace . --project openclaw --dry-run',
98
+ './node_modules/.bin/cogmem import-openclaw --workspace . --project openclaw',
99
+ './node_modules/.bin/cogmem memory status --project openclaw --json',
100
100
  ];
101
101
  }
102
102
  return [
103
- './node_modules/.bin/cogmem-init --agent hermes',
104
- './node_modules/.bin/cogmem-doctor',
105
- './node_modules/.bin/cogmem-connect hermes --workspace . --auto --force',
106
- './node_modules/.bin/cogmem-import-hermes --workspace . --project hermes --dry-run',
107
- './node_modules/.bin/cogmem-import-hermes --workspace . --project hermes',
103
+ './node_modules/.bin/cogmem doctor',
104
+ './node_modules/.bin/cogmem import-hermes --workspace . --project hermes --dry-run',
105
+ './node_modules/.bin/cogmem import-hermes --workspace . --project hermes',
106
+ './node_modules/.bin/cogmem memory status --project hermes --json',
108
107
  ];
109
108
  }
110
109
  function usage() {
@@ -138,33 +137,45 @@ function hostConfigSnippet(agent, workspaceRoot, auto) {
138
137
  '// Add host config only after installing a real OpenClaw plugin wrapper with a valid manifest/schema.',
139
138
  ].join('\n');
140
139
  }
141
- const mcpBin = resolveCogmemMcpCommand(workspaceRoot);
140
+ const mcpServer = resolveCogmemMcpServer(workspaceRoot);
142
141
  return [
143
142
  'mcp_servers:',
144
143
  ' cogmem:',
145
- ` command: "${mcpBin}"`,
146
- ' args: []',
144
+ ` command: "${mcpServer.command}"`,
145
+ ` args: ${JSON.stringify(mcpServer.args)}`,
147
146
  ' enabled: true',
148
147
  ' tools:',
149
148
  ' include:',
150
149
  ...HERMES_COGMEM_TOOLS.map((tool) => ` - ${tool}`),
151
150
  ].join('\n');
152
151
  }
153
- function resolveCogmemMcpCommand(workspaceRoot) {
152
+ function resolveCogmemMcpServer(workspaceRoot) {
154
153
  if (process.env.COGMEM_MCP_BIN)
155
- return process.env.COGMEM_MCP_BIN;
156
- const workspaceBin = join(workspaceRoot, 'node_modules', '.bin', 'cogmem-mcp');
157
- if (existsSync(workspaceBin))
158
- return workspaceBin;
154
+ return { command: process.env.COGMEM_MCP_BIN, args: [] };
155
+ if (process.env.COGMEM_BIN)
156
+ return { command: process.env.COGMEM_BIN, args: ['mcp'] };
157
+ const workspaceCli = join(workspaceRoot, 'node_modules', '.bin', 'cogmem');
158
+ if (existsSync(workspaceCli))
159
+ return { command: workspaceCli, args: ['mcp'] };
159
160
  const pathValue = process.env.PATH || '';
161
+ for (const segment of pathValue.split(':')) {
162
+ if (!segment)
163
+ continue;
164
+ const candidate = join(segment, 'cogmem');
165
+ if (existsSync(candidate))
166
+ return { command: candidate, args: ['mcp'] };
167
+ }
168
+ const workspaceMcp = join(workspaceRoot, 'node_modules', '.bin', 'cogmem-mcp');
169
+ if (existsSync(workspaceMcp))
170
+ return { command: workspaceMcp, args: [] };
160
171
  for (const segment of pathValue.split(':')) {
161
172
  if (!segment)
162
173
  continue;
163
174
  const candidate = join(segment, 'cogmem-mcp');
164
175
  if (existsSync(candidate))
165
- return candidate;
176
+ return { command: candidate, args: [] };
166
177
  }
167
- return 'cogmem-mcp';
178
+ return { command: 'cogmem', args: ['mcp'] };
168
179
  }
169
180
  function installSkill(args) {
170
181
  if (!args.agent)
@@ -237,9 +248,9 @@ function defaultHermesConfigPath(env = process.env) {
237
248
  }
238
249
  function installHermesMcpConfig(input) {
239
250
  const configPath = resolve(input.configPath || defaultHermesConfigPath());
240
- const serverCommand = resolveCogmemMcpCommand(resolve(input.workspaceRoot));
251
+ const server = resolveCogmemMcpServer(resolve(input.workspaceRoot));
241
252
  const original = existsSync(configPath) ? readFileSync(configPath, 'utf8') : '';
242
- const patched = patchHermesMcpConfig(original, serverCommand);
253
+ const patched = patchHermesMcpConfig(original, server.command, server.args);
243
254
  const changed = patched !== original;
244
255
  let backupPath;
245
256
  if (!input.dryRun && (changed || input.force)) {
@@ -253,21 +264,22 @@ function installHermesMcpConfig(input) {
253
264
  return {
254
265
  enabled: true,
255
266
  configPath,
256
- serverCommand,
267
+ serverCommand: server.command,
268
+ serverArgs: server.args,
257
269
  dryRun: input.dryRun,
258
270
  configUpdated: changed || input.force,
259
271
  backupPath,
260
272
  };
261
273
  }
262
- function patchHermesMcpConfig(original, serverCommand) {
263
- if (/^\s+cogmem\s*:/m.test(original) && original.includes('cogmem-mcp')) {
274
+ function patchHermesMcpConfig(original, serverCommand, serverArgs) {
275
+ if (/^\s+cogmem\s*:/m.test(original)) {
264
276
  return patchExistingHermesCogmemConfig(original);
265
277
  }
266
278
  const lines = original.replace(/\r\n/g, '\n').split('\n');
267
279
  const serverBlock = [
268
280
  ' cogmem:',
269
281
  ` command: "${serverCommand}"`,
270
- ' args: []',
282
+ ` args: ${JSON.stringify(serverArgs)}`,
271
283
  ' enabled: true',
272
284
  ' tools:',
273
285
  ' include:',
@@ -366,7 +378,7 @@ function printHuman(result) {
366
378
  console.log('');
367
379
  console.log('Hermes MCP integration:');
368
380
  console.log(` config: ${result.hermesMcp.configPath}`);
369
- console.log(` command: ${result.hermesMcp.serverCommand}`);
381
+ console.log(` command: ${result.hermesMcp.serverCommand} ${result.hermesMcp.serverArgs.join(' ')}`.trimEnd());
370
382
  if (result.hermesMcp.backupPath)
371
383
  console.log(` backup: ${result.hermesMcp.backupPath}`);
372
384
  console.log(' reload: /reload-mcp');
@@ -22,6 +22,7 @@ export interface AgentImportResult {
22
22
  recordsIngested: number;
23
23
  skippedRecords: number;
24
24
  rawRecordsAnchored?: number;
25
+ emptyEpisodesSkipped?: number;
25
26
  reindexRaw?: boolean;
26
27
  processedSourceIds: string[];
27
28
  diagnostics: SourceAdapterDiagnostic[];
@@ -152,6 +152,7 @@ function previewSources(input) {
152
152
  recordsIngested: 0,
153
153
  skippedRecords: 0,
154
154
  rawRecordsAnchored: 0,
155
+ emptyEpisodesSkipped: 0,
155
156
  reindexRaw: false,
156
157
  processedSourceIds: [],
157
158
  diagnostics,
@@ -161,6 +162,7 @@ function previewSources(input) {
161
162
  async function importSources(input) {
162
163
  const opened = openKernel(input.args, input.workspaceRoot);
163
164
  const importedEpisodeIds = new Set();
165
+ let emptyEpisodesSkipped = 0;
164
166
  const processor = new InstalledBatchProcessor({
165
167
  cursorStore: opened.kernel.cursorStore,
166
168
  ingestBatch: async (items) => {
@@ -190,7 +192,7 @@ async function importSources(input) {
190
192
  for (const episodeId of importedEpisodeIds) {
191
193
  const episode = opened.kernel.getEpisode(episodeId);
192
194
  if (episode?.status !== 'sealed') {
193
- opened.kernel.sealImportedEpisode(episodeId, { reason: `${input.agent}_import_batch_boundary` });
195
+ emptyEpisodesSkipped += sealImportedEpisodeIfReady(opened.kernel, episodeId, `${input.agent}_import_batch_boundary`) ? 0 : 1;
194
196
  }
195
197
  }
196
198
  return {
@@ -207,6 +209,7 @@ async function importSources(input) {
207
209
  recordsIngested: summary.recordsIngested,
208
210
  skippedRecords: summary.skippedRecords,
209
211
  rawRecordsAnchored: summary.recordsIngested,
212
+ emptyEpisodesSkipped,
210
213
  reindexRaw: false,
211
214
  processedSourceIds: summary.processedSourceIds,
212
215
  diagnostics: summary.adapterDiagnostics,
@@ -238,6 +241,7 @@ async function reindexRawSources(input) {
238
241
  let rawRecordsAnchored = 0;
239
242
  let skippedRecords = 0;
240
243
  const importedEpisodeIds = new Set();
244
+ let emptyEpisodesSkipped = 0;
241
245
  try {
242
246
  for (const source of input.sources) {
243
247
  const adapter = adapters.get(source.adapterKind);
@@ -279,7 +283,7 @@ async function reindexRawSources(input) {
279
283
  for (const episodeId of importedEpisodeIds) {
280
284
  const episode = opened.kernel.getEpisode(episodeId);
281
285
  if (episode?.status !== 'sealed') {
282
- opened.kernel.sealImportedEpisode(episodeId, { reason: `${input.agent}_reindex_batch_boundary` });
286
+ emptyEpisodesSkipped += sealImportedEpisodeIfReady(opened.kernel, episodeId, `${input.agent}_reindex_batch_boundary`) ? 0 : 1;
283
287
  }
284
288
  }
285
289
  return {
@@ -297,6 +301,7 @@ async function reindexRawSources(input) {
297
301
  recordsIngested: rawRecordsAnchored,
298
302
  skippedRecords,
299
303
  rawRecordsAnchored,
304
+ emptyEpisodesSkipped,
300
305
  processedSourceIds,
301
306
  diagnostics,
302
307
  sourceResults,
@@ -307,6 +312,12 @@ async function reindexRawSources(input) {
307
312
  opened.kernel.close();
308
313
  }
309
314
  }
315
+ function sealImportedEpisodeIfReady(kernel, episodeId, reason) {
316
+ if (kernel.listEpisodeEventLinks(episodeId).length === 0)
317
+ return false;
318
+ kernel.sealImportedEpisode(episodeId, { reason });
319
+ return true;
320
+ }
310
321
  async function recordRawImportedEvidence(kernel, projectId, envelope) {
311
322
  const sourceRef = envelope.ingestInput.sourceRefs?.[0];
312
323
  const record = envelope.record;
@@ -483,6 +494,8 @@ function printHumanSummary(result) {
483
494
  console.log(`records ${action}: ${result.dryRun ? result.recordsWouldIngest : result.recordsIngested}`);
484
495
  if (result.rawRecordsAnchored !== undefined)
485
496
  console.log(`raw ledger anchors: ${result.rawRecordsAnchored}`);
497
+ if (result.emptyEpisodesSkipped)
498
+ console.log(`empty episodes skipped: ${result.emptyEpisodesSkipped}`);
486
499
  console.log(`records skipped: ${result.skippedRecords}`);
487
500
  if (result.diagnostics.length > 0) {
488
501
  console.log('diagnostics:');
package/dist/bin/mcp.js CHANGED
@@ -29,7 +29,8 @@ function stringArg(values, key) {
29
29
  }
30
30
  function usage() {
31
31
  return [
32
- 'Usage: cogmem-mcp [--db <memory.db>|--config <config.toml>] [--cwd <dir>]',
32
+ 'Usage: cogmem mcp [--db <memory.db>|--config <config.toml>] [--cwd <dir>]',
33
+ ' cogmem-mcp [--db <memory.db>|--config <config.toml>] [--cwd <dir>]',
33
34
  '',
34
35
  'Starts a stdio MCP server exposing recall, strategy, episode append/import/status/seal, conditional dream tick/status, memory map, maintenance, and prospective-memory tools.',
35
36
  ].join('\n');
@@ -62,11 +62,13 @@ async function main() {
62
62
  const args = parseArgs(process.argv.slice(2));
63
63
  const dbPath = resolveDbPath(args);
64
64
  const shouldBackup = !args.dryRun && args.backup && dbPath !== ':memory:' && existsSync(dbPath);
65
- const db = new Database(dbPath);
65
+ const db = new Database(dbPath, args.dryRun && dbPath !== ':memory:' ? { readonly: true, create: false } : undefined);
66
66
  db.exec('PRAGMA busy_timeout = 5000;');
67
+ if (args.dryRun)
68
+ db.exec('PRAGMA query_only = ON;');
67
69
  try {
68
70
  const backupPath = shouldBackup ? backupDatabase(db, dbPath) : undefined;
69
- const runner = new SchemaMigrationRunner(db, ALL_MIGRATIONS);
71
+ const runner = new SchemaMigrationRunner(db, ALL_MIGRATIONS, { readonly: args.dryRun });
70
72
  const result = runner.run({ dryRun: args.dryRun });
71
73
  if (!args.dryRun) {
72
74
  db.exec(`CREATE TABLE IF NOT EXISTS _meta (key TEXT PRIMARY KEY, value TEXT NOT NULL);`);
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env bun
2
- import { existsSync, readFileSync } from 'node:fs';
3
- import { join, resolve } from 'node:path';
2
+ import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
3
+ import { dirname, join, resolve } from 'node:path';
4
4
  import { defaultOpenClawAutoMemoryPluginDir, inspectOpenClawAutoMemoryPlugin, } from '../host/openclaw/AutoMemoryPluginInstaller.js';
5
5
  function readArg(name) {
6
6
  const index = process.argv.indexOf(name);
@@ -42,6 +42,54 @@ function readAudit(workspaceRoot) {
42
42
  recentErrors: records.filter((record) => record.action === 'error').slice(-20),
43
43
  };
44
44
  }
45
+ function countJsonlLines(path) {
46
+ if (!existsSync(path))
47
+ return 0;
48
+ return readFileSync(path, 'utf8').split('\n').map((line) => line.trim()).filter(Boolean).length;
49
+ }
50
+ function readLock(path) {
51
+ if (!existsSync(path))
52
+ return undefined;
53
+ const ownerPath = join(path, 'owner.json');
54
+ let owner;
55
+ if (existsSync(ownerPath)) {
56
+ try {
57
+ owner = JSON.parse(readFileSync(ownerPath, 'utf8'));
58
+ }
59
+ catch {
60
+ owner = { parseError: true };
61
+ }
62
+ }
63
+ const stat = statSync(path);
64
+ return {
65
+ path,
66
+ mtimeMs: stat.mtimeMs,
67
+ ageMs: Date.now() - stat.mtimeMs,
68
+ owner,
69
+ };
70
+ }
71
+ function inspectQueue(workspaceRoot) {
72
+ const queuePath = join(workspaceRoot, '.cogmem', 'queue', 'openclaw-remember.jsonl');
73
+ const queueDir = dirname(queuePath);
74
+ const processingFiles = existsSync(queueDir)
75
+ ? readdirSync(queueDir)
76
+ .filter((entry) => entry.startsWith('openclaw-remember.jsonl.') && entry.endsWith('.processing'))
77
+ .map((entry) => {
78
+ const path = join(queueDir, entry);
79
+ const stat = statSync(path);
80
+ return { path, lines: countJsonlLines(path), mtimeMs: stat.mtimeMs, ageMs: Date.now() - stat.mtimeMs };
81
+ })
82
+ : [];
83
+ return {
84
+ queuePath,
85
+ pendingLines: countJsonlLines(queuePath),
86
+ deadPath: `${queuePath}.dead.jsonl`,
87
+ deadLines: countJsonlLines(`${queuePath}.dead.jsonl`),
88
+ lock: readLock(`${queuePath}.lock`),
89
+ spawnLock: readLock(`${queuePath}.spawn.lock`),
90
+ processingFiles,
91
+ };
92
+ }
45
93
  function main() {
46
94
  const [command] = process.argv.slice(2).filter((arg) => !arg.startsWith('--'));
47
95
  if (command !== 'diagnose' || hasFlag('--help') || hasFlag('-h')) {
@@ -55,12 +103,14 @@ function main() {
55
103
  const pluginDir = readArg('--plugin-dir') || defaultOpenClawAutoMemoryPluginDir(workspaceRoot);
56
104
  const plugin = inspectOpenClawAutoMemoryPlugin({ workspaceRoot, pluginDir });
57
105
  const audit = readAudit(workspaceRoot);
106
+ const queue = inspectQueue(workspaceRoot);
58
107
  const payload = {
59
108
  schemaVersion: 'cogmem.cli.v1',
60
109
  command: 'openclaw diagnose',
61
110
  workspaceRoot,
62
111
  plugin,
63
112
  audit,
113
+ queue,
64
114
  };
65
115
  if (hasFlag('--json')) {
66
116
  console.log(JSON.stringify(payload));
@@ -74,5 +124,6 @@ function main() {
74
124
  else {
75
125
  console.log('last before_prompt_build: none');
76
126
  }
127
+ console.log(`queue: pending=${queue.pendingLines} dead=${queue.deadLines} processing=${Array.isArray(queue.processingFiles) ? queue.processingFiles.length : 0}`);
77
128
  }
78
129
  main();