cogmem 3.6.4 → 3.6.5

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,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.6.5
4
+
5
+ - Added `cogmem memory plan` as a read-only agent operations summary with queue state, blocking/non-blocking next actions, Dream backlog hints, and vector fallback state.
6
+ - Made default `cogmem memory candidates --json` return grouped ordinary, `needs_confirmation`, and deferred queues with actionable `nextActions`, while explicit `--status` still lists one queue.
7
+ - Fixed `cogmem memory list --since/--until/--order` so raw-ledger inspection can resume from global sequence cursors instead of silently ignoring the filters.
8
+ - Added `sourceLocator` drill-down commands to raw ledger list rows and Atlas search/explore evidence so agents can move from summaries to exact `memory show` context before quoting or claiming absence.
9
+ - Added a `historical_discussion` recall intent for “did we discuss this before?” questions, with raw-ledger-first routing and expanded cues for Cogmem/OpenClaw memory-black-box discussions.
10
+ - Changed Memory Binding backfill to scan raw events by cursor across the historical ledger rather than only the latest page, so old imported high-value user events can be bound after upgrade.
11
+ - Changed `cogmem connect ... --json` to expose structured `nextSteps` and keep unsafe operator/host actions such as interactive init and host restart out of agent-safe `nextCommands`.
12
+ - Fixed `cogmem memory plan` so Raw Ledger dream coverage lag is reported as non-blocking `raw_dream_ledger_lag` with `resolvableByDreamTick:false` instead of misleading agents into looping `dream tick` when no sealed episode backlog exists.
13
+ - Updated the auto-installed OpenClaw/Hermes skills and operations handbooks with the full npm install, update, migration, import, `memory plan`, historical recall, source drill-down, governance, and maintenance command playbook.
14
+
3
15
  ## 3.6.4
4
16
 
5
17
  - 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`.
package/README.md CHANGED
@@ -11,7 +11,7 @@ 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.4`
14
+ Current version: `3.6.5`
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
 
@@ -229,7 +229,7 @@ cogmem migrate --dry-run --json
229
229
 
230
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.
231
231
 
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:
232
+ Upgrade a 3.5.2 database, a 3.6.0 database, or a pre-release schema-25 test database into the 3.6.5 schema set with one command:
233
233
 
234
234
  ```bash
235
235
  cogmem migrate --yes --backup --json
@@ -270,7 +270,7 @@ cogmem memory candidates --project my-agent --status needs_confirmation --json
270
270
  cogmem memory review --project my-agent --id <candidate-id> --action approve --actor <operator> --reason "confirmed" --confirmation-event <user-event-id> --json
271
271
  ```
272
272
 
273
- For a host timer, call `dream tick`; the timer only wakes the scheduler. An empty backlog performs no Dream work:
273
+ For a host timer, call `dream tick`; the timer only wakes the sealed-episode scheduler. An empty episode backlog performs no Dream work, and `undreamedRawCount` by itself is not a reason to loop `dream tick`:
274
274
 
275
275
  ```bash
276
276
  cogmem dream tick --project my-agent --mode auto --max-episodes 10 --json
@@ -278,7 +278,7 @@ cogmem dream tick --project my-agent --mode auto --max-episodes 10 --json
278
278
 
279
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.
280
280
 
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.
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 and later skip import batch sealing for empty episode boundaries and skip 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.
282
282
 
283
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.
284
284
 
@@ -287,13 +287,17 @@ Episode surgery is available through `cogmem episode split|merge|move-event|recl
287
287
  Inspect queue state:
288
288
 
289
289
  ```bash
290
+ cogmem memory plan --project my-agent --json
290
291
  cogmem memory status --project my-agent --json
292
+ cogmem memory candidates --project my-agent --json
291
293
  cogmem memory candidates --project my-agent --status candidate --json
292
294
  cogmem memory govern --project my-agent --json
293
295
  cogmem memory candidates --project my-agent --status needs_confirmation --json
294
296
  cogmem memory review --project my-agent --id <candidate-id> --action approve --actor <operator> --reason "confirmed" --confirmation-event <user-event-id> --json
295
297
  ```
296
298
 
