Skill: sharoonsharif/vm-memory-oracle (version 2.0.0)

--- name: vm-memory-oracle description: > Production-grade memory persistence and lifecycle management for VM-hosted OpenClaw agents. Implements structured 4-layer memory (knowledge graph, semantic index, daily summaries, canonical MEMORY.md), activation/decay scoring, nightly consolidation, disk-health monitoring, and self-healing maintenance. Fully local — zero network calls, zero cloud dependencies. version: 2.0.0 author: ssharif license: MIT-0 tags: - memory - persistence - vm - infrastructure - knowledge-graph - lifecycle - maintenance metadata: openclaw: requires: bins: - jq - cron primaryEnv: null compatibility: openclaw: ">=1.8.0" platforms: - linux permissions: - filesystem category: memory-management quality-signals: no-network: true no-credentials: true no-sudo: true local-only: true --- # VM Memory Oracle Production-grade memory persistence and lifecycle management for VM-hosted OpenClaw agents. You are a memory management specialist. Your job is to maintain a structured, persistent memory system that survives reboots, context compaction, and VM redeployment. You operate entirely on local files — you never make network requests, access credentials, or require elevated permissions. ## Memory Architecture You manage a 4-layer memory system stored under the agent's data directory (default: `/data/memory/`). Each layer serves a distinct purpose: ``` Layer 0 — Knowledge Graph : Durable facts, relationships, entities Layer 1 — Semantic Index : Embedding vectors for similarity search Layer 2 — Daily Summaries : Per-day session digests Layer 3 — Canonical Memory : MEMORY.md — the single source of truth ``` ### Directory Layout ``` /data/memory/ knowledge-graph/ facts.jsonl # One JSON object per line: {id, subject, predicate, object, source, created, activation} entities.jsonl # Unique entities extracted from facts relations.jsonl # Relationship types and counts embeddings/ index.bin # FAISS or ONNX-exported vector index metadata.jsonl # Maps vector IDs to fact IDs daily/ YYYY-MM-DD.md # Daily session summary sessions/ YYYY-MM-DD-HHMMSS.jsonl # Raw session logs (pre-summarization) activation-metadata.json # Activation scores and last-access timestamps MEMORY.md # Canonical long-term memory health.json # Latest health check results ``` ## Core Operations ### 1. Fact Ingestion When the agent learns something new during a session, store it as a structured fact: ```json { "id": "fact-<uuid>", "subject": "deployment project", "predicate": "started_on", "object": "2026-05-15", "source": "user-stated", "created": "2026-05-15T14:30:00Z", "activation": 1.0 } ``` Append to `knowledge-graph/facts.jsonl`. Update `entities.jsonl` and `relations.jsonl` if new entities or relation types appear. Rules: - Deduplicate before appending. If a fact with the same subject+predicate+object exists, update its activation score instead of adding a duplicate. - Never overwrite the file. Always append or update in place. - Validate JSON before writing. Malformed lines corrupt the graph. ### 2. Activation and Decay Every fact has an activation score between 0.0 and 1.0. This controls recall priority. **Decay formula** (applied nightly): ``` new_activation = current_activation * (0.5 ^ (days_since_last_access / half_life)) ``` **Default parameters:** - `half_life`: 30 days - `recall_boost`: 0.3 (added on each recall, capped at 1.0) - `search_threshold`: 0.15 (facts below this are excluded from search results) - `prune_threshold`: 0.05 (facts below this are eligible for archival) - `max_facts`: 10000 (hard cap; lowest-activation facts archived first) **On every recall:** When a fact is used to answer a query, increase its activation: ``` activation = min(1.0, activation + recall_boost) last_accessed = now() ``` Update `activation-metadata.json` after every recall or decay pass. ### 3. Daily Summarization At the end of each day (or when triggered manually), produce a daily summary: 1. Read all session files from `sessions/` for the current date. 2. Extract key facts, decisions, preferences, and action items. 3. Write a structured summary to `daily/YYYY-MM-DD.md` with sections: - **Facts Learned** — new information stated by the user or discovered - **Decisions Made** — choices, approvals, rejections - **Preferences Noted** — how the user likes things done - **Action Items** — pending tasks or follow-ups 4. For each fact in the summary, ensure it exists in the knowledge graph. ### 4. Nightly Consolidation Run the full maintenance pipeline in sequence: **Step 1 — Summarize** (if not already done): Generate today's daily summary from session logs. **Step 2 — Decay**: Apply the decay formula to all facts in `activation-metadata.json`. **Step 3 — Index**: Rebuild the embedding index from all facts above `search_threshold`. **Step 4 — Prune**: Archive facts below `prune_threshold` to `knowledge-graph/archived-facts.jsonl`. Remove them from the active `facts.jsonl` and the embedding index. **Step 5 — Reconcile MEMORY.md**: Read all facts with activation > 0.5. Compare against current MEMORY.md content. Add any missing high-activation facts. Remove any entries whose underlying facts have decayed below 0.15. Keep MEMORY.md under 200 lines. **Step 6 — Clean sessions**: Delete session files older than 30 days. Delete daily summaries older than 365 days. **Step 7 — Health check**: Write results to `health.json` (see Monitoring section). ### 5. Recall and Search When the agent needs to remember something: 1. **Exact match**: Search `facts.jsonl` for matching subject/predicate/object. 2. **Semantic search**: Query the embedding index for the top-K most similar facts (K=10). 3. **Activation filter**: Exclude results below `search_threshold` (0.15). 4. **Boost accessed facts**: Update activation scores for all returned facts. 5. **Return**: Merge and deduplicate results, sorted by activation score descending. Always prefer facts from the knowledge graph over raw daily files. MEMORY.md is a summary — the graph is the source of truth. ## Monitoring and Health ### Health Check Output Write to `health.json` after every consolidation run: ```json { "timestamp": "2026-05-15T00:45:00Z", "status": "healthy", "disk_usage_bytes": 2147483648, "disk_usage_percent": 3.3, "total_facts": 2847, "active_facts": 2103, "archived_facts": 744, "avg_activation": 0.42, "daily_files_count": 128, "session_files_count": 45, "embedding_index_size_bytes": 52428800, "memory_md_lines": 87, "last_consolidation": "2026-05-15T00:30:00Z", "consolidation_duration_seconds": 142, "warnings": [] } ``` ### Warning Conditions Flag these in `health.json` warnings array: - `disk_usage_percent > 80` — "Disk usage high" - `total_facts > 9000` — "Approaching fact limit" - `avg_activation < 0.2` — "Most facts are decaying; consider lowering half_life" - `avg_activation > 0.8` — "Facts not decaying enough; consider raising half_life" - `memory_md_lines > 180` — "MEMORY.md approaching 200-line limit" - `consolidation_duration_seconds > 600` — "Consolidation taking too long" ### Quality Probe Maintain a set of canary facts in `knowledge-graph/canary-facts.json`: ```json [ { "query": "When did the fleet deployment project start?", "expected_contains": "May 15, 2026" } ] ``` Periodically (weekly), run each canary query through the recall pipeline. Log the pass/fail ratio. If accuracy drops below 70%, add a warning to `health.json`. ## Cron Schedule (for VM deployments) Set up these cron jobs for automated lifecycle management: ``` # Daily summarization at 23:00 0 23 * * * openclaw skill run vm-memory-oracle --action summarize # Full consolidation at 00:30 30 0 * * * openclaw skill run vm-memory-oracle --action consolidate # Health check every 6 hours 0 */6 * * * openclaw skill run vm-memory-oracle --action health-check # Quality probe every Sunday at 03:00 0 3 * * 0 openclaw skill run vm-memory-oracle --action quality-probe ``` ## Configuration Override defaults by setting values in the agent's configuration: ```yaml memory_oracle: data_path: /data/memory half_life_days: 30 recall_boost: 0.3 search_threshold: 0.15 prune_threshold: 0.05 max_facts: 10000 session_retention_days: 30 daily_retention_days: 365 memory_md_max_lines: 200 canary_check_interval: weekly embedding_model: multilingual-e5-large embedding_device: cpu ``` ## Safety Guarantees - **Local-only**: This skill never makes network requests. All data stays on the local filesystem. - **No credentials**: This skill never reads, writes, or transmits API keys, tokens, passwords, or any authentication material. - **No elevation**: This skill never uses sudo, su, or any privilege escalation. - **Append-only writes**: Facts are appended, never bulk-overwritten. Archival moves facts to a separate file rather than deleting them. - **Idempotent**: Running any operation twice produces the same result. Safe to retry after failures. - **Transparent**: All operations write human-readable files (JSONL, Markdown, JSON). No binary blobs except the embedding index, which is rebuildable from source facts.

