cogmem 3.6.5 → 3.7.0
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 +12 -0
- package/MEMORY_ATLAS.md +47 -10
- package/README.md +13 -10
- package/RELEASE_CHECKLIST.md +5 -4
- package/dist/agent/AgentMemoryBackend.d.ts +13 -1
- package/dist/agent/AgentMemoryBackend.js +103 -22
- package/dist/atlas/EpisodeTitleGenerator.d.ts +31 -0
- package/dist/atlas/EpisodeTitleGenerator.js +152 -0
- package/dist/atlas/FacetQueryPlanner.d.ts +31 -0
- package/dist/atlas/FacetQueryPlanner.js +188 -0
- package/dist/atlas/GraphCurator.d.ts +27 -0
- package/dist/atlas/GraphCurator.js +397 -0
- package/dist/atlas/MemoryAtlasIndexer.d.ts +3 -0
- package/dist/atlas/MemoryAtlasIndexer.js +19 -6
- package/dist/atlas/MemoryAtlasService.d.ts +4 -1
- package/dist/atlas/MemoryAtlasService.js +127 -8
- package/dist/atlas/MemoryAtlasTypes.d.ts +75 -11
- package/dist/bin/memory.js +4 -1
- package/dist/factory.js +1 -1
- package/dist/host/openclaw/AutoMemoryPluginInstaller.js +77 -8
- package/dist/mcp/server.js +1 -1
- package/dist/store/MemoryAtlasStore.d.ts +10 -1
- package/dist/store/MemoryAtlasStore.js +228 -14
- package/examples/hermes-backend/AGENTS.md +3 -3
- package/examples/hermes-backend/README.md +1 -1
- package/examples/hermes-backend/SKILL.md +7 -5
- package/examples/hermes-backend/references/operations.md +7 -5
- package/examples/openclaw-backend/AGENTS.md +3 -2
- package/examples/openclaw-backend/README.md +3 -2
- package/examples/openclaw-backend/SKILL.md +12 -7
- package/examples/openclaw-backend/references/operations.md +9 -7
- package/package.json +1 -1
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { createHash, randomUUID } from 'node:crypto';
|
|
2
|
+
export const MEMORY_ATLAS_PROJECTION_NAME = 'memory_atlas.v2';
|
|
3
|
+
export const MEMORY_ATLAS_PROJECTION_SCHEMA_VERSION = '3.7.0';
|
|
2
4
|
export class MemoryAtlasStore {
|
|
3
5
|
db;
|
|
4
6
|
constructor(db) {
|
|
@@ -82,12 +84,81 @@ export class MemoryAtlasStore {
|
|
|
82
84
|
return mapNode(row, matches + Number(row.activation || 0));
|
|
83
85
|
}).sort((a, b) => b.score - a.score);
|
|
84
86
|
}
|
|
87
|
+
searchCanonicalEpisodeCards(projectId, plan, limit) {
|
|
88
|
+
const plannedFacets = plan.facets;
|
|
89
|
+
if (!plannedFacets.length)
|
|
90
|
+
return [];
|
|
91
|
+
const facetMatches = plannedFacets.map((facet) => ({ facet, rows: this.episodeEdgesForFacet(projectId, facet) }));
|
|
92
|
+
if (plan.operator === 'intersection' && facetMatches.some((match) => match.rows.length === 0))
|
|
93
|
+
return [];
|
|
94
|
+
const candidateIds = plan.operator === 'intersection'
|
|
95
|
+
? intersectSets(facetMatches.map((match) => new Set(match.rows.map((row) => row.source_id))))
|
|
96
|
+
: new Set(facetMatches.flatMap((match) => match.rows.map((row) => row.source_id)));
|
|
97
|
+
if (!candidateIds.size)
|
|
98
|
+
return [];
|
|
99
|
+
const rows = this.episodeRows(projectId, Array.from(candidateIds));
|
|
100
|
+
const cards = rows.map((row) => {
|
|
101
|
+
const candidateEdges = facetMatches.flatMap((match) => match.rows.filter((edge) => edge.source_id === row.source_id));
|
|
102
|
+
return this.cardFromEpisodeRow(row, candidateEdges, projectId);
|
|
103
|
+
});
|
|
104
|
+
const selectedIds = new Set(cards.map((card) => card.canonicalId));
|
|
105
|
+
for (const card of cards) {
|
|
106
|
+
card.relatedButNotSelected = mergeRelatedCards(this.relatedEpisodeCards(projectId, card.canonicalId, selectedIds, 4), this.topicRelatedCardsForPlan(projectId, plan, selectedIds, 4)).slice(0, 4);
|
|
107
|
+
}
|
|
108
|
+
return cards.sort((left, right) => scoreCard(right) - scoreCard(left)).slice(0, Math.max(1, Math.min(limit, 100)));
|
|
109
|
+
}
|
|
110
|
+
relatedEpisodeCards(projectId, canonicalId, selectedIds, limit) {
|
|
111
|
+
const parsed = parseNodeId(canonicalId, projectId);
|
|
112
|
+
if (!parsed || parsed.type !== 'episode')
|
|
113
|
+
return [];
|
|
114
|
+
const rows = this.db.prepare(`
|
|
115
|
+
SELECT e.relation_type, e.confidence, d.node_id, d.label, d.metadata_json
|
|
116
|
+
FROM memory_edges e
|
|
117
|
+
JOIN memory_atlas_documents d ON d.project_id=e.project_id AND d.node_id=CASE
|
|
118
|
+
WHEN e.source_type='episode' AND e.source_id=? THEN 'episode:' || e.target_id
|
|
119
|
+
ELSE 'episode:' || e.source_id
|
|
120
|
+
END
|
|
121
|
+
WHERE e.project_id=? AND e.status IN ('active','weak') AND e.relation_type IN ('SAME_ISSUE','FOLLOWS_UP','REFINES','CORRECTS','CONTRADICTS','SUPERSEDES','RELATED_TO')
|
|
122
|
+
AND ((e.source_type='episode' AND e.source_id=?) OR (e.target_type='episode' AND e.target_id=?))
|
|
123
|
+
ORDER BY CASE e.relation_type WHEN 'SAME_ISSUE' THEN 1 WHEN 'FOLLOWS_UP' THEN 2 WHEN 'REFINES' THEN 3 ELSE 4 END, e.confidence DESC
|
|
124
|
+
LIMIT ?
|
|
125
|
+
`).all(parsed.id, projectId, parsed.id, parsed.id, Math.max(1, Math.min(limit * 3, 30)));
|
|
126
|
+
const result = [];
|
|
127
|
+
for (const row of rows) {
|
|
128
|
+
if (selectedIds.has(row.node_id))
|
|
129
|
+
continue;
|
|
130
|
+
result.push({
|
|
131
|
+
canonicalId: row.node_id,
|
|
132
|
+
displayTitle: row.label,
|
|
133
|
+
reason: row.relation_type === 'RELATED_TO' ? 'related topic but different issue/date' : row.relation_type.toLowerCase(),
|
|
134
|
+
});
|
|
135
|
+
if (result.length >= limit)
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
return result;
|
|
139
|
+
}
|
|
140
|
+
topicRelatedCardsForPlan(projectId, plan, selectedIds, limit) {
|
|
141
|
+
const topicFacets = plan.facets.filter((facet) => facet.type === 'topic');
|
|
142
|
+
if (!topicFacets.length)
|
|
143
|
+
return [];
|
|
144
|
+
const rows = topicFacets.flatMap((facet) => this.episodeEdgesForFacet(projectId, facet));
|
|
145
|
+
const candidateIds = Array.from(new Set(rows.map((row) => row.source_id))).filter((id) => !selectedIds.has(`episode:${id}`));
|
|
146
|
+
if (!candidateIds.length)
|
|
147
|
+
return [];
|
|
148
|
+
return this.episodeRows(projectId, candidateIds)
|
|
149
|
+
.map((row) => ({
|
|
150
|
+
canonicalId: row.node_id,
|
|
151
|
+
displayTitle: row.label,
|
|
152
|
+
reason: 'related topic but different issue/date',
|
|
153
|
+
}))
|
|
154
|
+
.slice(0, Math.max(1, Math.min(limit, 20)));
|
|
155
|
+
}
|
|
85
156
|
resolveTargetNodeIds(projectId, query) {
|
|
86
157
|
const normalizedQuery = normalizeLookup(query);
|
|
87
158
|
const candidates = this.db.prepare(`
|
|
88
159
|
SELECT node_id,node_type,source_id,label,topic_path,metadata_json,evidence_event_ids_json
|
|
89
160
|
FROM memory_atlas_documents
|
|
90
|
-
WHERE project_id=? AND node_type IN ('entity','topic','project') AND status NOT IN ('rejected','archived')
|
|
161
|
+
WHERE project_id=? AND node_type IN ('entity','topic','issue','project') AND status NOT IN ('rejected','archived')
|
|
91
162
|
`).all(projectId);
|
|
92
163
|
const seeds = [];
|
|
93
164
|
const labels = [];
|
|
@@ -375,12 +446,34 @@ export class MemoryAtlasStore {
|
|
|
375
446
|
}
|
|
376
447
|
projectionNeedsRefresh(projectId) {
|
|
377
448
|
const row = this.db.prepare(`
|
|
449
|
+
SELECT status, metadata_json FROM memory_atlas_projection_state
|
|
450
|
+
WHERE project_id=? AND projection_name=?
|
|
451
|
+
`).get(projectId, MEMORY_ATLAS_PROJECTION_NAME);
|
|
452
|
+
if (!row || row.status !== 'clean')
|
|
453
|
+
return true;
|
|
454
|
+
const metadata = parseMetadata(row.metadata_json);
|
|
455
|
+
if (metadata.projectionSchemaVersion !== MEMORY_ATLAS_PROJECTION_SCHEMA_VERSION)
|
|
456
|
+
return true;
|
|
457
|
+
const legacyDirty = this.db.prepare(`
|
|
378
458
|
SELECT status FROM memory_atlas_projection_state
|
|
379
|
-
WHERE project_id=? AND projection_name='memory_atlas.v1'
|
|
459
|
+
WHERE project_id=? AND projection_name='memory_atlas.v1' AND status<>'clean'
|
|
380
460
|
`).get(projectId);
|
|
381
|
-
return
|
|
461
|
+
return Boolean(legacyDirty);
|
|
382
462
|
}
|
|
383
463
|
markProjectionClean(projectId, metadata = {}, now = Date.now()) {
|
|
464
|
+
const enrichedMetadata = {
|
|
465
|
+
...metadata,
|
|
466
|
+
projectionName: MEMORY_ATLAS_PROJECTION_NAME,
|
|
467
|
+
projectionSchemaVersion: MEMORY_ATLAS_PROJECTION_SCHEMA_VERSION,
|
|
468
|
+
};
|
|
469
|
+
this.db.prepare(`
|
|
470
|
+
INSERT INTO memory_atlas_projection_state(
|
|
471
|
+
project_id, projection_name, cursor_value, status, last_rebuild_at, last_error, metadata_json
|
|
472
|
+
) VALUES(?, ?, ?, 'clean', ?, NULL, ?)
|
|
473
|
+
ON CONFLICT(project_id, projection_name) DO UPDATE SET
|
|
474
|
+
cursor_value=excluded.cursor_value, status='clean', last_rebuild_at=excluded.last_rebuild_at,
|
|
475
|
+
last_error=NULL, metadata_json=excluded.metadata_json
|
|
476
|
+
`).run(projectId, MEMORY_ATLAS_PROJECTION_NAME, String(now), now, JSON.stringify(enrichedMetadata));
|
|
384
477
|
this.db.prepare(`
|
|
385
478
|
INSERT INTO memory_atlas_projection_state(
|
|
386
479
|
project_id, projection_name, cursor_value, status, last_rebuild_at, last_error, metadata_json
|
|
@@ -388,17 +481,20 @@ export class MemoryAtlasStore {
|
|
|
388
481
|
ON CONFLICT(project_id, projection_name) DO UPDATE SET
|
|
389
482
|
cursor_value=excluded.cursor_value, status='clean', last_rebuild_at=excluded.last_rebuild_at,
|
|
390
483
|
last_error=NULL, metadata_json=excluded.metadata_json
|
|
391
|
-
`).run(projectId, String(now), now, JSON.stringify(
|
|
484
|
+
`).run(projectId, String(now), now, JSON.stringify({ compatibilityAliasFor: MEMORY_ATLAS_PROJECTION_NAME }));
|
|
392
485
|
}
|
|
393
486
|
markProjectionFailed(projectId, error, now = Date.now()) {
|
|
394
487
|
this.db.prepare(`
|
|
395
488
|
INSERT INTO memory_atlas_projection_state(project_id,projection_name,status,last_rebuild_at,last_error,metadata_json)
|
|
396
|
-
VALUES(
|
|
489
|
+
VALUES(?,?,'error',?,?,?)
|
|
397
490
|
ON CONFLICT(project_id,projection_name) DO UPDATE SET status='error',last_rebuild_at=excluded.last_rebuild_at,last_error=excluded.last_error
|
|
398
|
-
`).run(projectId, now, error.slice(0, 2000)
|
|
491
|
+
`).run(projectId, MEMORY_ATLAS_PROJECTION_NAME, now, error.slice(0, 2000), JSON.stringify({
|
|
492
|
+
projectionName: MEMORY_ATLAS_PROJECTION_NAME,
|
|
493
|
+
projectionSchemaVersion: MEMORY_ATLAS_PROJECTION_SCHEMA_VERSION,
|
|
494
|
+
}));
|
|
399
495
|
}
|
|
400
496
|
getProjectionState(projectId) {
|
|
401
|
-
const row = this.db.prepare(`SELECT status,last_rebuild_at,last_error FROM memory_atlas_projection_state WHERE project_id=? AND projection_name
|
|
497
|
+
const row = this.db.prepare(`SELECT status,last_rebuild_at,last_error FROM memory_atlas_projection_state WHERE project_id=? AND projection_name=?`).get(projectId, MEMORY_ATLAS_PROJECTION_NAME);
|
|
402
498
|
return row ? { status: row.status, lastRebuildAt: row.last_rebuild_at ?? undefined, lastError: row.last_error || undefined } : null;
|
|
403
499
|
}
|
|
404
500
|
listKnownProjectIds() {
|
|
@@ -436,6 +532,60 @@ export class MemoryAtlasStore {
|
|
|
436
532
|
target: nodeId('topic', row.target_path, projectId), confidence: Number(row.confidence),
|
|
437
533
|
evidenceEventIds: parseStringArray(row.evidence_event_ids_json) }));
|
|
438
534
|
}
|
|
535
|
+
episodeEdgesForFacet(projectId, facet) {
|
|
536
|
+
const relationFilter = facet.relation ? 'AND relation_type=?' : '';
|
|
537
|
+
const params = facet.relation
|
|
538
|
+
? [projectId, facet.type, facet.value, facet.relation]
|
|
539
|
+
: [projectId, facet.type, facet.value];
|
|
540
|
+
return this.db.prepare(`
|
|
541
|
+
SELECT source_id, relation_type, target_type, target_id, confidence, evidence_event_ids_json
|
|
542
|
+
FROM memory_edges
|
|
543
|
+
WHERE project_id=? AND source_type='episode' AND target_type=? AND target_id=? ${relationFilter}
|
|
544
|
+
AND status IN ('active','weak')
|
|
545
|
+
ORDER BY confidence DESC
|
|
546
|
+
LIMIT 5000
|
|
547
|
+
`).all(...params);
|
|
548
|
+
}
|
|
549
|
+
episodeRows(projectId, episodeIds) {
|
|
550
|
+
const bounded = Array.from(new Set(episodeIds)).slice(0, 500);
|
|
551
|
+
if (!bounded.length)
|
|
552
|
+
return [];
|
|
553
|
+
return this.db.prepare(`
|
|
554
|
+
SELECT d.*, COALESCE(a.activation, 0) AS activation
|
|
555
|
+
FROM memory_atlas_documents d LEFT JOIN memory_atlas_activation a
|
|
556
|
+
ON a.project_id=d.project_id AND a.node_id=d.node_id
|
|
557
|
+
WHERE d.project_id=? AND d.node_id IN (${bounded.map(() => '?').join(',')})
|
|
558
|
+
AND d.node_type='episode' AND d.status NOT IN ('rejected','archived')
|
|
559
|
+
`).all(projectId, ...bounded.map((id) => `episode:${id}`));
|
|
560
|
+
}
|
|
561
|
+
cardFromEpisodeRow(row, edges, projectId) {
|
|
562
|
+
const metadata = parseMetadata(row.metadata_json);
|
|
563
|
+
const evidenceEventIds = parseStringArray(row.evidence_event_ids_json);
|
|
564
|
+
const matchedFacets = edges.map((edge) => facetFromEdge(edge, projectId));
|
|
565
|
+
const matchedPaths = edges.map((edge) => {
|
|
566
|
+
const facet = facetFromEdge(edge, projectId);
|
|
567
|
+
return { facet, via: [facet.nodeId, row.node_id], relation: edge.relation_type, confidence: Number(edge.confidence || 0) };
|
|
568
|
+
});
|
|
569
|
+
const issueHints = stringArray(metadata.issueHints);
|
|
570
|
+
const topicHints = stringArray(metadata.topicHints);
|
|
571
|
+
return {
|
|
572
|
+
canonicalId: row.node_id,
|
|
573
|
+
nodeType: 'episode',
|
|
574
|
+
displayTitle: row.label,
|
|
575
|
+
oneLineSummary: row.summary || undefined,
|
|
576
|
+
matchedFacets,
|
|
577
|
+
matchedPaths,
|
|
578
|
+
parentTopics: topicHints.length ? topicHints : row.topic_path ? [row.topic_path] : [],
|
|
579
|
+
issueType: issueHints[0],
|
|
580
|
+
eventKind: optionalMetadataString(metadata.eventKind),
|
|
581
|
+
localDate: optionalMetadataString(metadata.localDate) ?? (row.occurred_at ? new Date(row.occurred_at).toISOString().slice(0, 10) : undefined),
|
|
582
|
+
whyMatched: matchedFacets.length ? `matched ${matchedFacets.map((facet) => `${facet.type}:${facet.value}`).join(', ')}` : 'matched canonical episode',
|
|
583
|
+
relatedButNotSelected: [],
|
|
584
|
+
evidenceEventIds,
|
|
585
|
+
evidenceTotal: evidenceEventIds.length,
|
|
586
|
+
evidenceReturned: 0,
|
|
587
|
+
};
|
|
588
|
+
}
|
|
439
589
|
}
|
|
440
590
|
function mapNode(row, score) {
|
|
441
591
|
return { id: row.node_id, projectId: row.project_id, nodeType: row.node_type, sourceId: row.source_id,
|
|
@@ -479,7 +629,7 @@ catch {
|
|
|
479
629
|
} }
|
|
480
630
|
function escapeLike(value) { return value.replace(/[\\%_]/g, '\\$&'); }
|
|
481
631
|
function nodeId(type, id, projectId) {
|
|
482
|
-
if (
|
|
632
|
+
if (['topic', 'time', 'issue', 'session', 'thread', 'memoryKind', 'actionKind'].includes(type))
|
|
483
633
|
return `${type}:${projectId}:${id}`;
|
|
484
634
|
return `${type}:${id}`;
|
|
485
635
|
}
|
|
@@ -487,14 +637,78 @@ function timeNodeId(projectId, occurredAt) {
|
|
|
487
637
|
return `time:${projectId}:${new Date(occurredAt).getUTCFullYear()}`;
|
|
488
638
|
}
|
|
489
639
|
function parseNodeId(value, projectId) {
|
|
490
|
-
const
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
return { type: 'time', id: value.slice(timePrefix.length) };
|
|
640
|
+
for (const type of ['topic', 'time', 'issue', 'session', 'thread', 'memoryKind', 'actionKind']) {
|
|
641
|
+
const prefix = `${type}:${projectId}:`;
|
|
642
|
+
if (value.startsWith(prefix))
|
|
643
|
+
return { type, id: value.slice(prefix.length) };
|
|
644
|
+
}
|
|
496
645
|
const separator = value.indexOf(':');
|
|
497
646
|
if (separator <= 0 || separator === value.length - 1)
|
|
498
647
|
return null;
|
|
499
648
|
return { type: value.slice(0, separator), id: value.slice(separator + 1) };
|
|
500
649
|
}
|
|
650
|
+
function parseMetadata(value) {
|
|
651
|
+
try {
|
|
652
|
+
const parsed = JSON.parse(value || '{}');
|
|
653
|
+
return parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed : {};
|
|
654
|
+
}
|
|
655
|
+
catch {
|
|
656
|
+
return {};
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
function stringArray(value) {
|
|
660
|
+
return Array.isArray(value) ? value.filter((item) => typeof item === 'string' && item.length > 0) : [];
|
|
661
|
+
}
|
|
662
|
+
function optionalMetadataString(value) {
|
|
663
|
+
return typeof value === 'string' && value ? value : undefined;
|
|
664
|
+
}
|
|
665
|
+
function facetFromEdge(edge, projectId) {
|
|
666
|
+
return {
|
|
667
|
+
type: edge.target_type,
|
|
668
|
+
value: edge.target_id,
|
|
669
|
+
label: facetLabel(edge.target_type, edge.target_id),
|
|
670
|
+
nodeId: nodeId(edge.target_type, edge.target_id, projectId),
|
|
671
|
+
relation: edge.relation_type,
|
|
672
|
+
};
|
|
673
|
+
}
|
|
674
|
+
function facetLabel(type, value) {
|
|
675
|
+
if (type === 'topic')
|
|
676
|
+
return value.split('/').pop() || value;
|
|
677
|
+
if (type === 'issue') {
|
|
678
|
+
if (value === 'memory-context-blackbox')
|
|
679
|
+
return 'Memory Context 黑盒';
|
|
680
|
+
if (value === 'graph-runtime-blackbox')
|
|
681
|
+
return 'Graph Runtime 黑盒';
|
|
682
|
+
if (value === 'atlas-readability')
|
|
683
|
+
return 'Atlas 可读性黑盒';
|
|
684
|
+
if (value === 'auto-injection-mismatch')
|
|
685
|
+
return '自动注入不一致';
|
|
686
|
+
}
|
|
687
|
+
return value;
|
|
688
|
+
}
|
|
689
|
+
function intersectSets(sets) {
|
|
690
|
+
if (!sets.length)
|
|
691
|
+
return new Set();
|
|
692
|
+
const [first, ...rest] = sets;
|
|
693
|
+
const result = new Set();
|
|
694
|
+
for (const value of first ?? []) {
|
|
695
|
+
if (rest.every((set) => set.has(value)))
|
|
696
|
+
result.add(value);
|
|
697
|
+
}
|
|
698
|
+
return result;
|
|
699
|
+
}
|
|
700
|
+
function scoreCard(card) {
|
|
701
|
+
const issuePriority = card.issueType === 'memory-context-blackbox' ? 4
|
|
702
|
+
: card.issueType === 'graph-runtime-blackbox' ? 2
|
|
703
|
+
: card.issueType === 'atlas-readability' ? 1
|
|
704
|
+
: 0;
|
|
705
|
+
return card.matchedFacets.length * 10 + issuePriority + card.matchedPaths.reduce((sum, path) => sum + path.confidence, 0) + (card.localDate ? 0.1 : 0);
|
|
706
|
+
}
|
|
707
|
+
function mergeRelatedCards(...groups) {
|
|
708
|
+
const merged = new Map();
|
|
709
|
+
for (const group of groups)
|
|
710
|
+
for (const card of group)
|
|
711
|
+
if (!merged.has(card.canonicalId))
|
|
712
|
+
merged.set(card.canonicalId, card);
|
|
713
|
+
return Array.from(merged.values());
|
|
714
|
+
}
|
|
@@ -122,7 +122,7 @@ cogmem normalize-transcript --input ./hermes-sessions.jsonl --output ./hermes.no
|
|
|
122
122
|
cogmem import-hermes --workspace . --project hermes --session ./hermes.normalized.md
|
|
123
123
|
```
|
|
124
124
|
|
|
125
|
-
Cogmem
|
|
125
|
+
Cogmem skips import batch sealing for empty episode boundaries and skips legacy empty Dream jobs so one bad imported episode cannot block the queue.
|
|
126
126
|
|
|
127
127
|
After import, use this order:
|
|
128
128
|
|
|
@@ -162,7 +162,7 @@ cogmem memory list --project hermes --since <globalSeq> --order asc --json
|
|
|
162
162
|
|
|
163
163
|
`vectors: 0` does not mean Cogmem has no memory. It means the dense vector index has no hot vectors yet. `memory recall` still falls back to governed raw ledger search and returns `sourceContext` locators. Broad inventory questions are expanded into structured cues such as `库存管理`, `在库`, `产品コード`, and `数量`; if compiled-memory candidates miss those cues, raw ledger evidence is preferred.
|
|
164
164
|
|
|
165
|
-
`sourceContext` and `memory show --json`
|
|
165
|
+
`sourceContext` and `memory show --json` share the same replay contract: each event has a `label`, optional `charRange` / `sourceRange`, and `sourceContext.window` / `window` metadata with requested counts, actual counts, `excludesAnchor`, `ordering`, `roleFilter`, and `overlapHandling`. Use those fields before quoting exact wording or explaining what happened before/after a recalled point. Raw Ledger list rows and Atlas search/explore evidence include `sourceLocator.command` and `sourceLocator.contextCommand`; run those commands before saying the source event is unavailable.
|
|
166
166
|
|
|
167
167
|
Check status with:
|
|
168
168
|
|
|
@@ -227,7 +227,7 @@ Hermes has no automatic observation path in this integration. Use `cogmem_episod
|
|
|
227
227
|
|
|
228
228
|
Use `cogmem_topic_operate` with actor `user_explicit` only for explicit user naming/organization instructions. Model suggestions use `model_candidate` and remain reviewable; alias collisions fail closed. Use `cogmem_episode_repair` for split/merge/move/reclassify/requeue work so receipts, stale candidates, cross-references, Dream jobs, and audit records stay synchronized. Do not hand-edit the database.
|
|
229
229
|
|
|
230
|
-
Use `cogmem memory map --project hermes --json` or MCP `cogmem_memory_map` to inspect Memory Binding and Graph Recall counters. Bindings attach high-value user raw events to stable topic/entity paths, fuse same-claim evidence into claim-key clusters, and create graph anchors for source drill-down only; they are not verified facts, user preferences, or instructions. Correction bindings expose review flags and correction edges. If `cogmem memory tick --project hermes --json` suggests `bind_raw_events`, run `cogmem memory bind --project hermes --json`;
|
|
230
|
+
Use `cogmem memory map --project hermes --json` or MCP `cogmem_memory_map` to inspect Memory Binding and Graph Recall counters. Bindings attach high-value user raw events to stable topic/entity paths, fuse same-claim evidence into claim-key clusters, and create graph anchors for source drill-down only; they are not verified facts, user preferences, or instructions. Correction bindings expose review flags and correction edges. If `cogmem memory tick --project hermes --json` suggests `bind_raw_events`, run `cogmem memory bind --project hermes --json`; it scans the historical ledger by cursor and can resume with `--since <globalSeq>`. For old-discussion questions, use `cogmem memory recall --intent historical_discussion ...` or `cogmem_graph_explore`; in 3.7.0 cards carry `canonicalId`, `matchedFacets`, `matchedPaths`, `relatedButNotSelected`, and `sourceLocator`. Answer from the selected canonical card, not from a side card. Re-run `cogmem connect hermes --workspace . --auto --force --json` after upgrades to patch existing MCP allow-lists with new Cogmem tools. Follow only `nextCommands` for unattended agent work; operator/host actions are in `nextSteps` with `safeForAutomation=false`.
|
|
231
231
|
|
|
232
232
|
Dream correction records require explicit user clarification; assistant self-correction and questions containing `是不是` are not user-owned contradictions. Invalid provider output is a rejected diagnostic. Maintenance ticks supersede `needs_confirmation` entries older than the default 30-day TTL and retain their evidence rows.
|
|
233
233
|
|
|
@@ -109,7 +109,7 @@ Dream stores explicit user clarification as organizational correction evidence r
|
|
|
109
109
|
|
|
110
110
|
After upgrades, reload MCP. Rerun `cogmem connect hermes --workspace . --auto --force --json` when MCP wiring, allow-listed tools, or the installed skill bundle changed. Follow only JSON `nextCommands` for unattended agent work; operator/host actions are in `nextSteps` with `safeForAutomation=false`.
|
|
111
111
|
|
|
112
|
-
Cogmem 3.
|
|
112
|
+
Cogmem 3.7.0 exposes read-only/idempotent Memory Atlas query tools plus explicit `cogmem_graph_touch`, installs from npm by default, prevents empty imported episodes from blocking Dream, and adds an agent-safe operations protocol. Use `memory plan` for the next safe command, grouped `memory candidates --json` for queue state, `historical_discussion` recall for old-discussion questions, and returned `sourceLocator` commands for exact evidence. Only run `dream_tick` when it appears in `memory plan.nextActions`; `raw_dream_ledger_lag` in `nonBlocking` has `resolvableByDreamTick:false` and is not fixed by looping `dream tick`. Use explore for broad memory inventory/history, search and node for a known concept, path/neighbors for relations, timeline for ordered reconstruction, and normal recall for a direct fact. Query facets combine the user's actual project, day/month/year, topic, issue, entity/target, session/thread, memory-kind, action-kind, and keyword conditions like table filters, so cold memory can be revived without requiring an entity-time-action tuple. Prefer returned `cards[]` for historical discussion: `canonicalId` dedupes the episode, `matchedFacets` explains why it matched, `relatedButNotSelected` is only side context, and `sourceLocator` opens raw evidence. Touch only nodes actually used, and follow returned event IDs or `sourceLocator` commands before quoting exact wording.
|
|
113
113
|
|
|
114
114
|
## Runtime
|
|
115
115
|
|
|
@@ -114,7 +114,7 @@ timeout_ms = 60000
|
|
|
114
114
|
|
|
115
115
|
## Migrate Existing Hermes Memory
|
|
116
116
|
|
|
117
|
-
Upgrade a 3.5.2 database, an existing 3.6.
|
|
117
|
+
Upgrade a 3.5.2 database, an existing 3.6.x database, or a pre-release schema-25 test database to the current 3.7.0 schema/projection set in one backed-up command:
|
|
118
118
|
|
|
119
119
|
```bash
|
|
120
120
|
cogmem migrate --yes --backup --json
|
|
@@ -180,7 +180,7 @@ cogmem import-hermes --workspace . --project hermes --session ./hermes.normalize
|
|
|
180
180
|
|
|
181
181
|
The importer is idempotent. Re-running it skips records already imported into the same memory database.
|
|
182
182
|
|
|
183
|
-
Cogmem
|
|
183
|
+
Cogmem skips import batch sealing for empty episode boundaries and Dream skips legacy empty episode jobs instead of blocking the whole queue. If `episode status` shows `dreamError` beginning with `episode_empty`, inspect the source events and use episode repair instead of editing SQLite rows.
|
|
184
184
|
|
|
185
185
|
Run the maintenance loop under host supervision after import and during normal use. `needs_confirmation` is a human review queue, not the Dream backlog, and `memory govern` promotes only ordinary `candidate` rows:
|
|
186
186
|
|
|
@@ -214,7 +214,9 @@ Choose the graph tool from the question shape:
|
|
|
214
214
|
- Direct factual question: `cogmem_recall`.
|
|
215
215
|
- Exact wording: follow an event ID with `cogmem memory show`.
|
|
216
216
|
|
|
217
|
-
Atlas combines whatever conditions the user supplies like table filters. Do not require entity + time + action. Project,
|
|
217
|
+
Atlas combines whatever conditions the user supplies like table filters. Do not require entity + time + action. Project, day/month/year, topic, issue, entity/target, session/thread, memory kind, action kind, and ordinary cues may revive cold nodes together. Activation is visibility, not truth. Atlas summaries are hints and never replace raw evidence.
|
|
218
|
+
|
|
219
|
+
In 3.7.0, `cogmem_graph_search`, `cogmem_graph_explore`, and historical recall can return canonical `cards[]`. Prefer cards over raw node labels for past-discussion questions. A card's `canonicalId` is the single episode identity; `matchedFacets` explains time/topic/issue/entity matches; `matchedPaths` explains how the card was reached; `relatedButNotSelected` is context only and must not replace the selected answer; `sourceLocator.command` is the command to inspect exact original text. If `relaxationTrace` exists, say the answer is a relaxed nearby match, not an exact hit.
|
|
218
220
|
|
|
219
221
|
When the prompt does not contain enough injected Cogmem context, do not search legacy memory files first. Ask Cogmem directly:
|
|
220
222
|
|
|
@@ -250,7 +252,7 @@ cogmem memory show --event <eventId> --project hermes --before 2 --after 2 --jso
|
|
|
250
252
|
cogmem memory list --project hermes --since <globalSeq> --order asc --json
|
|
251
253
|
```
|
|
252
254
|
|
|
253
|
-
|
|
255
|
+
Raw list rows and Atlas search/explore evidence include `sourceLocator.command` and a deeper `sourceLocator.contextCommand`. Use those commands before claiming an event ID is missing, before quoting exact words, or before treating an Atlas summary as the source.
|
|
254
256
|
|
|
255
257
|
`vectors: 0` does not mean memory is unavailable. It means dense vector search has no hot index yet; `memory recall` still has governed raw-ledger fallback. Broad inventory questions are expanded into structured cues such as `库存管理`, `在库`, `产品コード`, and `数量`; when compiled candidates miss those cues, prefer the raw ledger result and use its `sourceContext` for details. Check status with:
|
|
256
258
|
|
|
@@ -278,7 +280,7 @@ cogmem memory tick --project hermes --json
|
|
|
278
280
|
cogmem memory bind --project hermes --json
|
|
279
281
|
```
|
|
280
282
|
|
|
281
|
-
`memory tick` does not start a daemon. Use its `suggestedActions` to decide whether Hermes should run `dream tick`, `memory govern`, `episode repair`, entity review, re-embedding, or `memory bind` for unbound high-value raw events. `undreamedRawCount` by itself is Raw Ledger coverage lag, not a sealed-episode job; do not loop `dream tick` unless `memory plan.nextActions` contains `dream_tick`.
|
|
283
|
+
`memory tick` does not start a daemon. Use its `suggestedActions` to decide whether Hermes should run `dream tick`, `memory govern`, `episode repair`, entity review, re-embedding, or `memory bind` for unbound high-value raw events. `undreamedRawCount` by itself is Raw Ledger coverage lag, not a sealed-episode job; do not loop `dream tick` unless `memory plan.nextActions` contains `dream_tick`. `memory bind` scans the historical Raw Ledger by cursor instead of only the latest page; resume large repairs with `--since <globalSeq>`.
|
|
282
284
|
|
|
283
285
|
`memory map` also exposes Memory Binding and Graph Recall counters. Bindings connect high-value user raw events to stable topic/entity paths before promotion, fuse same-claim evidence into claim-key clusters, and create graph anchors for source drill-down. Correction bindings expose review flags and correction edges. Use graph recall hits for source drill-down and topic continuity only; do not treat bindings, clusters, or edges as verified facts, user preferences, or prompt instructions.
|
|
284
286
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Cogmem 3.
|
|
1
|
+
# Cogmem 3.7.0 Operations Reference for Hermes
|
|
2
2
|
|
|
3
3
|
Read this file when installing, upgrading, importing, repairing, or operating Cogmem. `SKILL.md` contains the decision rules; this file records the operational commands.
|
|
4
4
|
|
|
@@ -76,7 +76,7 @@ cogmem doctor
|
|
|
76
76
|
cogmem connect hermes --workspace . --auto --force --json
|
|
77
77
|
```
|
|
78
78
|
|
|
79
|
-
The backed-up command upgrades 3.5.2 schema 24, an existing 3.6.
|
|
79
|
+
The backed-up command upgrades 3.5.2 schema 24, an existing 3.6.x database, or a pre-release schema-25 test database to the current 3.7.0 schema/projection state in one run and preserves Raw Ledger evidence. `--dry-run` is read-only and does not create `_schema_migrations`. Reload MCP after reconnecting.
|
|
80
80
|
|
|
81
81
|
## Import Hermes memory
|
|
82
82
|
|
|
@@ -129,7 +129,7 @@ cogmem memory review --project hermes --id <candidate-id> --action approve --act
|
|
|
129
129
|
cogmem memory recall --query "<verification question>" --project hermes --agent hermes --json
|
|
130
130
|
```
|
|
131
131
|
|
|
132
|
-
`memory plan` is the first agent-safe health and next-action command. It reports queue state, blocking and non-blocking actions, Dream backlog hints, vector fallback state, and safe commands. Only run `dream_tick` when it appears in `nextActions`; if `nonBlocking` contains `raw_dream_ledger_lag` with `resolvableByDreamTick:false`, inspect raw sources or episode/import boundaries instead of retrying `dream tick`. Default `memory candidates --json` groups ordinary candidates, `needs_confirmation`, and deferred review entries; use `--status` only for one explicit queue. `needs_confirmation` is not a Dream backlog. `memory govern` does not approve it. Use `memory review` with explicit evidence. Cogmem
|
|
132
|
+
`memory plan` is the first agent-safe health and next-action command. It reports queue state, blocking and non-blocking actions, Dream backlog hints, vector fallback state, and safe commands. Only run `dream_tick` when it appears in `nextActions`; if `nonBlocking` contains `raw_dream_ledger_lag` with `resolvableByDreamTick:false`, inspect raw sources or episode/import boundaries instead of retrying `dream tick`. Default `memory candidates --json` groups ordinary candidates, `needs_confirmation`, and deferred review entries; use `--status` only for one explicit queue. `needs_confirmation` is not a Dream backlog. `memory govern` does not approve it. Use `memory review` with explicit evidence. Cogmem skips import batch sealing for empty episode boundaries and marks legacy empty Dream jobs as skipped so one bad imported episode cannot block the queue. If `episode status` reports `episode_empty_*`, inspect the episode and repair boundaries with the audited episode repair commands.
|
|
133
133
|
|
|
134
134
|
## Inspect, recall, and drill down
|
|
135
135
|
|
|
@@ -153,12 +153,14 @@ Use `historical_discussion` for “did we discuss this before?”, “几个月
|
|
|
153
153
|
|
|
154
154
|
## Memory Atlas as composable filters
|
|
155
155
|
|
|
156
|
-
Atlas uses any available project,
|
|
156
|
+
Atlas uses any available project, day/month/year, topic, issue, entity/target, session/thread, memory-kind, action-kind, and text facets together. It does not require an entity + time + operation tuple. A canonical episode appears once even if it is reached through several facets.
|
|
157
157
|
|
|
158
158
|
```bash
|
|
159
159
|
cogmem memory graph --project hermes --json
|
|
160
160
|
cogmem memory graph-search --project hermes --query "Hermes" --json
|
|
161
161
|
cogmem memory graph-explore --project hermes --query "2025 年 Hermes 的决策" --now 1782057600000 --evidence-limit 2 --json
|
|
162
|
+
cogmem memory graph-explore --project hermes --query "6月6号关于记忆黑盒聊过什么" --json
|
|
163
|
+
cogmem memory graph-explore --project hermes --query "记忆黑盒后来有没有继续讨论" --json
|
|
162
164
|
cogmem memory graph-node --project hermes --id <node-id> --include-evidence --evidence-limit 4 --json
|
|
163
165
|
cogmem memory graph-neighbors --project hermes --id <node-id> --hops 2 --json
|
|
164
166
|
cogmem memory graph-path --project hermes --from <node-id> --to <node-id> --json
|
|
@@ -174,7 +176,7 @@ Use MCP by question shape:
|
|
|
174
176
|
- Direct fact: `cogmem_recall`.
|
|
175
177
|
- Exact source: follow `evidenceEventIds` with `memory show`.
|
|
176
178
|
|
|
177
|
-
Graph reads are pure and declared read-only/idempotent. Call `cogmem_graph_touch` only after using selected nodes. Overview display alone must not change future ranking. `evidenceTotal` is all known evidence; `evidenceReturned` is the bounded payload. Search/explore evidence includes `sourceLocator.command` and `sourceLocator.contextCommand`; use those locators before treating an Atlas summary as evidence.
|
|
179
|
+
Graph reads are pure and declared read-only/idempotent. Call `cogmem_graph_touch` only after using selected nodes. Overview display alone must not change future ranking. Search/explore may return `cards[]` for canonical episodes. Use `cards[].displayTitle` for UI/readability, `oneLineSummary` as a hint, `matchedFacets` and `matchedPaths` to explain why it matched, and `canonicalId` to dedupe. `relatedButNotSelected` is context only; do not substitute it as the answer. If `relaxationTrace` exists, say the match was relaxed. `evidenceTotal` is all known evidence; `evidenceReturned` is the bounded payload. Search/explore evidence includes `sourceLocator.command` and `sourceLocator.contextCommand`; use those locators before treating an Atlas summary as evidence.
|
|
178
180
|
|
|
179
181
|
## Candidate governance and review
|
|
180
182
|
|
|
@@ -97,7 +97,7 @@ cogmem import-openclaw --workspace . --project openclaw --json
|
|
|
97
97
|
```
|
|
98
98
|
|
|
99
99
|
Real non-JSON imports print source-level and embedding+ingest progress to stderr. Use `--json --progress` to keep JSON on stdout while streaming progress to stderr, or `--no-progress` when a wrapper needs quiet stderr.
|
|
100
|
-
Cogmem
|
|
100
|
+
Cogmem skips import batch sealing for empty episode boundaries and skips legacy empty Dream jobs so one bad imported episode cannot block the queue.
|
|
101
101
|
|
|
102
102
|
After import, use this order:
|
|
103
103
|
|
|
@@ -184,7 +184,8 @@ Recall behavior:
|
|
|
184
184
|
- Use `cogmem memory map --project openclaw --json` to inspect Memory Binding and Graph Recall counters. Bindings attach high-value user raw events to stable topic/entity paths, fuse same-claim evidence into claim-key clusters, and create graph anchors for source drill-down only; they are not verified facts, user preferences, or instructions. Correction bindings expose review flags and `CORRECTS` / `CONTRADICTS` edges; inspect the raw ledger before relying on them.
|
|
185
185
|
- If `cogmem memory tick --project openclaw --json` suggests `bind_raw_events`, run `cogmem memory bind --project openclaw --json` to backfill imported or adapter-written raw user events into the binding graph.
|
|
186
186
|
- For “did we discuss this before?”, “几个月前是不是聊过…”, “记忆黑盒”, or missing injection cases, run `cogmem memory recall --query "<past discussion question>" --intent historical_discussion --project openclaw --agent openclaw --json` before claiming no memory.
|
|
187
|
-
- For ledger audits or resumable checks, use `cogmem memory list --project openclaw --since <globalSeq> --order asc --json`; list rows and Atlas search/explore evidence include `sourceLocator` commands
|
|
187
|
+
- For ledger audits or resumable checks, use `cogmem memory list --project openclaw --since <globalSeq> --order asc --json`; list rows and Atlas search/explore evidence include `sourceLocator` commands.
|
|
188
|
+
- For old-discussion or "do you remember" questions, prefer `cogmem memory recall --intent historical_discussion ...` or `cogmem memory graph-explore ... --json`. In 3.7.0, cards carry `canonicalId`, `matchedFacets`, `matchedPaths`, `relatedButNotSelected`, and `sourceLocator`; answer from the selected canonical card, not from a related-but-not-selected side card.
|
|
188
189
|
|
|
189
190
|
Installing the workspace skill makes the kernel procedure discoverable to OpenClaw agents. Installing the local auto wrapper makes future turns call the memory kernel automatically:
|
|
190
191
|
|
|
@@ -84,11 +84,12 @@ cogmem memory tick --project openclaw --json
|
|
|
84
84
|
cogmem memory bind --project openclaw --json
|
|
85
85
|
```
|
|
86
86
|
|
|
87
|
-
Cogmem 3.
|
|
87
|
+
Cogmem 3.7.0 keeps npm as the default install/update channel and upgrades Memory Atlas into a multi-dimensional navigation graph. Use `memory plan` for the next safe command, grouped `memory candidates --json` for queue state, `historical_discussion` recall for old-discussion questions, and returned `sourceLocator` commands for exact evidence. Only run `dream_tick` when it appears in `memory plan.nextActions`; `raw_dream_ledger_lag` in `nonBlocking` has `resolvableByDreamTick:false` and is not fixed by looping `dream tick`. The auto plugin uses one shared bridge/kernel lifecycle for graph exploration, evidence-bearing node/timeline drill-down, and recall, so OpenClaw does not need MCP for broad inventory/history questions. Atlas combines the query's actual project, day/month/year, topic, issue, entity/target, session/thread, memory-kind, action-kind, and keyword conditions like table filters; no fixed entity-time-action tuple is required. Prefer returned `cards[]` for historical discussion: `canonicalId` dedupes the episode, `matchedFacets` explains why it matched, `relatedButNotSelected` is only side context, and `sourceLocator` opens the raw evidence.
|
|
88
88
|
|
|
89
89
|
```bash
|
|
90
90
|
cogmem memory plan --project openclaw --json
|
|
91
91
|
cogmem memory graph-explore --project openclaw --query "去年与 Hermes 有关的决定" --json
|
|
92
|
+
cogmem memory graph-explore --project openclaw --query "6月6号关于记忆黑盒聊过什么" --json
|
|
92
93
|
cogmem memory graph-node --project openclaw --id <node-id> --include-evidence --json
|
|
93
94
|
cogmem memory graph-path --project openclaw --from <node-id> --to <node-id> --json
|
|
94
95
|
cogmem memory recall --query "几个月前我们是不是讨论过 Cogmem 的记忆黑盒" --intent historical_discussion --project openclaw --agent openclaw --json
|
|
@@ -229,7 +230,7 @@ To make future OpenClaw turns automatically recall and record memory, run:
|
|
|
229
230
|
cogmem connect openclaw --workspace . --auto --force
|
|
230
231
|
```
|
|
231
232
|
|
|
232
|
-
`--auto` installs `<workspace>/extensions/cogmem-auto-memory/`, patches OpenClaw `plugins.load.paths`, and enables a local plugin wrapper with `before_prompt_build` and `agent_end` hooks. The wrapper calls `KernelAgentMemoryBackend` through the public `cogmem` API via a Bun bridge; core still does not import OpenClaw. Plugin 0.
|
|
233
|
+
`--auto` installs `<workspace>/extensions/cogmem-auto-memory/`, patches OpenClaw `plugins.load.paths`, and enables a local plugin wrapper with `before_prompt_build` and `agent_end` hooks. The wrapper calls `KernelAgentMemoryBackend` through the public `cogmem` API via a Bun bridge; core still does not import OpenClaw. Plugin 0.7.0 uses singleton queue/spawn locks, stale-lock and stale-processing recovery, and bounded remember batches so queued `agent_end` recording does not hold SQLite open longer than necessary.
|
|
233
234
|
|
|
234
235
|
The wrapper does not rewrite OpenClaw's native prompt, tool instructions, skills, or conversation order. It only prepends Cogmem-owned blocks:
|
|
235
236
|
|
|
@@ -114,7 +114,7 @@ timeout_ms = 60000
|
|
|
114
114
|
|
|
115
115
|
## Migrate Existing OpenClaw Memory
|
|
116
116
|
|
|
117
|
-
Upgrade a 3.5.2 database, an existing 3.6.
|
|
117
|
+
Upgrade a 3.5.2 database, an existing 3.6.x database, or a pre-release schema-25 test database to the current 3.7.0 schema/projection set in one backed-up command:
|
|
118
118
|
|
|
119
119
|
```bash
|
|
120
120
|
cogmem migrate --yes --backup --json
|
|
@@ -176,7 +176,7 @@ cogmem import-openclaw --workspace . --project openclaw --json
|
|
|
176
176
|
|
|
177
177
|
The importer is idempotent. Re-running it skips records already imported into the same memory database.
|
|
178
178
|
Real non-JSON imports print source-level and embedding+ingest progress to stderr. Use `--json --progress` to keep JSON on stdout while streaming progress to stderr, or `--no-progress` when a wrapper needs quiet stderr.
|
|
179
|
-
Cogmem
|
|
179
|
+
Cogmem skips import batch sealing for empty episode boundaries and Dream skips legacy empty episode jobs instead of blocking the whole queue. If `episode status` shows `dreamError` beginning with `episode_empty`, inspect the source events and use episode repair instead of editing SQLite rows.
|
|
180
180
|
|
|
181
181
|
After import, run the maintenance loop in this order. `needs_confirmation` is a human review queue, not the Dream backlog, and `memory govern` promotes only ordinary `candidate` rows:
|
|
182
182
|
|
|
@@ -270,6 +270,7 @@ For broad inventory, project history, or relationship questions, navigate Memory
|
|
|
270
270
|
|
|
271
271
|
```bash
|
|
272
272
|
cogmem memory graph-explore --project openclaw --query "我们关于 Hermes 做过哪些工作" --json
|
|
273
|
+
cogmem memory graph-explore --project openclaw --query "6月6号关于记忆黑盒聊过什么" --json
|
|
273
274
|
cogmem memory graph-node --project openclaw --id <node-id> --include-evidence --json
|
|
274
275
|
cogmem memory graph-path --project openclaw --from <node-id> --to <node-id> --json
|
|
275
276
|
cogmem memory graph-timeline --project openclaw --query "去年与 Hermes 有关的决定和操作" --json
|
|
@@ -277,9 +278,13 @@ cogmem memory graph-timeline --project openclaw --query "去年与 Hermes 有关
|
|
|
277
278
|
|
|
278
279
|
Graph reads default to stale-safe diagnostics. If a drainer or gateway has SQLite busy, JSON may include `atlasFresh=false` and `refreshError` while returning the existing projection. Use `--refresh` when the operator explicitly wants rebuild-or-fail, and `--no-refresh` when investigating locks.
|
|
279
280
|
|
|
280
|
-
Atlas combines the conditions present in the user's message like table filters. Do not force every question into entity + time + action. Project,
|
|
281
|
+
Atlas combines the conditions present in the user's message like table filters. Do not force every question into entity + time + action. Project, day/month/year, topic, issue, entity/target, session/thread, memory kind, action kind, and ordinary cues may independently or jointly revive cold nodes. Graph reads do not change activation; explicitly touch only nodes the agent actually uses. Activation changes visibility only.
|
|
281
282
|
|
|
282
|
-
|
|
283
|
+
In 3.7.0, `graph-search`, `graph-explore`, and historical recall can return `cards[]`. Prefer cards over raw node labels for past-discussion questions. A card's `canonicalId` is the single episode identity; `matchedFacets` explains time/topic/issue/entity matches; `matchedPaths` explains how the card was reached; `relatedButNotSelected` is context only and must not replace the selected answer; `sourceLocator.command` is the command to inspect exact original text. If `relaxationTrace` exists, say the answer is a relaxed nearby match, not an exact hit.
|
|
284
|
+
|
|
285
|
+
Follow returned `sourceLocator.command` or event IDs with `cogmem memory show`; never treat an Atlas summary or title as evidence.
|
|
286
|
+
|
|
287
|
+
The OpenClaw auto plugin calls the Atlas core directly and injects bounded volatile `<COGMEM_RECALL_CONTEXT>` / `<COGMEM_MEMORY_ATLAS>` blocks. For `historical_discussion`, the recall context includes selected episode cards, `matchedFacets`, `selectedLane`, `strictFacetsMatched`-style decision metadata when available, `relatedButNotSelected`, and `relaxationTrace`. It does not require MCP. Use normal `memory recall` for a direct factual question and `memory show` for exact wording.
|
|
283
288
|
|
|
284
289
|
If `<COGMEM_RECALL_CONTEXT>` is absent, thin, or does not answer the user's question, do not answer "I do not remember" until you actively query CogMem. Use the kernel first, not the old `memory/` Markdown files:
|
|
285
290
|
|
|
@@ -302,7 +307,7 @@ cogmem memory show --event <eventId> --before 2 --after 2 --json
|
|
|
302
307
|
cogmem memory list --project openclaw --since <globalSeq> --order asc --json
|
|
303
308
|
```
|
|
304
309
|
|
|
305
|
-
For old memories, a `raw_ledger` result may come from full scoped ledger text fallback even when Chinese FTS has no direct hit. Equal matches prefer the original user event; use `sourceContext.after` to inspect the paired assistant response instead of preferring a later assistant retelling.
|
|
310
|
+
For old memories, a `raw_ledger` result may come from full scoped ledger text fallback even when Chinese FTS has no direct hit. Equal matches prefer the original user event; use `sourceContext.after` to inspect the paired assistant response instead of preferring a later assistant retelling. Raw list rows and Atlas search/explore evidence include `sourceLocator.command` and a deeper `sourceLocator.contextCommand`; use those before claiming exact source or event IDs are unavailable.
|
|
306
311
|
|
|
307
312
|
Use collection routing for creative artifacts or drafts:
|
|
308
313
|
|
|
@@ -321,7 +326,7 @@ cogmem memory tick --project openclaw --json
|
|
|
321
326
|
cogmem memory bind --project openclaw --json
|
|
322
327
|
```
|
|
323
328
|
|
|
324
|
-
`memory tick` decays activation and returns `suggestedActions`; it does not run a hidden daemon. If it suggests `bind_raw_events`, run `memory bind` to backfill high-value raw user events written by imports or adapters.
|
|
329
|
+
`memory tick` decays activation and returns `suggestedActions`; it does not run a hidden daemon. If it suggests `bind_raw_events`, run `memory bind` to backfill high-value raw user events written by imports or adapters. `memory bind` scans the historical Raw Ledger by cursor instead of only the latest page; resume large repairs with `--since <globalSeq>`. The tick also supersedes `needs_confirmation` items older than the default 30-day review TTL with an explicit status reason; it preserves candidate evidence.
|
|
325
330
|
|
|
326
331
|
`memory map` also exposes Memory Binding and Graph Recall counters. Bindings connect high-value user raw events to stable topic/entity paths before promotion, fuse same-claim evidence into claim-key clusters, and create graph anchors for source drill-down. Correction bindings add review flags and `CORRECTS` / `CONTRADICTS` edges. Use graph recall hits to inspect raw ledger history through `sourceContext`; do not treat bindings, clusters, or edges as verified facts, user preferences, or prompt instructions.
|
|
327
332
|
|
|
@@ -349,7 +354,7 @@ cogmem connect openclaw --workspace . --auto --force
|
|
|
349
354
|
|
|
350
355
|
`--auto` writes `<workspace>/extensions/cogmem-auto-memory/`, patches `plugins.load.paths`, and enables `hooks.allowPromptInjection=true` and `hooks.allowConversationAccess=true` for the wrapper. The wrapper registers `before_prompt_build` for governed recall and `agent_end` for turn recording, then calls `KernelAgentMemoryBackend` through `cogmem` public API via a Bun bridge. Core does not import OpenClaw. In JSON output, follow only `nextCommands` for unattended agent work; unsafe operator or host steps such as interactive init and gateway restart are listed under `nextSteps` with `safeForAutomation=false`.
|
|
351
356
|
|
|
352
|
-
Queued remember is the default. `agent_end` appends a durable JSONL job under `.cogmem/queue/openclaw-remember.jsonl` and starts a singleton drainer, so Telegram or gateway responses are not blocked by embeddings, SQLite writes, or slow local models. Plugin 0.
|
|
357
|
+
Queued remember is the default. `agent_end` appends a durable JSONL job under `.cogmem/queue/openclaw-remember.jsonl` and starts a singleton drainer, so Telegram or gateway responses are not blocked by embeddings, SQLite writes, or slow local models. Plugin 0.7.0 acquires the queue lock before opening Cogmem, recovers stale lock directories and stale `.processing` queue files older than `rememberDrainTimeoutMs`, writes `owner.json` lock metadata, and processes bounded batches controlled by `rememberDrainBatchSize` (default `20`). If a drain fails, the job is retried and then moved to a dead-letter file instead of being silently discarded.
|
|
353
358
|
|
|
354
359
|
When automatic memory recording looks stuck, do not delete queue files first. Diagnose the plugin and locks:
|
|
355
360
|
|