clawmem 0.5.0 → 0.6.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/AGENTS.md CHANGED
@@ -250,7 +250,7 @@ ClawMem hooks handle ~90% of retrieval automatically. Agent-initiated MCP calls
250
250
  | `postcompact-inject` | SessionStart (compact) | 1200 tokens | re-injects authoritative context after compaction: precompact state (600) + recent decisions (400) + antipatterns (150) + vault context (200) → `<vault-postcompact>` |
251
251
  | `curator-nudge` | SessionStart | 200 tokens | surfaces curator report actions, nudges when report is stale (>7 days) |
252
252
  | `precompact-extract` | PreCompact | — | extracts decisions, file paths, open questions → writes `precompact-state.md` to auto-memory. Query-aware decision ranking. Reindexes auto-memory collection. |
253
- | `decision-extractor` | Stop | — | LLM extracts observations → `_clawmem/agent/observations/`, infers causal links, detects contradictions with prior decisions |
253
+ | `decision-extractor` | Stop | — | LLM extracts observations → `_clawmem/agent/observations/`, infers causal links, detects contradictions, extracts SPO triples from decision/preference/milestone/problem facts. Background consolidation worker synthesizes deductive observations from related facts (Phase 3, every ~15 min). |
254
254
  | `handoff-generator` | Stop | — | LLM summarizes session → `_clawmem/agent/handoffs/` |
255
255
  | `feedback-loop` | Stop | — | tracks referenced notes → boosts confidence, records usage relations + co-activations between co-referenced docs, tracks utility signals (surfaced vs referenced ratio for lifecycle automation) |
256
256
 
@@ -307,9 +307,15 @@ All other retrieval is handled by Tier 2 hooks. Do NOT call MCP tools speculativ
307
307
  4. Chain tracing → find_causal_links(docid, direction="both", depth=5)
308
308
  Traverses causal edges between _clawmem/agent/observations/ docs (from decision-extractor).
309
309
 
310
- 5. Memory debuggingmemory_evolution_status(docid)
310
+ 5. Entity factskg_query(entity, as_of?, direction?)
311
+ Structured SPO triples with temporal validity. Different from intent_search:
312
+ - kg_query: "what does ClawMem relate to?" → returns structured facts (subject-predicate-object)
313
+ - intent_search: "why did we choose ClawMem?" → returns documents with causal reasoning
314
+ Use kg_query for entity lookup, intent_search for causal chains.
311
315
 
312
- 6. Temporal contexttimeline(docid, before=5, after=5, same_collection=false)
316
+ 6. Memory debuggingmemory_evolution_status(docid)
317
+
318
+ 7. Temporal context → timeline(docid, before=5, after=5, same_collection=false)
313
319
  Shows what was created/modified before and after a document.
314
320
  Use after search to understand chronological neighborhood.