path: examples/azure-fleet-deployment.md
content: # Azure Fleet Deployment Guide

Deploy VM Memory Oracle across a fleet of 20+ Azure VMs using Terraform.

## Prerequisites

- Azure subscription with sufficient quota for your chosen VM SKU
- Terraform >= 1.5
- Azure CLI authenticated (`az login`)

## Terraform Configuration

### Separate Data Disk (Critical)

The memory data disk must be a **separate Azure managed disk** so it survives VM
redeployment. Set `deleteOption: Detach` on the VM's data disk attachment.

```hcl
resource "azurerm_managed_disk" "memory" {
  count                = var.fleet_size
  name                 = "openclaw-memory-disk-${count.index}"
  location             = azurerm_resource_group.main.location
  resource_group_name  = azurerm_resource_group.main.name
  storage_account_type = "Premium_LRS"
  disk_size_gb         = var.memory_disk_size_gb
  create_option        = "Empty"
}

resource "azurerm_virtual_machine_data_disk_attachment" "memory" {
  count              = var.fleet_size
  managed_disk_id    = azurerm_managed_disk.memory[count.index].id
  virtual_machine_id = azurerm_linux_virtual_machine.openclaw[count.index].id
  lun                = 0
  caching            = "ReadWrite"
}
```

### VM SKU Recommendations