299
+ `memory plan` is the read-only agent operations summary. It returns queue counts, Dream backlog, vector fallback state, blocking actions, and safe next commands. Only run `dream_tick` when it appears in `nextActions`; `nonBlocking[].type === "raw_dream_ledger_lag"` reports Raw Ledger coverage lag with `resolvableByDreamTick: false`, so inspect sources or episode/import boundaries instead of retrying `dream tick`. Default `memory candidates --json` groups ordinary, `needs_confirmation`, and deferred work in one payload; pass `--status candidate` or `--status needs_confirmation` only when the user asks for one queue.
300
+
297
301
  `memory govern` intentionally promotes only `candidate`. With `--status needs_confirmation` it lists the review queue and prints the `memory review` command instead of silently promoting the wrong status. Review actions are approve, reject, defer, supersede, and correction relink; every action stores operator identity, reason, and evidence requirements in an immutable audit row. `defer` keeps the candidate in `needs_confirmation` and records `reviewAfter` plus a status reason.
298
302
 
299
303
  ## Memory Atlas: let an agent see what it remembers
@@ -314,6 +318,8 @@ Atlas filtering is not limited to entity + time + action. The query compiler com
314
318
 
315
319
  Defaults are 8 nodes, one hop, and two evidence IDs per node. Hard limits are 30 nodes, two hops, ten evidence IDs, six path hops, and 2,000 visited nodes. Raw excerpts are omitted unless `--include-evidence` or `includeEvidence: true` is explicit. `evidenceTotal` reports all known evidence while `evidenceReturned` reports the bounded payload. Every returned evidence item carries an `eventId` and a `cogmem memory show` drilldown command.
316
320
 
321
+ In 3.6.5, Atlas search and explore evidence also carries `sourceLocator.command` and `sourceLocator.contextCommand`. Agents should run that locator before quoting exact wording, before claiming a historical topic is absent, or when a graph summary looks relevant but underspecified.
322
+
317
323
  Atlas reads do not brighten everything they display. MCP graph queries are read-only/idempotent; call `cogmem_graph_touch` only after the agent actually uses selected nodes. Maintenance decays activation, refreshes dirty projections only, and prunes old access telemetry.
318
324
 
319
325
  Agents should use Atlas for broad inventory, history, and relationship questions; use normal recall for a direct fact. See [MEMORY_ATLAS.md](./MEMORY_ATLAS.md) for the complete CLI, MCP, OpenClaw, activation, and provenance contract.
@@ -351,7 +357,7 @@ Operational cost classes:
351
357
 
352
358
  Never overlap maintenance writers against one database. Wait for each command to exit, use returned `durationMs`, backlog, and failure details to set the next interval, and keep routine status/candidate inspection on the read-only path. A `vectors` count of zero is not by itself a failure: `memory status --json` includes `vectorState.recallAvailableWithoutVectors` and the active fallback status.
353
359
 
354
- `memory bind` backfills Memory Binding for raw user events written outside the agent turn path, including imported OpenClaw/Hermes history and adapter-written raw events. Use `--since <globalSeq>` to resume from a known ledger sequence.
360
+ `memory bind` backfills Memory Binding for raw user events written outside the agent turn path, including imported OpenClaw/Hermes history and adapter-written raw events. In 3.6.5 it scans by Raw Ledger cursor rather than only the latest page. Use `--since <globalSeq>` to resume from a known ledger sequence.
355
361
 
356
362
  `memory map` includes Memory Binding and Graph Recall counters. Bindings attach valuable user raw events to stable topic/entity paths before any fact promotion, fuse same-claim evidence into claim-key clusters, and create graph anchors for source drill-down. Correction events create explicit correction edges and review flags instead of poisoning the active cluster. Treat bindings, clusters, and graph edges as organization hints, not as verified long-term facts.
357
363
 
@@ -374,6 +380,8 @@ cogmem strategy outcomes --project hermes --json
374
380
 
375
381
  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.
376
382
 
383
+ `cogmem connect openclaw --auto --force --json` and `cogmem connect hermes --auto --force --json` now return structured `nextSteps`. Only `nextSteps` with `actor: "agent"` and `safeForAutomation: true` are mirrored into `nextCommands`. Interactive setup, gateway restart, and Hermes reload remain visible as operator/host steps but are intentionally absent from `nextCommands`.
384
+
377
385
  `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.
378
386
 
379
387
  ```bash