315
321
  ```
@@ -327,6 +333,9 @@ All other retrieval is handled by Tier 2 hooks. Do NOT call MCP tools speculativ
327
333
  - `timeline(docid, before=5, after=5, same_collection=false)` — temporal neighborhood around a document. Progressive disclosure: search → timeline → get. Supports same-collection scoping and session correlation.
328
334
  - `list_vaults()` — show configured vault names and paths. Empty in single-vault mode (default).
329
335
  - `vault_sync(vault, content_root, pattern?, collection_name?)` — index markdown from a directory into a named vault. Restricted-path validation rejects sensitive directories (`/etc/`, `/root/`, `.ssh`, `.env`, `credentials`, etc.).
336
+ - `kg_query(entity, as_of?, direction?)` — query the SPO knowledge graph for an entity's relationships. Returns temporal triples with validity windows. USE THIS for "what does X relate to?", "what was true about X in January?". Uses entity resolution for lookup.
337
+ - `diary_write(entry, topic?, agent?)` — write a diary entry. USE PROACTIVELY in non-hooked environments (Hermes, Gemini, plain MCP) for recording important events and decisions. Do NOT use in Claude Code (hooks handle this automatically).
338
+ - `diary_read(last_n?, agent?)` — read recent diary entries.
330
339
 
331
340
  ### Multi-Vault
332
341
 
@@ -355,6 +364,8 @@ Pin, snooze, and forget are **manual MCP tools** — not automated. The agent sh
355
364
  - Do NOT forget memories to "clean up" — let confidence decay and contradiction detection handle it naturally.
356
365
  - Do NOT run `build_graphs` after every reindex — A-MEM creates per-doc links automatically. Only after bulk ingestion or when `intent_search` returns weak graph results.
357
366
  - Do NOT run `clawmem mine` autonomously — it is a bulk ingestion command (same category as `update`/`reindex`). Suggest it to the user when they mention old conversation exports, but let them run it. Bulk import has disk/embedding cost implications that need user consent.
367
+ - Do NOT use `diary_write` in Claude Code — hooks (`decision-extractor`, `handoff-generator`) capture this automatically. Diary is for non-hooked environments only (Hermes, Gemini, plain MCP clients).
368
+ - Do NOT use `kg_query` for causal "why" questions — use `intent_search` or `memory_retrieve`. `kg_query` returns structured entity facts (SPO triples), not reasoning chains.
358
369
 
359
370
  ## Tool Selection (one-liner)
360
371
 
@@ -436,7 +447,7 @@ compositeScore = (0.10 × searchScore + 0.70 × recencyScore + 0.20 × confidenc
436
447
 
437
448
  | Content Type | Half-Life | Effect |
438
449
  |--------------|-----------|--------|
439
- | decision, preference, hub | ∞ | Never decay |
450
+ | decision, deductive, preference, hub | ∞ | Never decay |
440
451
  | antipattern | ∞ | Never decay — accumulated negative patterns persist |
441
452
  | project | 120 days | Slow decay |
442
453
  | research | 90 days | Moderate decay |
@@ -445,7 +456,7 @@ compositeScore = (0.10 × searchScore + 0.70 × recencyScore + 0.20 × confidenc
445
456
  | handoff | 30 days | Fast — recent matters most |
446
457
 
447
458
  Half-lives extend up to 3× for frequently-accessed memories (access reinforcement decays over 90 days).
448
- Attention decay: non-durable types (handoff, progress, conversation, note, project) lose 5% confidence per week without access. Decision/preference/hub/research/antipattern are exempt.
459
+ Attention decay: non-durable types (handoff, progress, conversation, note, project) lose 5% confidence per week without access. Decision/deductive/preference/hub/research/antipattern are exempt.
449
460
 
450
461
  ## Indexing & Graph Building
451
462
 
@@ -488,6 +499,7 @@ The `memory_relations` table is populated by multiple independent sources:
488
499
  | `buildSemanticGraph()` | semantic | `build_graphs` MCP tool (manual) | Pure cosine similarity. PK collision: `INSERT OR IGNORE` means A-MEM semantic edges take precedence if they exist first. |
489
500
  | Entity co-occurrence graph | entity | A-MEM enrichment (indexing) | LLM entity extraction → quality filters (title/length/blocklist/location validation) → type-agnostic canonical resolution within compatibility buckets (person, org, location, tech=project/service/tool/concept) → `entity_mentions` + `entity_cooccurrences` tables. Entity edges use IDF-based specificity scoring. Feeds ENTITY intent queries and MPFP `[entity, semantic]` patterns. |
490
501
  | `consolidated_observations` | supporting | Consolidation worker (background) | 3-tier consolidation: facts → observations → mental models. Observations track `proof_count`, `trend` (STABLE/STRENGTHENING/WEAKENING/STALE), and source links. |
502
+ | Deductive synthesis | supporting | Consolidation worker Phase 3 (background, every ~15 min) | Combines 2-3 related recent observations (decision/preference/milestone/problem, last 7 days) into `content_type='deductive'` documents with `source_doc_ids` provenance. First-class searchable docs with ∞ half-life. |
491
503
 
492
504
  **Edge collision:** Both `generateMemoryLinks()` and `buildSemanticGraph()` insert `relation_type='semantic'`. PK is `(source_id, target_id, relation_type)` — first writer wins.
493
505
 
@@ -564,6 +576,12 @@ Symptom: "Local model download blocked" error
564
576
  → llama-server endpoint unreachable while CLAWMEM_NO_LOCAL_MODELS=true.
565
577
  → Fix: Start the llama-server instance. Or set CLAWMEM_NO_LOCAL_MODELS=false for in-process fallback.
566
578
 
579
+ Symptom: "[generate] Remote LLM in cooldown, falling back to in-process generation"
580
+ → Remote LLM server had a transport failure (ECONNREFUSED/ETIMEDOUT). ClawMem set a 60s cooldown
581
+ and is using local node-llama-cpp. Remote will be retried after cooldown expires.
582
+ → Not an error if you expect local fallback. If you want remote only: ensure llama-server is running,
583
+ or set CLAWMEM_NO_LOCAL_MODELS=true to get null instead of slow local inference.
584
+
567
585
  Symptom: Query expansion always fails / returns garbage
568
586
  → On CPU-only systems, in-process inference is significantly slower and less reliable. Systems with GPU acceleration (Metal/Vulkan) handle these models well in-process.
569
587
  → Fix: Run llama-server on a GPU. Even a low-end NVIDIA card handles 1.7B models.
package/CLAUDE.md CHANGED
@@ -250,7 +250,7 @@ ClawMem hooks handle ~90% of retrieval automatically. Agent-initiated MCP calls
250
250
  | `postcompact-inject` | SessionStart (compact) | 1200 tokens | re-injects authoritative context after compaction: precompact state (600) + recent decisions (400) + antipatterns (150) + vault context (200) → `<vault-postcompact>` |
251
251
  | `curator-nudge` | SessionStart | 200 tokens | surfaces curator report actions, nudges when report is stale (>7 days) |
252
252
  | `precompact-extract` | PreCompact | — | extracts decisions, file paths, open questions → writes `precompact-state.md` to auto-memory. Query-aware decision ranking. Reindexes auto-memory collection. |
253
- | `decision-extractor` | Stop | — | LLM extracts observations → `_clawmem/agent/observations/`, infers causal links, detects contradictions with prior decisions |
253
+ | `decision-extractor` | Stop | — | LLM extracts observations → `_clawmem/agent/observations/`, infers causal links, detects contradictions, extracts SPO triples from decision/preference/milestone/problem facts. Background consolidation worker synthesizes deductive observations from related facts (Phase 3, every ~15 min). |
254
254
  | `handoff-generator` | Stop | — | LLM summarizes session → `_clawmem/agent/handoffs/` |
255
255
  | `feedback-loop` | Stop | — | tracks referenced notes → boosts confidence, records usage relations + co-activations between co-referenced docs, tracks utility signals (surfaced vs referenced ratio for lifecycle automation) |
256
256
 
@@ -307,9 +307,15 @@ All other retrieval is handled by Tier 2 hooks. Do NOT call MCP tools speculativ
307
307
  4. Chain tracing → find_causal_links(docid, direction="both", depth=5)
308
308
  Traverses causal edges between _clawmem/agent/observations/ docs (from decision-extractor).
309
309
 
310
- 5. Memory debuggingmemory_evolution_status(docid)
310
+ 5. Entity factskg_query(entity, as_of?, direction?)
311
+ Structured SPO triples with temporal validity. Different from intent_search:
312
+ - kg_query: "what does ClawMem relate to?" → returns structured facts (subject-predicate-object)
313
+ - intent_search: "why did we choose ClawMem?" → returns documents with causal reasoning
314
+ Use kg_query for entity lookup, intent_search for causal chains.
311
315
 
312
- 6. Temporal contexttimeline(docid, before=5, after=5, same_collection=false)
316
+ 6. Memory debuggingmemory_evolution_status(docid)
317
+
318
+ 7. Temporal context → timeline(docid, before=5, after=5, same_collection=false)
313
319
  Shows what was created/modified before and after a document.
314
320
  Use after search to understand chronological neighborhood.
315
321
  ```