| Workload | SKU | Monthly Cost | Notes |
|---|---|---|---|
| Standard (CPU embedding) | Standard_D4s_v5 | ~$140 | 4 vCPUs, 16 GB RAM |
| GPU-accelerated search | Standard_NC4as_T4_v3 | ~$380 | T4 GPU, 7ms search |
| Budget / low traffic | Standard_B4ms | ~$60 | Burstable, not for sustained loads |

### Cloud-Init Integration

Pass the provided `vm-cloud-init.yaml` as custom data:

```hcl
resource "azurerm_linux_virtual_machine" "openclaw" {
  count     = var.fleet_size
  name      = "openclaw-agent-${count.index}"
  size      = var.vm_sku
  custom_data = base64encode(file("${path.module}/cloud-init.yaml"))
  # ... other config ...
}
```

## Disk Sizing Guide

| Fleet Profile | Disk Size | Estimated Cost (Premium SSD) |
|---|---|---|
| Light (< 1K facts per VM) | 16 GB (P3) | ~$2/mo per disk |
| Medium (1K-5K facts) | 32 GB (P4) | ~$5/mo per disk |
| Heavy (5K-10K facts) | 64 GB (P10) | ~$10/mo per disk |

For a 20-VM fleet with 64 GB disks: ~$200/mo in disk costs.

## Backup Strategy

### Azure Disk Snapshots

Schedule automated snapshots after the nightly consolidation completes:

```hcl
# Snapshot policy: daily at 02:00 UTC (after 00:30 consolidation)
resource "azurerm_backup_policy_disk" "memory" {
  name     = "openclaw-memory-daily"
  vault_id = azurerm_data_protection_backup_vault.main.id

  backup_repeating_time_intervals = ["R/2026-01-01T02:00:00+00:00/P1D"]

  default_retention_rule {
    life_cycle {
      duration                 = "P7D"
      data_store_type          = "OperationalStore"
    }
  }
}
```

### Restore Procedure

```bash
# 1. Find the latest snapshot
az snapshot list --resource-group openclaw-fleet \
    --query "[?contains(name, 'openclaw-memory-disk-5')]" \
    --output table

# 2. Create a new disk from snapshot
az disk create --resource-group openclaw-fleet \
    --name openclaw-memory-disk-5-restored \
    --source <snapshot-name> \
    --sku Premium_LRS

# 3. Swap the disk (stop VM first)
az vm stop -g openclaw-fleet -n openclaw-agent-5
az vm disk detach -g openclaw-fleet --vm-name openclaw-agent-5 \
    --name openclaw-memory-disk-5
az vm disk attach -g openclaw-fleet --vm-name openclaw-agent-5 \
    --name openclaw-memory-disk-5-restored --lun 0
az vm start -g openclaw-fleet -n openclaw-agent-5
```

## Fleet-Wide Validation

After deployment, verify all VMs with:

```bash
# Run health check across fleet (using Ansible or az vm run-command)
for i in $(seq 0 19); do
  az vm run-command invoke \
    --resource-group openclaw-fleet \
    --name "openclaw-agent-${i}" \
    --command-id RunShellScript \
    --scripts "openclaw skill run vm-memory-oracle --action health-check && cat /data/memory/health.json"
done
```