@@ -459,9 +467,9 @@ From the OpenClaw workspace:
459
467
 
460
468
  ```bash
461
469
  cd ~/.openclaw/workspace
462
- cogmem init --agent openclaw --scope project
470
+ npm install cogmem@latest --save
471
+ ./node_modules/.bin/cogmem connect openclaw --workspace . --auto --force
463
472
  cogmem doctor
464
- cogmem connect openclaw --workspace . --auto --force
465
473
  ```
466
474
 
467
475
  Import existing OpenClaw memory:
@@ -500,7 +508,9 @@ By default, `selective_compile` uses user text as the durable compile signal, ex
500
508
  After updates or config drift:
501
509
 
502
510
  ```bash
503
- cogmem doctor --fix --agent openclaw --workspace .
511
+ cogmem update --yes
512
+ cogmem doctor --fix --agent openclaw --workspace . --plugin-only
513
+ openclaw gateway restart
504
514
  ```
505
515
 
506
516
  ## Hermes
@@ -622,6 +632,7 @@ Useful intents:
622
632
  ```bash
623
633
  cogmem memory recall --query "上个会话我们聊了什么" --intent previous_session_summary --project openclaw --agent openclaw --json
624
634
  cogmem memory recall --query "我当时关于记忆黑盒的原话是什么" --intent forensic_quote --project openclaw --agent openclaw --json
635
+ cogmem memory recall --query "几个月前我们是不是讨论过 Cogmem 的记忆黑盒" --intent historical_discussion --project openclaw --agent openclaw --json
625
636
  ```
626
637
 
627
638
  Recall results include:
@@ -647,6 +658,15 @@ cogmem memory show --event <eventId> --before 2 --after 2 --json
647
658
 
648
659
  Raw-ledger fallback is not limited to the latest fixed event window. When Chinese FTS cannot match a cue directly, Cogmem runs a project/workspace/thread/time-scoped ledger text fallback and prefers an original user event over an assistant retelling when both match equally. Imported OpenClaw Markdown also accepts empty `user:` / `assistant:` headers whose body follows on later lines and collapses only adjacent exact duplicate exports.
649
660
 
661
+ For ledger audits or resumable import/binding checks, use global sequence cursors:
662
+
663
+ ```bash
664
+ cogmem memory list --project openclaw --since <global-seq> --order asc --json
665
+ cogmem memory list --project openclaw --since <global-seq> --until <global-seq> --order asc --json
666
+ ```
667
+
668
+ Each listed event includes a `sourceLocator` with a `memory show` command. Use it before saying an event ID or exact source is unavailable.
669
+
650
670
  ## TypeScript API
651
671
 
652
672
  ```ts
@@ -770,7 +790,7 @@ npm pack --dry-run --json
770
790
  npm publish --dry-run --access public
771
791
  ```