@@ -327,6 +333,9 @@ All other retrieval is handled by Tier 2 hooks. Do NOT call MCP tools speculativ
327
333
  - `timeline(docid, before=5, after=5, same_collection=false)` — temporal neighborhood around a document. Progressive disclosure: search → timeline → get. Supports same-collection scoping and session correlation.
328
334
  - `list_vaults()` — show configured vault names and paths. Empty in single-vault mode (default).
329
335
  - `vault_sync(vault, content_root, pattern?, collection_name?)` — index markdown from a directory into a named vault. Restricted-path validation rejects sensitive directories (`/etc/`, `/root/`, `.ssh`, `.env`, `credentials`, etc.).
336
+ - `kg_query(entity, as_of?, direction?)` — query the SPO knowledge graph for an entity's relationships. Returns temporal triples with validity windows. USE THIS for "what does X relate to?", "what was true about X in January?". Uses entity resolution for lookup.
337
+ - `diary_write(entry, topic?, agent?)` — write a diary entry. USE PROACTIVELY in non-hooked environments (Hermes, Gemini, plain MCP) for recording important events and decisions. Do NOT use in Claude Code (hooks handle this automatically).
338
+ - `diary_read(last_n?, agent?)` — read recent diary entries.
330
339
 
331
340
  ### Multi-Vault
332
341
 
@@ -355,6 +364,8 @@ Pin, snooze, and forget are **manual MCP tools** — not automated. The agent sh
355
364
  - Do NOT forget memories to "clean up" — let confidence decay and contradiction detection handle it naturally.
356
365
  - Do NOT run `build_graphs` after every reindex — A-MEM creates per-doc links automatically. Only after bulk ingestion or when `intent_search` returns weak graph results.
357
366
  - Do NOT run `clawmem mine` autonomously — it is a bulk ingestion command (same category as `update`/`reindex`). Suggest it to the user when they mention old conversation exports, but let them run it. Bulk import has disk/embedding cost implications that need user consent.
367
+ - Do NOT use `diary_write` in Claude Code — hooks (`decision-extractor`, `handoff-generator`) capture this automatically. Diary is for non-hooked environments only (Hermes, Gemini, plain MCP clients).
368
+ - Do NOT use `kg_query` for causal "why" questions — use `intent_search` or `memory_retrieve`. `kg_query` returns structured entity facts (SPO triples), not reasoning chains.
358
369
 
359
370
  ## Tool Selection (one-liner)
360
371
 