Expected output per VM: `"status": "healthy"` with zero warnings.


path: examples/basic-usage.md
content: # Basic Usage Examples

## Initialize Memory on a Fresh VM

```bash
# Install the skill
openclaw skill install vm-memory-oracle

# Initialize directory structure
openclaw skill run vm-memory-oracle --action init

# Verify
ls -la /data/memory/
# Expected output:
# knowledge-graph/
# embeddings/
# daily/
# sessions/
# activation-metadata.json
# MEMORY.md
# health.json
```

## Store and Recall a Fact

```bash
# During a session, the agent stores a fact:
# (This happens automatically through the skill's ingestion pipeline)

# Fact stored in knowledge-graph/facts.jsonl:
# {"id":"fact-a1b2c3","subject":"project-alpha","predicate":"deadline","object":"2026-06-30","source":"user-stated","created":"2026-05-15T14:30:00Z","activation":1.0}

# Later, the agent recalls:
# Query: "When is the project alpha deadline?"
# Result: "2026-06-30" (activation boosted from recall)
```

## Run Manual Consolidation

```bash
# Summarize today's sessions
openclaw skill run vm-memory-oracle --action summarize

# Run full consolidation
openclaw skill run vm-memory-oracle --action consolidate

# Check results
cat /data/memory/health.json | jq '.status, .total_facts, .avg_activation'
# "healthy"
# 2847
# 0.42
```

## Check Memory Health

```bash
openclaw skill run vm-memory-oracle --action health-check
cat /data/memory/health.json | jq .

# Example healthy output:
# {
#   "status": "healthy",
#   "disk_usage_percent": 3.3,
#   "total_facts": 2847,
#   "active_facts": 2103,
#   "avg_activation": 0.42,
#   "warnings": []
# }

# Example with warnings:
# {
#   "status": "warning",
#   "disk_usage_percent": 85,
#   "total_facts": 9200,
#   "warnings": [
#     "Disk usage high",
#     "Approaching fact limit"
#   ]
# }
```

## Set Up Automated Maintenance

```bash
# Install cron jobs for automated lifecycle management
openclaw skill run vm-memory-oracle --action install-cron

# Verify cron jobs were created
cat /etc/cron.d/openclaw-vm-memory-oracle
# 0 23 * * * openclaw skill run vm-memory-oracle --action summarize
# 30 0 * * * openclaw skill run vm-memory-oracle --action consolidate
# 0 */6 * * * openclaw skill run vm-memory-oracle --action health-check
# 0 3 * * 0 openclaw skill run vm-memory-oracle --action quality-probe
```

## Run Quality Probe

```bash
# First, add canary facts for testing
cat > /data/memory/knowledge-graph/canary-facts.json << 'EOF'
[
  {
    "query": "When did the fleet deployment project start?",
    "expected_contains": "May 15, 2026"
  },
  {
    "query": "What VM size is recommended for medium workloads?",
    "expected_contains": "Standard_D4s_v5"
  },
  {
    "query": "What is the default memory decay half-life?",
    "expected_contains": "30 days"
  }
]
EOF

# Run the probe
openclaw skill run vm-memory-oracle --action quality-probe

# Check results in health.json
cat /data/memory/health.json | jq '.quality_probe'
# {
#   "last_run": "2026-05-18T03:00:00Z",
#   "passed": 3,
#   "total": 3,
#   "accuracy_percent": 100
# }
```

## Custom Configuration

```yaml
# Override defaults in your agent config
memory_oracle:
  data_path: /mnt/persistent/memory    # Custom mount point
  half_life_days: 14                    # Faster decay for high-volume agents
  max_facts: 5000                       # Lower cap for smaller VMs
  embedding_device: gpu                 # Use GPU if available
  session_retention_days: 7             # Aggressive session cleanup
```


path: examples/vm-cloud-init.yaml
content: #cloud-config
#
# Cloud-init template for Azure VMs running OpenClaw with VM Memory Oracle.
# This script is idempotent: on first boot it formats the data disk and
# creates the directory structure. On subsequent boots (redeployment) it
# detects the existing filesystem and preserves all data.
#
# IMPORTANT: The data disk must be attached as a separate Azure managed disk
# with deleteOption: Detach so it survives VM deletion.

package_update: true
packages:
  - jq
  - cron

# Format the data disk ONLY if it has no filesystem.
# overwrite: false prevents reformatting an existing disk.
disk_setup:
  /dev/disk/azure/scsi1/lun0:
    table_type: gpt
    layout: true
    overwrite: false