772
792
 
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`.
793
+ Create a GitHub Release from the matching version tag, for example `v3.6.5`. 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
794
 
775
795
  Publish manually only for emergency fallback:
776
796
 
@@ -1,11 +1,11 @@
1
- # cogmem 3.6.4 Release Checklist
1
+ # cogmem 3.6.5 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.4`.
8
+ - `package.json` version is `3.6.5`.
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.
@@ -60,7 +60,9 @@ MCP `tools/list` includes strategy, episode append/import/status/seal/repair, to
60
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.
61
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
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`.
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 explain the 3.6.5 agent operations protocol: `memory plan` for next actions, default grouped `memory candidates --json`, `memory list --since/--until/--order`, historical-discussion recall intent, Atlas evidence `sourceLocator`, and cursor-based `memory bind`.
65
+ - `connect openclaw|hermes --json` documents structured `nextSteps`; `nextCommands` must contain only agent-safe, non-interactive commands and must not include `cogmem init`, `cogmem-init`, gateway restart, or Hermes reload.
64
66
  - README and skills document `cogmem mcp` as the preferred MCP server command for new configs while preserving `cogmem-mcp` as a compatibility bin.
65
67
  - 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.
66
68
  - README and skills explain user-shaped topic operations, user-explicit versus model-candidate authority, alias collision review, operation rollback, and project isolation.
@@ -91,7 +93,7 @@ npm publish --dry-run --access public
91
93
 
92
94
  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.
93
95
 
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.
96
+ After verification, create a GitHub Release from the matching version tag, for example `v3.6.5`. The release workflow publishes through npm Trusted Publishing when the release is published. It must not publish on tag push alone.
95
97
 
96
98
  Emergency manual fallback:
97
99
 
@@ -61,6 +61,7 @@ export interface AgentRecallSourceAnchor {
61
61
  }
62
62
  export interface AgentRecallSourceContextEvent {
63
63
  eventId: string;
64
+ globalSeq?: number;
64
65
  label: string;
65
66
  role?: MemoryEvent['role'];
66
67
  rawEventType?: MemoryEvent['rawEventType'];
@@ -89,7 +90,10 @@ export interface AgentRecallSourceContext {
89
90
  window: SourceContextWindowMetadata;
90
91
  locator: {
91
92
  eventId: string;
93
+ globalSeq?: number;
94
+ projectId?: string;
92
95
  command: string;
96
+ contextCommand?: string;
93
97
  threadId?: string;
94
98
  sessionId?: string;
95
99
  localDate?: string;
@@ -172,7 +176,7 @@ export interface AgentRecallResult {
172
176
  export interface AgentRecallDecisionTrace {
173
177
  version: 'agent_recall_decision.v1';
174
178
  selectedLane: 'graph' | 'compiled' | 'brain_fallback' | 'raw_ledger' | 'mixed' | 'none';
175
- reason: 'previous_session' | 'forensic_quote' | 'graph_selected' | 'raw_cue_match_preferred' | 'compiled_cue_match' | 'brain_fallback_selected' | 'raw_ledger_only' | 'no_recall_evidence';
179
+ reason: 'previous_session' | 'forensic_quote' | 'historical_discussion' | 'graph_selected' | 'raw_cue_match_preferred' | 'compiled_cue_match' | 'brain_fallback_selected' | 'raw_ledger_only' | 'no_recall_evidence';
176
180
  candidateCounts: {
177
181
  graph: number;
178
182
  navigation: number;
@@ -242,6 +246,7 @@ export declare class KernelAgentMemoryBackend {
242
246
  recallPack(query: AgentRecallQuery): AgentRecallPackResult;
243
247
  private recallPreviousSession;
244
248
  private recallForensicQuote;
249
+ private recallHistoricalDiscussion;
245
250
  private recallForensicAnchor;
246
251
  private searchRawEventsByQueryPlan;
247
252
  private rawLedgerFallbackItemsForQuery;
@@ -254,6 +254,9 @@ export class KernelAgentMemoryBackend {
254
254
  if (query.intent === 'forensic_quote') {
255
255
  return this.recallForensicQuote(query, queryPlan);
256
256
  }
257
+ if (queryPlan.intent === 'historical_discussion') {
258
+ return this.recallHistoricalDiscussion(query, queryPlan);
259
+ }
257
260
  const limit = query.limit ?? 5;
258
261
  const allowsGraph = laneAllowed(query.retrievalPolicy, 'graph');
259
262
  const allowsCompiled = laneAllowed(query.retrievalPolicy, 'compiled');
@@ -490,6 +493,46 @@ export class KernelAgentMemoryBackend {
490
493
  }, items.length),
491
494
  };
492
495
  }
496
+ recallHistoricalDiscussion(query, queryPlan) {
497
+ const limit = query.limit ?? 5;
498
+ const allowsGraph = laneAllowed(query.retrievalPolicy, 'graph');
499
+ const allowsCompiled = laneAllowed(query.retrievalPolicy, 'compiled');
500
+ const allowsRawSource = laneAllowed(query.retrievalPolicy, 'raw_source');
501
+ const graphItems = allowsGraph ? this.memoryBindingGraphItemsForQuery(query, queryPlan, limit) : [];
502
+ const rawItems = allowsRawSource ? this.rawLedgerFallbackItemsForQuery(queryPlan, query, Math.max(limit * 2, 10)) : [];
503
+ const retrievalLimit = Math.max(limit * 4, 24);
504
+ const compiledItems = allowsCompiled
505
+ ? this.filterAgentEvidence(this.kernel.navigateMemory(queryPlan.primarySearchText, {
506
+ projectId: query.projectId,
507
+ limit: retrievalLimit,
508
+ startTime: query.startTime,
509
+ endTime: query.endTime,
510
+ }).rawEvidence, query.agentId, query.collection, query.excludeSessionId)
511
+ .slice(0, limit)
512
+ .map((neuron) => this.toAgentRecallItem(neuron))
513
+ : [];
514
+ const items = this.mergeRecallItems(rawItems, this.mergeRecallItems(graphItems, compiledItems, limit), limit);
515
+ const selectedLane = rawItems.length > 0
516
+ ? 'raw_ledger'
517
+ : graphItems.length > 0
518
+ ? 'graph'
519
+ : compiledItems.length > 0
520
+ ? 'compiled'
521
+ : 'none';
522
+ return {
523
+ recallMode: rawItems.length > 0 ? 'raw_ledger_fallback' : 'brain_recall_fallback',
524
+ items,
525
+ fallbackUsed: true,
526
+ queryPlan,
527
+ decisionTrace: recallDecisionTrace(selectedLane, 'historical_discussion', {
528
+ graph: graphItems.length,
529
+ navigation: compiledItems.length,
530
+ scopedNavigation: compiledItems.length,
531
+ brainFallback: 0,
532
+ rawLedger: rawItems.length,
533
+ }, items.length),
534
+ };
535
+ }
493
536
  recallForensicAnchor(query, limit) {
494
537
  if (!query.anchorEventId)
495
538
  return [];
@@ -928,7 +971,10 @@ export class KernelAgentMemoryBackend {
928
971
  window: normalized.window,
929
972
  locator: {
930
973
  eventId: event.eventId,
931
- command: `cogmem memory show --event ${event.eventId} --before 2 --after 2`,
974
+ globalSeq: event.globalSeq,
975
+ projectId: event.projectId,
976
+ command: `cogmem memory show --event ${cliArg(event.eventId)}${event.projectId ? ` --project ${cliArg(event.projectId)}` : ''} --before 2 --after 2 --json`,
977
+ contextCommand: `cogmem memory show --event ${cliArg(event.eventId)}${event.projectId ? ` --project ${cliArg(event.projectId)}` : ''} --before 3 --after 3 --json`,
932
978
  threadId: event.threadId,
933
979
  sessionId: event.sessionId,
934
980
  localDate: event.localDate,
@@ -939,6 +985,7 @@ export class KernelAgentMemoryBackend {
939
985
  const text = this.eventText(event);
940
986
  return {
941
987
  eventId: event.eventId,
988
+ globalSeq: event.globalSeq,
942
989
  label: memoryEventLabel(event),
943
990
  role: event.role,
944
991
  rawEventType: event.rawEventType,
@@ -1270,3 +1317,6 @@ function uniqueNonEmpty(values) {
1270
1317
  function laneAllowed(policy, lane) {
1271
1318
  return !policy || policy.allowedLanes.includes(lane);
1272
1319
  }
1320
+ function cliArg(value) {
1321
+ return /^[A-Za-z0-9._:/=@+-]+$/u.test(value) ? value : `'${value.replace(/'/g, `'\\''`)}'`;
1322
+ }
@@ -1,4 +1,4 @@
1
- export type AgentRecallIntent = 'memory_recall' | 'previous_session_summary' | 'forensic_quote';
1
+ export type AgentRecallIntent = 'memory_recall' | 'previous_session_summary' | 'forensic_quote' | 'historical_discussion';
2
2
  export interface AgentRecallQueryCompileInput {
3
3
  query: string;
4
4
  intent?: AgentRecallIntent;
@@ -99,6 +99,9 @@ export function inferAgentRecallIntent(query) {
99
99
  if (/原话|怎么说的|完整对话|上一句|下一句|exact quote|verbatim/.test(text)) {
100
100
  return 'forensic_quote';
101
101
  }
102
+ if (/记得.{0,12}(聊过|讨论过|说过)|还记得|之前.{0,12}(聊过|讨论过|说过)|以前.{0,12}(聊过|讨论过|说过)|(过去|几个月前|半年前|上个月|前几天|昨天|上次|上个).{0,20}(聊过|讨论过|说过)|当时.{0,12}(聊|说|问)|那次.{0,12}(聊|说|问)|有没有.{0,12}(记录|聊过|讨论过)|have we discussed|did we talk about|previously discussed/.test(text)) {
103
+ return 'historical_discussion';
104
+ }
102
105
  return 'memory_recall';
103
106
  }
104
107
  export function extractRecallKeywords(text) {
@@ -168,10 +171,19 @@ function buildSemanticCuePhrases(keywords, query, anchorText) {
168
171
  const hasBlackBox = merged.includes('黑盒') || /黑盒|black\s*box/iu.test(text);
169
172
  if (hasMemory && hasBlackBox) {
170
173
  out.push('记忆 黑盒');
174
+ out.push('记忆黑盒');
175
+ out.push('CogMem Memory Context');
176
+ out.push('Memory Context');
177
+ out.push('上下文注入');
178
+ out.push('sourceContext 原文下钻');
171
179
  out.push('存档 黑盒');
172
180
  out.push('对话 存档 黑盒');
173
181
  out.push('上下文 黑盒');
174
182
  out.push('黑盒');
183
+ if (/graph|图|卡死|database locked|zombie|锁/iu.test(text)) {
184
+ out.push('memory graph 黑盒');
185
+ out.push('database locked zombie');
186
+ }
175
187
  }
176
188
  else if (hasBlackBox) {
177
189
  out.push('黑盒');
@@ -16,6 +16,7 @@ export declare class MemoryAtlasService {
16
16
  maxHops?: number;
17
17
  }): MemoryAtlasPathResult;
18
18
  timeline(query: string, options: MemoryAtlasQueryOptions): MemoryAtlasTimelineResult;
19
+ private attachEvidence;
19
20
  private evidence;
20
21
  private edgesFor;
21
22
  private safeEdges;
@@ -15,7 +15,8 @@ export class MemoryAtlasService {
15
15
  search(query, options) {
16
16
  const projectId = requiredProject(options.projectId);
17
17
  const nodes = this.store.search(boundedQuery(query), projectId, boundedLimit(options.limit));
18
- return slice(projectId, nodes, this.edgesFor(nodes, projectId), query);
18
+ const withEvidence = this.attachEvidence(nodes, projectId, options);
19
+ return slice(projectId, withEvidence, this.edgesFor(withEvidence, projectId), query);
19
20
  }
20
21
  explore(query, options) {
21
22
  const projectId = requiredProject(options.projectId);
@@ -32,8 +33,9 @@ export class MemoryAtlasService {
32
33
  from: compiled.range?.from, to: compiled.range?.to, limit });
33
34
  nodes = uniqueNodes([...actions.map((action) => this.store.getNode(action.id, projectId)).filter((node) => Boolean(node)), ...nodes]).slice(0, limit);
34
35
  }
35
- const edges = this.edgesFor(nodes, projectId);
36
- const result = slice(projectId, nodes, edges, query);
36
+ const nodesWithEvidence = this.attachEvidence(nodes, projectId, options);
37
+ const edges = this.edgesFor(nodesWithEvidence, projectId);
38
+ const result = slice(projectId, nodesWithEvidence, edges, query);
37
39
  result.facets = { time: compiled.range, target: target.labels.join(', ') || compiled.target, memoryKinds: compiled.memoryKinds, keywords: compiled.keywords };
38
40
  const hasFacet = Boolean(compiled.range || compiled.target || compiled.memoryKinds.length || compiled.tokens.length);
39
41
  result.coldMemoryResurrected = hasFacet && nodes.some((node) => node.activation <= 0.1);
@@ -155,14 +157,28 @@ export class MemoryAtlasService {
155
157
  return { version: 'memory_atlas.v1', projectId, query, range: compiled.range,
156
158
  temporalResurrection: Boolean(compiled.range && [...nodes, ...actions].length), nodes, actions, warnings: [] };
157
159
  }
160
+ attachEvidence(nodes, projectId, options) {
161
+ return nodes.map((node) => {
162
+ const evidence = this.evidence(node.id, projectId, options.evidenceLimit, options.includeEvidence);
163
+ const evidenceTotal = this.store.evidenceTotal(node.id, projectId);
164
+ return { ...node, evidenceCount: evidenceTotal, evidenceTotal, evidenceReturned: evidence.length, evidence };
165
+ });
166
+ }
158
167
  evidence(nodeId, projectId, requested, includeExcerpt) {
159
168
  const limit = Math.max(1, Math.min(requested ?? 2, 10));
160
169
  return this.store.evidenceIds(nodeId, projectId, limit).flatMap((eventId) => {
161
170
  const event = this.eventStore.getEvent(eventId);
162
171
  if (!event || event.projectId !== projectId)
163
172
  return [];
164
- return [{ eventId, drilldown: `cogmem memory show --event ${eventId} --project ${projectId} --json`,
165
- excerpt: includeExcerpt ? eventTextForMemory(event).slice(0, 500) : undefined }];
173
+ const sourceLocator = atlasSourceLocator(event, projectId);
174
+ return [{
175
+ eventId,
176
+ globalSeq: event.globalSeq,
177
+ projectId,
178
+ drilldown: sourceLocator.command,
179
+ sourceLocator,
180
+ excerpt: includeExcerpt ? eventTextForMemory(event).slice(0, 500) : undefined,
181
+ }];
166
182
  });
167
183
  }
168
184
  edgesFor(nodes, projectId) {
@@ -214,3 +230,21 @@ function chunked(values, size) {
214
230
  return chunks;
215
231
  }
216
232
  function slice(projectId, nodes, edges, query) { return { version: 'memory_atlas.v1', projectId, query, nodes, edges, nextActions: nodes.slice(0, 5).map((node) => ({ label: `Inspect ${node.label}`, tool: 'cogmem_graph_node', args: { id: node.id, projectId } })), warnings: [] }; }
233
+ function atlasSourceLocator(event, projectId) {
234
+ const project = projectId || event.projectId;
235
+ const projectArg = project ? ` --project ${cliArg(project)}` : '';
236
+ const base = `cogmem memory show --event ${cliArg(event.eventId)}${projectArg}`;
237
+ return {
238
+ eventId: event.eventId,
239
+ globalSeq: event.globalSeq,
240
+ projectId: project,
241
+ threadId: event.threadId,
242
+ sessionId: event.sessionId,
243
+ localDate: event.localDate,
244
+ command: `${base} --before 2 --after 2 --json`,
245
+ contextCommand: `${base} --before 3 --after 3 --json`,
246
+ };
247
+ }
248
+ function cliArg(value) {
249
+ return /^[A-Za-z0-9._:/=@+-]+$/u.test(value) ? value : `'${value.replace(/'/g, `'\\''`)}'`;
250
+ }
@@ -1,7 +1,19 @@
1
1
  export type MemoryAtlasNodeType = 'project' | 'topic' | 'entity' | 'cluster' | 'episode' | 'belief' | 'action' | 'time' | 'event';
2
2
  export interface MemoryAtlasEvidence {
3
3
  eventId: string;
4
+ globalSeq?: number;
5
+ projectId?: string;
4
6
  drilldown: string;
7
+ sourceLocator?: {
8
+ eventId: string;
9
+ globalSeq?: number;
10
+ projectId?: string;
11
+ threadId?: string;
12
+ sessionId?: string;
13
+ localDate?: string;
14
+ command: string;
15
+ contextCommand: string;
16
+ };
5
17
  excerpt?: string;
6
18
  }
7
19
  export interface MemoryAtlasNode {
@@ -24,6 +36,8 @@ export interface MemoryAtlasNode {
24
36
  evidenceTotal: number;
25
37
  /** Number of evidence records returned in this response. */
26
38
  evidenceReturned?: number;
39
+ /** Bounded first-hop raw evidence locators for agent-facing graph search/explore responses. */
40
+ evidence?: MemoryAtlasEvidence[];
27
41
  }
28
42
  export interface MemoryAtlasEdge {
29
43
  source: string;
@@ -90,21 +90,92 @@ function defaultSkillPath(agent, workspaceRoot) {
90
90
  return join(process.env.HOME || homedir(), '.hermes', 'skills', 'cogmem-memory', 'SKILL.md');
91
91
  }
92
92
  function nextCommands(agent) {
93
+ return nextSteps(agent)
94
+ .filter((step) => step.safeForAutomation && step.actor === 'agent')
95
+ .map((step) => step.command);
96
+ }
97
+ function nextSteps(agent) {
98
+ const project = agent === 'openclaw' ? 'openclaw' : 'hermes';
99
+ const importCommand = agent === 'openclaw' ? 'import-openclaw' : 'import-hermes';
100
+ const steps = [
101
+ {
102
+ id: 'doctor',
103
+ actor: 'agent',
104
+ safeForAutomation: true,
105
+ command: './node_modules/.bin/cogmem doctor',
106
+ when: 'after installation or update',
107
+ purpose: 'verify package, config, and database access',
108
+ },
109
+ {
110
+ id: 'import_dry_run',
111
+ actor: 'agent',
112
+ safeForAutomation: true,
113
+ command: `./node_modules/.bin/cogmem ${importCommand} --workspace . --project ${project} --dry-run --json`,
114
+ when: 'before importing legacy memory',
115
+ purpose: 'preview source discovery and import counts',
116
+ },
117
+ {
118
+ id: 'import_apply',
119
+ actor: 'agent',
120
+ safeForAutomation: true,
121
+ command: `./node_modules/.bin/cogmem ${importCommand} --workspace . --project ${project} --json`,
122
+ when: 'after dry-run looks correct',
123
+ purpose: 'idempotently import legacy memory into Cogmem',
124
+ },
125
+ {
126
+ id: 'memory_plan',
127
+ actor: 'agent',
128
+ safeForAutomation: true,
129
+ command: `./node_modules/.bin/cogmem memory plan --project ${project} --json`,
130
+ when: 'after import, update, or user asks for governance progress',
131
+ purpose: 'read agent-safe next actions instead of guessing from raw counters',
132
+ },
133
+ {
134
+ id: 'memory_status',
135
+ actor: 'agent',
136
+ safeForAutomation: true,
137
+ command: `./node_modules/.bin/cogmem memory status --project ${project} --json`,
138
+ when: 'for read-only health checks',
139
+ purpose: 'inspect raw ledger, vector fallback, dream backlog, and queue summary',
140
+ },
141
+ {
142
+ id: 'interactive_init',
143
+ actor: 'operator',
144
+ safeForAutomation: false,
145
+ command: `./node_modules/.bin/cogmem init --agent ${agent} --scope project`,
146
+ when: 'only if no Cogmem config exists and a human operator is present',
147
+ purpose: 'interactive first-time config wizard; agents must not run this unattended',
148
+ },
149
+ ];
93
150
  if (agent === 'openclaw') {
94
- return [
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
- ];
151
+ steps.splice(1, 0, {
152
+ id: 'openclaw_diagnose',
153
+ actor: 'agent',
154
+ safeForAutomation: true,
155
+ command: './node_modules/.bin/cogmem openclaw diagnose --workspace . --json',
156
+ when: 'after connect --auto --force or before investigating injection failures',
157
+ purpose: 'verify generated plugin files, audit log, queue lock, and hook diagnostics',
158
+ });
159
+ steps.push({
160
+ id: 'restart_gateway',
161
+ actor: 'host',
162
+ safeForAutomation: false,
163
+ command: 'openclaw gateway restart',
164
+ when: 'after plugin files or OpenClaw config changed',
165
+ purpose: 'reload OpenClaw hooks so the refreshed Cogmem plugin is active',
166
+ });
101
167
  }
102
- return [
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',
107
- ];
168
+ else {
169
+ steps.push({
170
+ id: 'reload_hermes',
171
+ actor: 'host',
172
+ safeForAutomation: false,
173
+ command: 'restart or reload Hermes MCP server',
174
+ when: 'after Hermes MCP config changed',
175
+ purpose: 'reload the cogmem MCP server entry',
176
+ });
177
+ }
178
+ return steps;
108
179
  }
109
180
  function usage() {
110
181
  return [
@@ -238,6 +309,7 @@ function installSkill(args) {
238
309
  installed: !args.dryRun && !alreadyCurrent,
239
310
  alreadyCurrent,
240
311
  nextCommands: nextCommands(args.agent),
312
+ nextSteps: nextSteps(args.agent),
241
313
  hostConfigSnippet: hostConfigSnippet(args.agent, args.workspaceRoot, args.auto),
242
314
  autoMemory,
243
315
  hermesMcp,