@@ -436,7 +447,7 @@ compositeScore = (0.10 × searchScore + 0.70 × recencyScore + 0.20 × confidenc
436
447
 
437
448
  | Content Type | Half-Life | Effect |
438
449
  |--------------|-----------|--------|
439
- | decision, preference, hub | ∞ | Never decay |
450
+ | decision, deductive, preference, hub | ∞ | Never decay |
440
451
  | antipattern | ∞ | Never decay — accumulated negative patterns persist |
441
452
  | project | 120 days | Slow decay |
442
453
  | research | 90 days | Moderate decay |
@@ -445,7 +456,7 @@ compositeScore = (0.10 × searchScore + 0.70 × recencyScore + 0.20 × confidenc
445
456
  | handoff | 30 days | Fast — recent matters most |
446
457
 
447
458
  Half-lives extend up to 3× for frequently-accessed memories (access reinforcement decays over 90 days).
448
- Attention decay: non-durable types (handoff, progress, conversation, note, project) lose 5% confidence per week without access. Decision/preference/hub/research/antipattern are exempt.
459
+ Attention decay: non-durable types (handoff, progress, conversation, note, project) lose 5% confidence per week without access. Decision/deductive/preference/hub/research/antipattern are exempt.
449
460
 
450
461
  ## Indexing & Graph Building
451
462
 
@@ -488,6 +499,7 @@ The `memory_relations` table is populated by multiple independent sources:
488
499
  | `buildSemanticGraph()` | semantic | `build_graphs` MCP tool (manual) | Pure cosine similarity. PK collision: `INSERT OR IGNORE` means A-MEM semantic edges take precedence if they exist first. |
489
500
  | Entity co-occurrence graph | entity | A-MEM enrichment (indexing) | LLM entity extraction → quality filters (title/length/blocklist/location validation) → type-agnostic canonical resolution within compatibility buckets (person, org, location, tech=project/service/tool/concept) → `entity_mentions` + `entity_cooccurrences` tables. Entity edges use IDF-based specificity scoring. Feeds ENTITY intent queries and MPFP `[entity, semantic]` patterns. |
490
501
  | `consolidated_observations` | supporting | Consolidation worker (background) | 3-tier consolidation: facts → observations → mental models. Observations track `proof_count`, `trend` (STABLE/STRENGTHENING/WEAKENING/STALE), and source links. |
502
+ | Deductive synthesis | supporting | Consolidation worker Phase 3 (background, every ~15 min) | Combines 2-3 related recent observations (decision/preference/milestone/problem, last 7 days) into `content_type='deductive'` documents with `source_doc_ids` provenance. First-class searchable docs with ∞ half-life. |
491
503
 
492
504
  **Edge collision:** Both `generateMemoryLinks()` and `buildSemanticGraph()` insert `relation_type='semantic'`. PK is `(source_id, target_id, relation_type)` — first writer wins.
493
505
 
@@ -564,6 +576,12 @@ Symptom: "Local model download blocked" error
564
576
  → llama-server endpoint unreachable while CLAWMEM_NO_LOCAL_MODELS=true.
565
577
  → Fix: Start the llama-server instance. Or set CLAWMEM_NO_LOCAL_MODELS=false for in-process fallback.
566
578
 
579
+ Symptom: "[generate] Remote LLM in cooldown, falling back to in-process generation"
580
+ → Remote LLM server had a transport failure (ECONNREFUSED/ETIMEDOUT). ClawMem set a 60s cooldown
581
+ and is using local node-llama-cpp. Remote will be retried after cooldown expires.
582
+ → Not an error if you expect local fallback. If you want remote only: ensure llama-server is running,
583
+ or set CLAWMEM_NO_LOCAL_MODELS=true to get null instead of slow local inference.
584
+
567
585
  Symptom: Query expansion always fails / returns garbage
568
586
  → On CPU-only systems, in-process inference is significantly slower and less reliable. Systems with GPU acceleration (Metal/Vulkan) handle these models well in-process.
569
587
  → Fix: Run llama-server on a GPU. Even a low-end NVIDIA card handles 1.7B models.
package/README.md CHANGED
@@ -176,7 +176,7 @@ ClawMem integrates via hooks (`settings.json`) and an MCP stdio server. Hooks ha
176
176
 
177
177
  ```bash
178
178
  clawmem setup hooks # Install lifecycle hooks (SessionStart, UserPromptSubmit, Stop, PreCompact)
179
- clawmem setup mcp # Register MCP server in ~/.claude.json (28 tools)
179
+ clawmem setup mcp # Register MCP server in ~/.claude.json (31 tools)
180
180
  ```
181
181
 
182
182
  **Automatic (90%):** `context-surfacing` injects relevant memory on every prompt. `postcompact-inject` re-injects state after compaction. `decision-extractor`, `handoff-generator`, `feedback-loop` capture session state on stop.
@@ -203,7 +203,7 @@ Disable OpenClaw's native memory and `memory-lancedb` auto-recall/capture to avo
203
203
  openclaw config set agents.defaults.memorySearch.extraPaths "[]"
204
204
  ```
205
205
 
206
- **Alternative:** OpenClaw agents can also use ClawMem's MCP server directly (`clawmem setup mcp`), with or without hooks. This gives full access to all 28 MCP tools but bypasses OpenClaw's ContextEngine lifecycle, so you lose token budget awareness, native compaction orchestration, and the `afterTurn()` message pipeline. The ContextEngine plugin is recommended for new OpenClaw setups; MCP is available as an additional or standalone integration.
206
+ **Alternative:** OpenClaw agents can also use ClawMem's MCP server directly (`clawmem setup mcp`), with or without hooks. This gives full access to all 31 MCP tools but bypasses OpenClaw's ContextEngine lifecycle, so you lose token budget awareness, native compaction orchestration, and the `afterTurn()` message pipeline. The ContextEngine plugin is recommended for new OpenClaw setups; MCP is available as an additional or standalone integration.
207
207
 
208
208
  #### Hermes Agent
209
209
 
@@ -310,9 +310,9 @@ ClawMem uses three `llama-server` (llama.cpp) instances for neural inference. Al
310
310
  | LLM | 8089 | [qmd-query-expansion-1.7B-q4_k_m](https://huggingface.co/tobil/qmd-query-expansion-1.7B-gguf) | ~2.2GB | Intent classification, query expansion, A-MEM |
311
311
  | Reranker | 8090 | [qwen3-reranker-0.6B-Q8_0](https://huggingface.co/ggml-org/Qwen3-Reranker-0.6B-Q8_0-GGUF) | ~1.3GB | Cross-encoder reranking (query, intent_search) |
312
312
 
313
- The `bin/clawmem` wrapper defaults to `localhost:8088/8089/8090`. If a server is unreachable, ClawMem silently falls back to in-process inference via `node-llama-cpp` (auto-downloads the QMD native models on first use, uses Metal/Vulkan/CPU depending on hardware). With GPU acceleration this is fast; on CPU-only it is significantly slower. ClawMem always works either way, but **if you're running dedicated GPU servers, use [systemd services](docs/guides/systemd-services.md) to ensure they stay up** — otherwise a crashed server silently degrades without warning.
313
+ The `bin/clawmem` wrapper defaults to `localhost:8088/8089/8090`. If a server is unreachable (transport error like ECONNREFUSED/ETIMEDOUT), ClawMem sets a 60-second cooldown and falls back to in-process inference via `node-llama-cpp` (auto-downloads the QMD native models on first use, uses Metal/Vulkan/CPU depending on hardware). HTTP errors (400/500) and user-cancelled requests do not trigger cooldown — the remote server is retried normally on the next call. With GPU acceleration the fallback is fast; on CPU-only it is significantly slower. ClawMem always works either way, but **if you're running dedicated GPU servers, use [systemd services](docs/guides/systemd-services.md) to ensure they stay up**.
314
314
 
315
- To prevent silent fallback and fail fast instead, set `CLAWMEM_NO_LOCAL_MODELS=true`.
315
+ To prevent fallback and fail fast instead, set `CLAWMEM_NO_LOCAL_MODELS=true`.
316
316
 
317
317
  #### Remote GPU (optional)
318
318
 
@@ -473,7 +473,7 @@ llama-server -m Qwen3-Reranker-0.6B-Q8_0.gguf \
473
473
 
474
474
  ### MCP Server
475
475
 
476
- ClawMem exposes 28 MCP tools via the [Model Context Protocol](https://modelcontextprotocol.io) and an optional HTTP REST API. Any MCP-compatible client or HTTP client can use it.
476
+ ClawMem exposes 31 MCP tools via the [Model Context Protocol](https://modelcontextprotocol.io) and an optional HTTP REST API. Any MCP-compatible client or HTTP client can use it.
477
477
 
478
478
  **Claude Code (automatic):**
479
479
 
@@ -678,7 +678,7 @@ clawmem doctor Full health check
678
678
  clawmem status Quick index status
679
679
  ```
680
680
 
681
- ## MCP Tools (28)
681
+ ## MCP Tools (31)
682
682
 
683
683
  Registered by `clawmem setup mcp`. Available to any MCP-compatible client.
684
684
 
@@ -715,6 +715,7 @@ Registered by `clawmem setup mcp`. Available to any MCP-compatible client.
715
715
  |---|---|
716
716
  | `build_graphs` | Build temporal and/or semantic graphs from document corpus |
717
717
  | `find_causal_links` | Trace decision chains: "what led to X", "how we got from A to B". Follow up `intent_search` with this tool on a top result to walk the full causal chain. Traverses causes / caused_by / both up to N hops with depth-annotated reasoning. |
718
+ | `kg_query` | Query the SPO knowledge graph: "what does X relate to?", "what was true about X when?". Returns temporal entity-relationship triples with validity windows. Uses entity resolution for lookup. |
718
719
  | `memory_evolution_status` | Show how a document's A-MEM metadata evolved over time |
719
720
  | `timeline` | Show the temporal neighborhood around a document — what was created/modified before and after it. Progressive disclosure: search → timeline (context) → get (full content). Supports same-collection scoping and session correlation. |
720
721
 
@@ -731,6 +732,13 @@ Registered by `clawmem setup mcp`. Available to any MCP-compatible client.
731
732
  | `list_vaults` | Show configured vault names and paths. Empty in single-vault mode. |
732
733
  | `vault_sync` | Index markdown from a directory into a named vault. Restricted-path validation rejects sensitive directories. |
733
734
 
735
+ ### Agent Diary
736
+
737
+ | Tool | Description |
738
+ |---|---|
739
+ | `diary_write` | Write a diary entry. Use for recording important events, decisions, or observations in environments without hook support. Stored as searchable memories. |
740
+ | `diary_read` | Read recent diary entries. Filter by agent name. |
741
+
734
742
  ### Memory Management & Lifecycle
735
743
 
736
744
  | Tool | Description |
@@ -815,6 +823,7 @@ For WHY and ENTITY queries, the search pipeline expands results through the memo
815
823
  | Type | Half-life | Baseline | Notes |
816
824
  |---|---|---|---|
817
825
  | `decision` | ∞ | 0.85 | Never decays |
826
+ | `deductive` | ∞ | 0.85 | Never decays — cross-session derived insights with source provenance |
818
827
  | `preference` | ∞ | 0.80 | Never decays — user preferences are durable facts |
819
828
  | `hub` | ∞ | 0.80 | Never decays |
820
829
  | `antipattern` | ∞ | 0.75 | Never decays — accumulated negative patterns persist |
@@ -827,7 +836,7 @@ For WHY and ENTITY queries, the search pipeline expands results through the memo
827
836
  | `progress` | 45 days | 0.50 | |
828
837
  | `note` | 60 days | 0.50 | Default |
829
838
 
830
- Content types are inferred from frontmatter or file path patterns. Half-lives extend up to 3× for frequently-accessed memories (access reinforcement, decays over 90 days). Non-durable types (handoff, progress, conversation, note, project) lose 5% confidence per week without access (attention decay). Decision/preference/hub/research/antipattern are exempt.
839
+ Content types are inferred from frontmatter or file path patterns. Half-lives extend up to 3× for frequently-accessed memories (access reinforcement, decays over 90 days). Non-durable types (handoff, progress, conversation, note, project) lose 5% confidence per week without access (attention decay). Decision/deductive/preference/hub/research/antipattern are exempt.
831
840
 
832
841
  **Quality scoring:** Each document gets a `quality_score` (0.0–1.0) computed during indexing based on length, structure (headings, lists), decision/correction keywords, and frontmatter richness. Applied as `qualityMultiplier = 0.7 + 0.6 × qualityScore` (range: 0.7× penalty to 1.3× boost).
833
842
 
@@ -1111,7 +1120,9 @@ Built on the shoulders of:
1111
1120
  - [Engram](https://github.com/Gentleman-Programming/engram) — observation dedup window, topic-key upsert pattern, temporal timeline navigation, duplicate metadata scoring signals
1112
1121
  - [Hermes Agent](https://github.com/NousResearch/hermes-agent) — MemoryProvider plugin integration, memory nudge system (periodic lifecycle tool prompting)
1113
1122
  - [Hindsight](https://github.com/vectorize-io/hindsight) — entity resolution, MPFP graph traversal, temporal extraction, 3-tier consolidation, observation invalidation, 4-way parallel retrieval
1123
+ - [Honcho](https://github.com/plastic-labs/honcho) — deductive observation synthesis patterns, surprisal-based anomaly scoring concept, embed-state self-healing, retrieval separation (raw vs derived)
1114
1124
  - [MAGMA](https://arxiv.org/abs/2501.13956) — multi-graph memory agent
1125
+ - [MemPalace](https://github.com/milla-jovovich/mempalace) — conversation import patterns, broadened observation taxonomy (preference/milestone/problem), session-bootstrap synthesis
1115
1126
  - [memory-lancedb-pro](https://github.com/CortexReach/memory-lancedb-pro) — retrieval gate, length normalization, MMR diversity, access reinforcement algorithms
1116
1127
  - [OpenViking](https://github.com/volcengine/OpenViking) — query decomposition patterns, collection-scoped retrieval, transaction-safe indexing
1117
1128
  - [QMD](https://github.com/tobi/qmd) — search backend (BM25 + vectors + RRF + reranking)
package/SKILL.md CHANGED
@@ -242,9 +242,15 @@ Once escalated, route by query type:
242
242
  4. Chain tracing -> find_causal_links(docid, direction="both", depth=5)
243
243
  Traverses causal edges between _clawmem/agent/observations/ docs.
244
244
 
245
- 5. Memory debugging -> memory_evolution_status(docid)
245
+ 5. Entity facts -> kg_query(entity, as_of?, direction?)
246
+ Structured SPO triples with temporal validity. Different from intent_search:
247
+ - kg_query: "what does ClawMem relate to?" -> returns structured facts (subject-predicate-object)
248
+ - intent_search: "why did we choose ClawMem?" -> returns documents with causal reasoning
249
+ Use kg_query for entity lookup, intent_search for causal chains.
246
250
 
247
- 6. Temporal context -> timeline(docid, before=5, after=5, same_collection=false)
251
+ 6. Memory debugging -> memory_evolution_status(docid)
252
+
253
+ 7. Temporal context -> timeline(docid, before=5, after=5, same_collection=false)
248
254
  Shows what was created/modified before and after a document.
249
255
  Use after search to understand chronological neighborhood.
250
256
  ```
@@ -277,6 +283,9 @@ Once escalated, route by query type:
277
283
  | `timeline` | Temporal neighborhood around a document — what was modified before/after. Progressive disclosure: search → timeline → get. Supports same-collection scoping and session correlation. |
278
284
  | `list_vaults` | Show configured vault names and paths. Empty in single-vault mode. |
279
285
  | `vault_sync` | Index markdown from a directory into a named vault. Restricted-path validation rejects sensitive directories. |
286
+ | `kg_query` | Query SPO knowledge graph for entity relationships with temporal validity. Uses entity resolution. |
287
+ | `diary_write` | Write diary entry. Use proactively in non-hooked environments. Do NOT use in Claude Code. |
288
+ | `diary_read` | Read recent diary entries. Filter by agent name. |
280
289
  | `lifecycle_status` | Document lifecycle statistics: active, archived, forgotten, pinned, snoozed counts and policy summary. |
281
290
  | `lifecycle_sweep` | Run lifecycle policies: archive stale docs. Defaults to dry_run (preview only). |
282
291
  | `lifecycle_restore` | Restore auto-archived documents. Filter by query, collection, or all. Does NOT restore manually forgotten docs. |
@@ -442,7 +451,7 @@ compositeScore = (0.10 x searchScore + 0.70 x recencyScore + 0.20 x confidenceSc
442
451
 
443
452
  | Content Type | Half-Life | Effect |
444
453
  |--------------|-----------|--------|
445
- | decision, preference, hub | infinity | Never decay |
454
+ | decision, deductive, preference, hub | infinity | Never decay |
446
455
  | antipattern | infinity | Never decay — accumulated negative patterns persist |
447
456
  | project | 120 days | Slow decay |
448
457
  | research | 90 days | Moderate decay |
@@ -567,6 +576,8 @@ When `decision-extractor` detects a new decision contradicting an old one, the o
567
576
  - Do NOT forget memories to "clean up" — let confidence decay and contradiction detection handle it.
568
577
  - Do NOT run `build_graphs` after every reindex — A-MEM creates per-doc links automatically.
569
578
  - Do NOT run `clawmem mine` autonomously — it is a bulk ingestion command. Suggest it to the user when they mention old conversation exports, but let them run it.
579
+ - Do NOT use `diary_write` in Claude Code — hooks capture this automatically. Diary is for non-hooked environments only (Hermes, Gemini, plain MCP).
580
+ - Do NOT use `kg_query` for causal "why" questions — use `intent_search` or `memory_retrieve`. `kg_query` returns structured entity facts (SPO triples), not reasoning chains.
570
581
 
571
582
  ---
572
583
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawmem",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "On-device context engine and memory for AI agents. Claude Code and OpenClaw. Hooks + MCP server + hybrid RAG search.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/clawmem.ts CHANGED
@@ -410,6 +410,9 @@ async function cmdEmbed(args: string[]) {
410
410
 
411
411
  const fragments = splitDocument(body, frontmatter);
412
412
  const docStart = Date.now();
413
+ const prevTotalFragments = totalFragments;
414
+ const prevFailedFragments = failedFragments;
415
+ let seq0Succeeded = false;
413
416
  console.error(` [${docIdx + 1}/${hashes.length}] ${basename(path)} (${fragments.length} frags, ${body.length} chars)`);
414
417
 
415
418
  if (isCloudEmbed) {
@@ -463,6 +466,7 @@ async function cmdEmbed(args: string[]) {
463
466
  result.model, new Date().toISOString(), frag.type, frag.label ?? undefined, canId
464
467
  );
465
468
  totalFragments++;
469
+ if (seq === 0) seq0Succeeded = true;
466
470
  } else {
467
471
  failedFragments++;
468
472
  }
@@ -491,6 +495,7 @@ async function cmdEmbed(args: string[]) {
491
495
  result.model, new Date().toISOString(), frag.type, frag.label ?? undefined, canId
492
496
  );
493
497
  totalFragments++;
498
+ if (seq === 0) seq0Succeeded = true;
494
499
  if (seq === 0 || (seq + 1) % 5 === 0 || seq === fragments.length - 1) {
495
500
  console.error(` frag ${seq + 1}/${fragments.length} (${frag.type}) ${fragMs}ms [${text.length} chars]`);
496
501
  }
@@ -505,6 +510,18 @@ async function cmdEmbed(args: string[]) {
505
510
  }
506
511
  }
507
512
 
513
+ // Track embed state per document — seq=0 (primary) must succeed for synced status
514
+ const docFragsOk = totalFragments - prevTotalFragments;
515
+ const docFragsFail = failedFragments - prevFailedFragments;
516
+ if (seq0Succeeded) {
517
+ s.markEmbedSynced(hash);
518
+ } else if (docFragsOk === 0 && docFragsFail > 0) {
519
+ s.markEmbedFailed(hash, "all fragments failed");
520
+ } else {
521
+ // seq=0 failed but some later fragments succeeded — mark failed so seq=0 gets retried
522
+ s.markEmbedFailed(hash, "primary fragment (seq=0) failed");
523
+ }
524
+
508
525
  embedded++;
509
526
  const docMs = Date.now() - docStart;
510
527
  const elapsed = ((Date.now() - batchStart) / 1000).toFixed(0);
@@ -1868,6 +1885,9 @@ async function main() {
1868
1885
  case "curate":
1869
1886
  await cmdCurate(subArgs);
1870
1887
  break;
1888
+ case "diary":
1889
+ await cmdDiary(subArgs);
1890
+ break;
1871
1891
  case "help":
1872
1892
  case "--help":
1873
1893
  case "-h":
@@ -2207,6 +2227,99 @@ interface CuratorReport {
2207
2227
  actions: string[];
2208
2228
  }
2209
2229
 
2230
+ async function cmdDiary(args: string[]) {
2231
+ const subCmd = args[0];
2232
+ const subArgs = args.slice(1);
2233
+
2234
+ switch (subCmd) {
2235
+ case "write": {
2236
+ const { values, positionals } = parseArgs({
2237
+ args: subArgs,
2238
+ options: {
2239
+ topic: { type: "string", short: "t", default: "general" },
2240
+ agent: { type: "string", short: "a", default: "user" },
2241
+ },
2242
+ allowPositionals: true,
2243
+ });
2244
+
2245
+ const entry = positionals.join(" ");
2246
+ if (!entry) die("Usage: clawmem diary write <entry text> [-t topic] [-a agent-name]");
2247
+
2248
+ const s = getStore();
2249
+ const now = new Date();
2250
+ const dateStr = now.toISOString().slice(0, 10);
2251
+ const timeStr = now.toISOString().slice(11, 19).replace(/:/g, "");
2252
+ const ms = String(now.getMilliseconds()).padStart(3, "0");
2253
+ const diaryPath = `diary/${dateStr}-${timeStr}${ms}-${values.topic}.md`;
2254
+ const body = [
2255
+ "---",
2256
+ `title: "${entry.slice(0, 80).replace(/"/g, '\\"')}"`,
2257
+ `content_type: note`,
2258
+ `tags: [diary, ${values.topic}]`,
2259
+ `domain: "${values.agent}"`,
2260
+ "---",
2261
+ "",
2262
+ entry,
2263
+ ].join("\n");
2264
+
2265
+ const result = s.saveMemory({
2266
+ collection: "_clawmem",
2267
+ path: diaryPath,
2268
+ title: entry.slice(0, 80),
2269
+ body,
2270
+ contentType: "note",
2271
+ confidence: 0.7,
2272
+ semanticPayload: `${diaryPath}::${entry}`,
2273
+ });
2274
+
2275
+ console.log(`${c.green}✓${c.reset} Diary entry saved (${result.action}, doc #${result.docId})`);
2276
+ break;
2277
+ }
2278
+
2279
+ case "read": {
2280
+ const { values } = parseArgs({
2281
+ args: subArgs,
2282
+ options: {
2283
+ last: { type: "string", short: "n", default: "10" },
2284
+ agent: { type: "string", short: "a" },
2285
+ },
2286
+ allowPositionals: false,
2287
+ });
2288
+
2289
+ const limit = parseInt(values.last || "10", 10);
2290
+ const s = getStore();
2291
+
2292
+ const rows = s.db.prepare(`
2293
+ SELECT d.id, d.path, d.title, d.modified_at as modifiedAt, d.domain,
2294
+ c.doc as body
2295
+ FROM documents d
2296
+ JOIN content c ON c.hash = d.hash
2297
+ WHERE d.active = 1 AND d.collection = '_clawmem' AND d.path LIKE 'diary/%'
2298
+ ${values.agent ? "AND d.domain = ?" : ""}
2299
+ ORDER BY d.modified_at DESC
2300
+ LIMIT ?
2301
+ `).all(...(values.agent ? [values.agent, limit] : [limit])) as any[];
2302
+
2303
+ if (rows.length === 0) {
2304
+ console.log("No diary entries found.");
2305
+ break;
2306
+ }
2307
+
2308
+ console.log(`${c.bold}Diary${c.reset} (${rows.length} entries)\n`);
2309
+ for (const row of rows) {
2310
+ const agent = row.domain ? ` [${row.domain}]` : "";
2311
+ console.log(`${c.dim}${row.modifiedAt.slice(0, 16)}${c.reset}${agent} ${row.title}`);
2312
+ }
2313
+ break;
2314
+ }
2315
+
2316
+ default:
2317
+ console.log(`Usage:
2318
+ clawmem diary write <entry> [-t topic] [-a agent] Write diary entry
2319
+ clawmem diary read [-n limit] [-a agent] Read recent entries`);
2320
+ }
2321
+ }
2322
+
2210
2323
  async function cmdCurate(_args: string[]) {
2211
2324
  const s = getStore();
2212
2325
  const report: CuratorReport = {
@@ -2422,6 +2535,8 @@ ${c.bold}Intelligence:${c.reset}
2422
2535
  clawmem reflect [days] Cross-session pattern analysis
2423
2536
  clawmem consolidate [--dry-run] Merge duplicate low-confidence docs
2424
2537
  clawmem curate Automated maintenance (health, sweep, dedup, hygiene)
2538
+ clawmem diary write <entry> [-t topic] Write a diary entry (for non-hooked environments)
2539
+ clawmem diary read [-n N] [-a agent] Read recent diary entries
2425
2540
 
2426
2541
  ${c.bold}Integration:${c.reset}
2427
2542
  clawmem mcp Start stdio MCP server