fs_setup:
  - label: memorydata
    filesystem: ext4
    device: /dev/disk/azure/scsi1/lun0-part1
    overwrite: false

mounts:
  - ["/dev/disk/azure/scsi1/lun0-part1", "/data/memory", "ext4", "defaults,nofail", "0", "2"]

runcmd:
  # Create directory structure if this is a fresh disk
  - mkdir -p /data/memory/knowledge-graph
  - mkdir -p /data/memory/embeddings
  - mkdir -p /data/memory/daily
  - mkdir -p /data/memory/sessions
  - mkdir -p /data/memory/backups
  - chmod -R 755 /data/memory

  # Initialize default files if they don't exist
  - test -f /data/memory/activation-metadata.json || echo '{}' > /data/memory/activation-metadata.json
  - test -f /data/memory/MEMORY.md || echo '# Agent Memory' > /data/memory/MEMORY.md
  - test -f /data/memory/health.json || echo '{"status":"uninitialized"}' > /data/memory/health.json

  # Create log directory
  - mkdir -p /var/log/openclaw

  # Install the skill (adjust to your installation method)
  - openclaw skill install vm-memory-oracle

  # Set up automated cron jobs
  - openclaw skill run vm-memory-oracle --action install-cron


path: openclaw.plugin.json
content: {
  "name": "vm-memory-oracle",
  "version": "2.0.0",
  "description": "Production-grade memory persistence and lifecycle management for VM-hosted OpenClaw agents. 4-layer architecture with knowledge graph, activation/decay, nightly consolidation, and health monitoring. Fully local — no network, no credentials, no sudo.",
  "author": "ssharif",
  "license": "MIT-0",
  "triggers": [
    "memory consolidation",
    "memory health check",
    "memory maintenance",
    "memory quality probe",
    "initialize memory",
    "summarize sessions"
  ],
  "permissions": [
    "filesystem"
  ],
  "config": {
    "data_path": "/data/memory",
    "half_life_days": 30,
    "recall_boost": 0.3,
    "search_threshold": 0.15,
    "prune_threshold": 0.05,
    "max_facts": 10000,
    "session_retention_days": 30,
    "daily_retention_days": 365,
    "memory_md_max_lines": 200,
    "canary_check_interval": "weekly",
    "embedding_model": "multilingual-e5-large",
    "embedding_device": "cpu"
  },
  "actions": {
    "init": {
      "description": "Initialize the memory directory structure and default files"
    },
    "summarize": {
      "description": "Summarize today's session logs into a daily summary file"
    },
    "consolidate": {
      "description": "Run the full nightly consolidation pipeline: decay, index, prune, reconcile, clean"
    },
    "health-check": {
      "description": "Run a health check and write results to health.json"
    },
    "quality-probe": {
      "description": "Test recall accuracy against canary facts"
    },
    "install-cron": {
      "description": "Register cron jobs for automated memory lifecycle management"
    }
  },
  "security": {
    "network": false,
    "credentials": false,
    "sudo": false,
    "filesystem_scope": "config.data_path"
  }
}


path: README.md
content: # VM Memory Oracle

Production-grade memory persistence and lifecycle management for VM-hosted OpenClaw agents.

## What It Does

VM Memory Oracle gives your OpenClaw agent a structured, persistent memory that survives reboots, context compaction, and VM redeployment. It replaces fragile flat-file memory with a 4-layer architecture:

| Layer | Purpose | Storage |
|---|---|---|
| Knowledge Graph | Durable facts, entities, relationships | `facts.jsonl`, `entities.jsonl` |
| Semantic Index | Vector similarity search | `index.bin` (rebuildable) |
| Daily Summaries | Per-day session digests | `daily/YYYY-MM-DD.md` |
| Canonical Memory | Single source of truth | `MEMORY.md` |

Every fact has an activation score that decays over time. Frequently recalled facts stay prominent; unused facts gradually fade and get archived. This keeps your agent's memory focused and relevant.

## Key Features

- **Activation/Decay System** — Facts decay with a configurable half-life (default: 30 days). Recalled facts get boosted. Stale facts get archived, not deleted.
- **Nightly Consolidation** — Automated pipeline: summarize sessions, apply decay, rebuild index, prune stale facts, reconcile MEMORY.md, clean old files.
- **Health Monitoring** — Disk usage, fact count, activation distribution, consolidation duration, and quality probes all tracked in `health.json`.
- **Quality Probes** — Canary facts tested weekly to detect memory recall degradation.
- **Fully Local** — Zero network calls. Zero cloud dependencies. Zero credential handling. All data stays on your VM's filesystem.

## Requirements

- OpenClaw >= 1.8.0
- Linux (designed for VM deployments)
- `jq` (JSON processing)
- `cron` (scheduled tasks)

## Installation

```bash
openclaw skill install vm-memory-oracle
```

Or install from ClawHub:

```bash
clawhub install ssharif/vm-memory-oracle
```

## Quick Start

### 1. Configure your data path

```yaml
# In your OpenClaw agent config
memory_oracle:
  data_path: /data/memory
```

### 2. Initialize the directory structure

```bash
openclaw skill run vm-memory-oracle --action init
```

This creates:
```
/data/memory/
  knowledge-graph/
  embeddings/
  daily/
  sessions/
  activation-metadata.json
  MEMORY.md
  health.json
```

### 3. Set up automated maintenance

```bash
openclaw skill run vm-memory-oracle --action install-cron
```

This registers four cron jobs:
- **23:00** — Daily session summarization
- **00:30** — Full consolidation (decay, index, prune, reconcile)
- **Every 6h** — Health check
- **Sunday 03:00** — Quality probe

### 4. Verify

```bash
openclaw skill run vm-memory-oracle --action health-check
cat /data/memory/health.json | jq .
```

## Configuration Reference

| Parameter | Default | Description |
|---|---|---|
| `data_path` | `/data/memory` | Root directory for all memory files |
| `half_life_days` | `30` | Days until a fact's activation halves |
| `recall_boost` | `0.3` | Activation increase on each recall |
| `search_threshold` | `0.15` | Minimum activation for search results |
| `prune_threshold` | `0.05` | Activation below which facts get archived |
| `max_facts` | `10000` | Hard cap on active facts |
| `session_retention_days` | `30` | Days to keep raw session logs |
| `daily_retention_days` | `365` | Days to keep daily summaries |
| `memory_md_max_lines` | `200` | Maximum lines in MEMORY.md |
| `canary_check_interval` | `weekly` | How often to run quality probes |
| `embedding_model` | `multilingual-e5-large` | Model for semantic embeddings |
| `embedding_device` | `cpu` | Device for embedding inference (`cpu` or `gpu`) |

## VM Deployment Guide

This skill is designed for persistent VM environments where the memory directory lives on a dedicated data disk.

### Azure VM Setup

1. **Attach a separate managed disk** for `/data/memory/` with `deleteOption: Detach` so the disk survives VM redeployment.
2. **Format only on first boot** — use `overwrite: false` in cloud-init to prevent reformatting existing data.
3. **Mount at `/data/memory/`** in `/etc/fstab` with `nofail` option.

### Disk Sizing

| Workload | Recommended Size | Notes |
|---|---|---|
| Light (< 1K facts) | 16 GB | Personal agent |
| Medium (1K-5K facts) | 32 GB | Team agent |
| Heavy (5K-10K facts) | 64 GB | Production fleet |
| With large RAG corpus | 128-256 GB | Domain-specific knowledge |

### Backup

Pair with Azure disk snapshots or local tarballs. The consolidation pipeline creates a local backup before pruning:

```
/data/memory/backups/pre-maintenance-YYYYMMDD.tar.gz
```

Backups older than 7 days are automatically cleaned up.

## How It Works

### Fact Lifecycle

```
Session → Ingestion → Knowledge Graph → Embedding Index
                                ↓
                         Activation: 1.0
                                ↓
                    Decay applied nightly (half-life: 30d)
                                ↓
              ┌─────────────────┼─────────────────┐
              ↓                 ↓                 ↓
        Active (>0.15)   Fading (0.05-0.15)  Archived (<0.05)
        Appears in        Excluded from       Moved to
        search results    search, still       archived-facts.jsonl
                          in graph
```

### Daily Pipeline

```
23:00  Summarize today's sessions → daily/YYYY-MM-DD.md
00:30  Apply decay → activation-metadata.json
       Rebuild embedding index → embeddings/index.bin
       Prune stale facts → archived-facts.jsonl
       Reconcile → MEMORY.md
       Clean old sessions (>30d) and dailies (>365d)
       Health check → health.json
```

## Safety

| Property | Guarantee |
|---|---|
| Network access | None. Zero outbound connections. |
| Credentials | Never read, written, or transmitted. |
| Privilege escalation | Never uses sudo or su. |
| Write behavior | Append-only for facts. Archival instead of deletion. |
| Idempotency | All operations safe to retry. |
| Transparency | All files human-readable (JSONL, Markdown, JSON). |

## Monitoring Integration

`health.json` is designed for easy ingestion into monitoring systems:

- **Azure Log Analytics** — Ship with Azure Monitor Agent using a custom log table.
- **Prometheus** — Parse with a JSON exporter or node-exporter textfile collector.
- **Grafana** — Dashboard the `health.json` fields directly.

### Alert Thresholds

| Metric | Warning | Critical |
|---|---|---|
| Disk usage | > 80% | > 90% |
| Active facts | > 9,000 | > 9,500 |
| Avg activation | < 0.2 or > 0.8 | N/A |
| Quality probe accuracy | < 80% | < 70% |
| Consolidation duration | > 600s | > 1200s |

## Troubleshooting

**Memory not persisting across reboots:**
Check that `/data/memory` is mounted on a separate disk, not the OS disk. Verify the mount with `df -h /data/memory`.

**Consolidation taking too long:**
Reduce `max_facts` or increase `prune_threshold` to archive more aggressively. Check embedding index size — if it exceeds 4 GB, consider switching `embedding_model` to a smaller variant.

**Quality probe failing:**
Canary facts may have decayed. Re-add them with high activation, or lower `half_life_days` to keep important facts active longer.

**MEMORY.md too large:**
Lower `memory_md_max_lines` or increase `search_threshold` so fewer facts qualify for inclusion.

## License

MIT-0 — Use, modify, and redistribute freely. No attribution required.


path: SECURITY.md
content: # Security Policy

## Scope

This document describes the security properties of the `vm-memory-oracle` skill
for ClawHub reviewers and users evaluating this skill for deployment.

## Security Properties

### What this skill does

- Reads and writes files under a single configurable directory (`data_path`,
  default `/data/memory/`).
- Creates and manages cron jobs under `/etc/cron.d/openclaw-vm-memory-oracle`.
- Processes JSON and Markdown files using `jq` and standard shell utilities.

### What this skill does NOT do

- **No network access.** This skill never opens sockets, makes HTTP requests,
  performs DNS lookups, or communicates with any external service. All data
  remains on the local filesystem.
- **No credential handling.** This skill never reads, writes, stores, or
  transmits API keys, tokens, passwords, SSH keys, wallet keys, browser cookies,
  session tokens, or any other authentication material.
- **No privilege escalation.** This skill never uses `sudo`, `su`, `pkexec`,
  `doas`, or any other mechanism to elevate privileges.
- **No code obfuscation.** All logic is in plain Markdown instructions and
  shell scripts. No Base64-encoded payloads, hex-encoded commands, string
  concatenation tricks, eval(), or dynamic code generation.
- **No binary execution.** This skill does not download or execute binaries.
  The only binary file it manages is the embedding index (`index.bin`), which
  is generated locally from source facts and is never executed.
- **No system modification.** This skill does not modify system configuration
  files, kernel parameters, firewall rules, or user accounts.
- **No container escape.** This skill does not interact with container runtimes,
  Docker sockets, or orchestration APIs.

## Filesystem Scope

All file operations are confined to:

| Path | Operations | Purpose |
|---|---|---|
| `{data_path}/` | Read, Write, Create | Memory data storage |
| `{data_path}/backups/` | Write, Delete | Pre-maintenance backups (7-day retention) |
| `/etc/cron.d/openclaw-vm-memory-oracle` | Write | Cron job registration |
| `/var/log/openclaw/` | Write | Log output from cron jobs |

No other paths are accessed.

## Dependencies

| Dependency | Source | Purpose |
|---|---|---|
| `jq` | System package manager | JSON parsing and validation |
| `cron` | System package manager | Scheduled task execution |

No third-party packages, pip/npm modules, or remote dependencies are installed
or required at runtime.

## Reporting Vulnerabilities

If you discover a security issue in this skill, please open an issue on the
GitHub repository or contact the author directly. Do not publish details of
security vulnerabilities before they are addressed.


path: tests/smoke-test.sh
content: #!/bin/bash
# VM Memory Oracle — Smoke Test Suite
# Run after installation to verify the memory system is functional.
# Exit codes: 0 = all tests pass, 1 = failure
#
# Usage: bash smoke-test.sh [data_path]
# Default data_path: /data/memory

set -euo pipefail

DATA_PATH="${1:-/data/memory}"
PASS=0
FAIL=0
TOTAL=0

run_test() {
    local name="$1"
    local result="$2"
    TOTAL=$((TOTAL + 1))
    if [ "$result" = "true" ]; then
        echo "  PASS: $name"
        PASS=$((PASS + 1))
    else
        echo "  FAIL: $name"
        FAIL=$((FAIL + 1))
    fi
}

echo "=== VM Memory Oracle Smoke Tests ==="
echo "Host: $(hostname)"
echo "Date: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
echo "Data path: $DATA_PATH"
echo ""

# --- Section 1: Directory Structure ---
echo "[1/5] Directory structure"
run_test "Data path exists" "$([ -d "$DATA_PATH" ] && echo true || echo false)"
run_test "knowledge-graph/ exists" "$([ -d "$DATA_PATH/knowledge-graph" ] && echo true || echo false)"
run_test "embeddings/ exists" "$([ -d "$DATA_PATH/embeddings" ] && echo true || echo false)"
run_test "daily/ exists" "$([ -d "$DATA_PATH/daily" ] && echo true || echo false)"
run_test "sessions/ exists" "$([ -d "$DATA_PATH/sessions" ] && echo true || echo false)"
echo ""

# --- Section 2: Core Files ---
echo "[2/5] Core files"
run_test "activation-metadata.json exists" "$([ -f "$DATA_PATH/activation-metadata.json" ] && echo true || echo false)"
run_test "MEMORY.md exists" "$([ -f "$DATA_PATH/MEMORY.md" ] && echo true || echo false)"
run_test "health.json exists" "$([ -f "$DATA_PATH/health.json" ] && echo true || echo false)"

# Validate JSON files are parseable
if [ -f "$DATA_PATH/activation-metadata.json" ]; then
    run_test "activation-metadata.json is valid JSON" "$(jq empty "$DATA_PATH/activation-metadata.json" 2>/dev/null && echo true || echo false)"
else
    run_test "activation-metadata.json is valid JSON" "false"
fi

if [ -f "$DATA_PATH/health.json" ]; then
    run_test "health.json is valid JSON" "$(jq empty "$DATA_PATH/health.json" 2>/dev/null && echo true || echo false)"
else
    run_test "health.json is valid JSON" "false"
fi
echo ""

# --- Section 3: Disk Mount ---
echo "[3/5] Disk mount"
run_test "Data path is a mount point" "$(mountpoint -q "$DATA_PATH" 2>/dev/null && echo true || echo false)"
DISK_USAGE=$(df "$DATA_PATH" --output=pcent 2>/dev/null | tail -1 | tr -d ' %' || echo "0")
run_test "Disk usage below 90%" "$([ "$DISK_USAGE" -lt 90 ] && echo true || echo false)"
echo "  Info: Disk usage at ${DISK_USAGE}%"
echo ""

# --- Section 4: File Permissions ---
echo "[4/5] File permissions"
run_test "Data path is writable" "$([ -w "$DATA_PATH" ] && echo true || echo false)"
run_test "knowledge-graph/ is writable" "$([ -w "$DATA_PATH/knowledge-graph" ] && echo true || echo false)"
run_test "daily/ is writable" "$([ -w "$DATA_PATH/daily" ] && echo true || echo false)"
echo ""

# --- Section 5: Cron Jobs ---
echo "[5/5] Cron configuration"
CRON_FILE="/etc/cron.d/openclaw-vm-memory-oracle"
run_test "Cron file exists" "$([ -f "$CRON_FILE" ] && echo true || echo false)"
if [ -f "$CRON_FILE" ]; then
    run_test "Summarize job configured" "$(grep -q 'summarize' "$CRON_FILE" && echo true || echo false)"
    run_test "Consolidate job configured" "$(grep -q 'consolidate' "$CRON_FILE" && echo true || echo false)"
    run_test "Health-check job configured" "$(grep -q 'health-check' "$CRON_FILE" && echo true || echo false)"
    run_test "Quality-probe job configured" "$(grep -q 'quality-probe' "$CRON_FILE" && echo true || echo false)"
fi
echo ""

# --- Summary ---
echo "=== Results ==="
echo "Passed: $PASS / $TOTAL"
echo "Failed: $FAIL / $TOTAL"
echo ""

if [ "$FAIL" -gt 0 ]; then
    echo "STATUS: FAIL"
    exit 1
else
    echo "STATUS: PASS"
    exit 0
fi


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (CRITICAL)