Skill System Memory (PostgreSQL)
Persistent shared memory for all AI agents. PostgreSQL 14+ on Linux or Windows. Memory failures look like intelligence failures — this skill ensures the right memory is retrieved at the right time.
Contract notes:
- Module-first:
mem.pyand MCP tooling are the primary runtime surface. - Plugin optional: OpenCode plugin integration is an adapter layer, not a required dependency.
- Prefer project-scoped DB naming:
<project>-memory(for exampleskills-memory).
DB Targeting — Project Isolation
Skills are installed globally but memory is project-scoped. Isolation is at the database level: each project gets its own PostgreSQL database named <project>-memory.
Cross-DB recall is an explicit read-side feature, not a default mode. Search and context reads stay on the current memory DB unless the caller opts in with scope=all or cross_db=true. All write paths remain pinned to the local SKILL_PGDATABASE target.
Search Path Role Architecture (SK-C)
The compatible rollout path is additive:
- legacy mode remains DB-per-project via
SKILL_PGDATABASE=<project>-memory - shared-DB mode uses an explicit shared DB plus schema isolation
- runtime roles are split into
admin,connector, andvisitor_<identity>
Role model:
admin: migration/init only; creates schemas, grants, and rolesconnector: CONNECT-only credential; opens the DB connection and immediatelySET ROLEsvisitor_<identity>: daily query role with enforcedsearch_path
Visitor search_path matrix:
visitor_hermes:ep_scope, sk_scope, fd_scope, work_scope, publicvisitor_atlas:ep_scope, publicvisitor_athena:sk_scope, publicvisitor_fd_coder:fd_scope, publicvisitor_ep_coder:ep_scope, publicvisitor_sk_coder:sk_scope, publicvisitor_hephaestion:work_scope, sk_scope, public
Shared-DB mode is explicit and backward-compatible:
SKILL_PGSHARED_DB=<shared-db-name>selects the shared DBSKILL_PGSCHEMA=<scope-schema>selects the local writable schemaSKILL_PGDATABASEremains valid for legacy DB-per-project mode
Runtime flow in shared-DB mode:
- connect as
connector SET ROLE visitor_<identity>- rely on the visitor
search_pathfor scoped queries - allow Hermes-only explicit override for all-scopes audit queries
Shared-DB examples:
# Provision shared DB schemas/roles for SK scope
python3 scripts/mem.py init-project \
--project-id sk \
--db-name shared-memory \
--schema-name sk_scope \
--shared-db-mode
# Run local SK queries through shared DB scope
SKILL_PGSHARED_DB=shared-memory \
SKILL_PGSCHEMA=sk_scope \
SKILL_VISITOR_ROLE=visitor_sk_coder \
python3 scripts/mem.py search "router policy"
# Hermes explicit all-scopes audit across the shared DB
SKILL_PGSHARED_DB=shared-memory \
SKILL_PGSCHEMA=sk_scope \
SKILL_VISITOR_ROLE=visitor_hermes \
python3 scripts/mem.py search "friction skill-system-comms" --all-scopes
Cross-DB Visibility Contract
visibility=private(default): searchable only inside the DB where the memory lives; legacy rows without visibility read asprivatevisibility=shared: searchable across configured memory DBs when federation is explicitvisibility=global: searchable across configured memory DBs and eligible for cross-DB auto context injection- Cross-DB results must include
source_db - Cross-DB ranking uses normalized fusion (RRF-style), not raw per-DB score comparison
- Known DB fan-out targets are configured in
config/insight.yamlundermemory.cross_db_targets - All mutation paths (
store,update,delete,purge) stay local to the activeSKILL_PGDATABASEtarget even when read-side cross-DB federation is enabled
Auto-detection (preferred)
When no env vars are set, the DB name is auto-derived from the project directory name:
- Plugin (JS): uses
directorypassed by OpenCode host → last path segment →<dir>-memory - mem.py CLI: uses script's root directory or cwd →
<dir>-memory - MCP server: uses
Path.cwd()at startup →<dir>-memory
Do NOT set SKILL_PGDATABASE globally. It overrides auto-detection for ALL projects.
# WRONG — breaks project isolation
export SKILL_PGDATABASE=skills-memory # every project now hits skills-memory
# RIGHT — let auto-detection work (no env var needed)
cd /path/to/FraudDetect && opencode # → FraudDetect-memory
cd /path/to/skills && opencode # → skills-memory
Per-project override (when needed)
If you must override, set SKILL_PGDATABASE at project level, not globally:
- In project's
.opencodeconfig or launch script - In project's
.envfile (if your host reads it) - As a prefix to the command:
SKILL_PGDATABASE=FraudDetect-memory opencode
Fail-closed policy
If PGDATABASE is set but SKILL_PGDATABASE is not, all entry points refuse to connect. This prevents accidental cross-project memory pollution.
MCP server path for multi-project setups
When skills are globally installed at ~/.agents/skills/, configure MCP with the absolute path to the global install:
{
"skill-system-memory": {
"command": "python3",
"args": ["~/.agents/skills/skill-system-memory/mcp/server.py"]
}
}
Do NOT use relative paths like skills/skill-system-memory/mcp/server.py — they break in projects that don't have a local skills/ directory.
Quick Start
Database <project>-memory and all functions are created by init.sql in this skill directory.
The current supported-now runtime surface covers core memory, typed context reads, the typed evolution ledger, and doctor/compaction support.
Session/project/context projection tables and behavior graph refresh remain optional capability-gated surfaces, not unconditional runtime guarantees.
# Linux — replace 'postgres' with your PostgreSQL superuser if different (e.g. your system username)
psql -U postgres -c "CREATE DATABASE <project>-memory;"
psql -U postgres -d <project>-memory -f init.sql
# Windows (adjust path to your psql.exe; replace 'postgres' with your PG superuser if needed)
& "C:\Program Files\PostgreSQL\18\bin\psql.exe" -U postgres -c "CREATE DATABASE <project>-memory;"
& "C:\Program Files\PostgreSQL\18\bin\psql.exe" -U postgres -d <project>-memory -f init.sql
Note: If your PostgreSQL installation does not have a
postgresrole, use your actual PostgreSQL superuser name. On many Linux distros this matches your OS username. You can override at any time by settingPGUSERbefore running scripts:export PGUSER=your_pg_username(Linux/macOS) or$env:PGUSER = "your_pg_username"(PowerShell).
Verify: SELECT * FROM memory_health_check();
MCP Server (Phase 6.1)
This skill includes an MCP (Model Context Protocol) server that exposes memory operations as agent tools.
MCP Server Setup
# Install dependencies
cd skills/skill-system-memory/mcp
pip install -r requirements.txt
# Verify installation
python server.py --help
# Run with stdio transport (default)
python server.py
# Run with SSE transport (for remote access)
MCP_TRANSPORT=sse MCP_PORT=8000 python server.py
# Or via MCP CLI
mcp dev server.py
MCP Environment Variables
| Variable | Default | Description |
|---|---|---|
SKILL_PGDATABASE |
<project>-memory |
Legacy DB-per-project PostgreSQL database name |
SKILL_PGSHARED_DB |
(unset) | Shared PostgreSQL database name for search_path mode |
SKILL_PGSCHEMA |
(unset) | Local writable schema for search_path mode |
PGHOST |
localhost |
PostgreSQL host |
PGPORT |
5432 |
PostgreSQL port |
PGUSER |
(optional) | PostgreSQL user |
MCP_TRANSPORT |
stdio |
Transport mode (stdio or sse) |
MCP_PORT |
8000 |
Port for SSE transport |
MCP Tools
| Tool | Description |
|---|---|
memory_search |
Search memories by natural language query (hybrid: FTS + trigram + pgvector) |
memory_store |
Store a new memory with auto-deduplication and local-only write isolation |
memory_update |
Update selected fields on a local memory row by id with audit logging |
memory_delete |
Soft-delete a local memory row by id with audit logging |
memory_purge |
Hard-delete a local memory row only with explicit authorization |
memory_auto_match |
Auto-match memories against input text + write to .sisyphus/tmp/mem-{session}.md |
memory_context |
Get user context (soul state, preferences, recent facets) |
memory_status |
Check memory system health (connection, schema, pgvector) |
debug_diagnose |
Run debug-tool diagnosis through the unified MCP server |
eda_profile |
Run EDA dataset profiling through the unified MCP server |
gate_validate |
Run gate validation through the unified MCP server |
memory_rebuild |
Rebuild full agent context after compact or memory loss |
MCP Resources
| Resource | Description |
|---|---|
memory://schema |
Memory database schema information |
memory://status |
Current memory system status |
MCP Agent Integration
To use the MCP server with an agent, configure the agent's MCP settings to include:
{
"mcpServers": {
"skill-system": {
"command": "python",
"args": ["skills/skill-system-memory/mcp/server.py"],
"env": {
"SKILL_PGDATABASE": "<project>-memory"
}
}
}
}
Shared-DB MCP example:
{
"mcpServers": {
"skill-system": {
"command": "python",
"args": ["skills/skill-system-memory/mcp/server.py"],
"env": {
"SKILL_PGSHARED_DB": "shared-memory",
"SKILL_PGSCHEMA": "sk_scope",
"SKILL_VISITOR_ROLE": "visitor_sk_coder"
}
}
}
}
MCP Tool Examples
# Search memories
mcp_tool: memory_search
args: { "query": "pgvector installation", "limit": 5 }
# Explicit cross-DB search
mcp_tool: memory_search
args: { "query": "reviewer feedback", "cross_db": true, "limit": 5 }
# Hermes all-scopes override in shared-DB mode
mcp_tool: memory_search
args: { "query": "cross-project audit", "all_scopes": true, "limit": 10 }
# Store a memory
mcp_tool: memory_store
args: { "type": "semantic", "category": "troubleshooting", "title": "Fixed pgvector on Windows", "content": "Build steps...", "importance": 8 }
# Update a memory locally
mcp_tool: memory_update
args: { "id": 42, "fields": { "title": "Updated title", "visibility": "shared" } }
# Soft-delete a memory locally
mcp_tool: memory_delete
args: { "id": 42 }
# Hard-delete a memory locally only with explicit authorization
mcp_tool: memory_purge
args: { "id": 42, "hard": true, "authorized": true }
# Auto-match memories (KEY TOOL for near-automatic surfacing)
mcp_tool: memory_auto_match
args: { "text": "I'm seeing an error with database connections", "threshold": 0.8, "limit": 5 }
# Get user context
mcp_tool: memory_context
args: { "user": "default" }
# Check system health
mcp_tool: memory_status
args: {}
For existing installations, also run:
psql -U postgres -d <project>-memory -v -f migrate-v2-postgres-first.sql
Pure Skill Mode (default)
This skill works without installing any plugin. In pure skill mode:
- you manually run scripts when you want (progressive disclosure)
- no global OpenCode config is modified automatically
Optional bootstrap (asks + records choices + tries to install)
Notes:
- Interactive mode defaults to NOT installing heavy optional components.
- Use
-InstallAll/--install-allonly when you're ready to install everything.
Run the bootstrap script to choose optional components (pgpass, local embeddings, pgvector) and record decisions.
Bootstrap can also optionally install the OpenCode compaction logging plugin (it will copy the plugin into your OpenCode plugins directory).
Windows:
# run from the skill directory
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "scripts\bootstrap.ps1"
Linux/macOS:
# run from the skill directory
bash "scripts/bootstrap.sh"
The selection record is stored at:
~/.config/opencode/skill-system-memory/setup.json
Agent rule:
- If this file does not exist, ask the user if they want to enable optional components.
- Recommended: run bootstrap with all options enabled (then fix any failures it reports).
Runtime Capability Model
Current live capability classifications are intentionally narrow:
| capability | current status | current support surface |
|---|---|---|
core_memory |
SUPPORTED_NOW |
agent_memories plus store_memory, search_memories, memory_health_check |
evolution_ledger |
SUPPORTED_NOW |
evolution_snapshots plus insert_evolution_snapshot, get_evolution_history |
compaction_logging |
SUPPORTED_NOW when the repo plugin is synced |
local JSONL compaction log plus guarded store_memory(...) writeback |
typed_context_reads |
SUPPORTED_NOW |
get_agent_context, get_soul_state, get_recent_facets, get_user_preferences |
runtime_sync_projections |
GATED_OPTIONAL |
session_summaries, project_summaries, context_rollups only when those tables exist |
behavior_refresh_graph |
GATED_OPTIONAL |
behavior_* refresh only when those tables exist |
control_plane_refresh |
DEFERRED_UNSUPPORTED |
not part of the current user-facing memory runtime |
When the durable evolution proposal model is present, doctor also reports:
- canonical accepted store:
evolution_nodes - canonical rejected store:
evolution_rejections - canonical task materialization:
evolution_tasks -> agent_tasks - role of
agent_memories: searchable summary/backref surface with explicit legacy compatibility rows - approve/reject path status: transaction-safe at the CLI boundary
- migration/backfill idempotence: rerun-safe
- decision replay status: replay-idempotent by
proposal_id - coordination mechanism: advisory lock by proposal + semantic fingerprint on canonical accepted/rejected rows
- payload mismatch policy: blocked with no mutation
- conflicting terminal policy: blocked with no mutation
- task authority model:
agent_taskslifecycle authority,evolution_tasksmapping only
In that state, evolution_snapshots is treated as LEGACY_COMPAT_SURFACE for proposal durability, while remaining active for snapshot/version history.
On Windows, pgvector installation follows the official pgvector instructions (Visual Studio C++ + nmake /F Makefile.win). The bootstrap will attempt to install prerequisites via winget.
Optional automation: compaction logging (OpenCode plugin)
If you want automatic compaction logging, install the OpenCode plugin template shipped with this skill.
Option A (recommended): run bootstrap and choose the plugin option.
- Copy
plugins/skill-system-memory.jsandplugins/runtime_sync.jsto~/.config/opencode/plugins/ - Restart OpenCode
Safety / rollback (if OpenCode gets stuck on startup):
- Remove or rename
~/.config/opencode/plugins/skill-system-memory.js - Remove or rename
~/.config/opencode/plugins/runtime_sync.js - Restart OpenCode
- Check logs:
- macOS/Linux:
~/.local/share/opencode/log/ - Windows:
%USERPROFILE%\.local\share\opencode\log
- macOS/Linux:
Plugin behavior notes:
- The plugin is designed to be a no-op unless you explicitly enabled it via bootstrap (
setup.jsonsetsselected.opencode_plugin=true). - It only attempts a Postgres write if
selected.pgpass=true(avoids hanging on auth prompts). - On compaction, it always keeps local JSONL logging and the core
store_memory(...)path available when the DB target is valid. - Runtime projection upserts (
session_summaries,project_summaries,context_rollups) are capability-gated: if those tables are absent, the plugin skips them with an explicit surfaced reason instead of attempting writes. - Behavior graph refresh into
behavior_*tables is also capability-gated and is skipped explicitly when the required tables are absent.
Uninstall:
- Remove
~/.config/opencode/plugins/skill-system-memory.js - Remove
~/.config/opencode/plugins/runtime_sync.js - Restart OpenCode
Credentials (psql)
Do NOT hardcode passwords in scripts, skill docs, or config files.
Recommended options for non-interactive psql:
.pgpass/pgpass.conf(recommended)- Linux/macOS:
~/.pgpass(must bechmod 0600 ~/.pgpassor libpq will ignore it) - Windows:
%APPDATA%\postgresql\pgpass.conf(example:C:\Users\<you>\AppData\Roaming\postgresql\pgpass.conf) - Format:
hostname:port:database:username:password - Docs: https://www.postgresql.org/docs/current/libpq-pgpass.html
- Linux/macOS:
PGPASSFILE(optional override): point to a custom location for the password filePGPASSWORD(not recommended): only for quick local testing; environment variables can leak on some systems
Tip: set connection defaults once (per shell) to shorten commands:
export PGHOST=localhost
export PGPORT=5432
export SKILL_PGDATABASE=<project>-memory
export PGUSER=postgres # change to your PG superuser if postgres role does not exist
Shell copy/paste safety:
- Avoid copying inline markdown backticks (e.g.
semantic) into your shell. In zsh, backticks are command substitution. - Prefer using the wrapper scripts (
scripts/mem.sh,scripts/mem.ps1) or copy from fenced code blocks.
One-time setup helper scripts
This skill ships helper scripts (relative paths):
scripts/setup-pgpass.ps1scripts/setup-pgpass.sh
OpenCode usage: run them from the skill directory.
Windows run:
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "scripts\setup-pgpass.ps1"
Linux/macOS run:
bash "scripts/setup-pgpass.sh"
Memory Types
| Type | Lifespan | Use When |
|---|---|---|
working |
24h auto-expire | Current conversation context (requires session_id) |
episodic |
Permanent + decay | Problem-solving experiences, debugging sessions |
semantic |
Permanent | Extracted facts, knowledge, patterns |
procedural |
Permanent | Step-by-step procedures, checklists (importance >= 7) |
Core Functions
store_memory(type, category, tags[], title, content, metadata, agent_id, session_id, importance)
Auto-deduplicates by content hash. Duplicate inserts bump access_count and importance_score.
SELECT store_memory(
'semantic',
'windows-networking',
ARRAY['ssh', 'tunnel', 'port-conflict'],
'SSH Tunnel Port Conflict Resolution',
'Fix: 1) taskkill /F /IM ssh.exe 2) Use processId not pid 3) Wait 3s',
'{"os": "Windows 11"}',
'sisyphus',
NULL,
9.0
);
Wrapper: scripts/mem.py (推薦 — parameterized query,無 quoting 問題)
Requirements:
pip install psycopg2-binary
# DB 連線狀態 + 記憶總數
python3 scripts/mem.py status
# 搜尋記憶(含特殊字元也安全)
python3 scripts/mem.py search "pgvector windows install" --limit 5
python3 scripts/mem.py search "fraud features" --scope project --limit 10
python3 scripts/mem.py search "reviewer feedback" --cross-db --limit 10
python3 scripts/mem.py search "shared debugging notes" --scope all --limit 10
# 跨 5 維度診斷搜尋 (B-015 TKT-001)
python3 scripts/mem.py search "alert file" --diagnostic --limit 10
# Tag 前綴自動展開 (B-015 TKT-003)
python3 scripts/mem.py search "root-cause" --auto-expand
# 儲存記憶(--content flag)
python3 scripts/mem.py store --type semantic --category project --title "pgvector install" --tags "postgres,pgvector,windows" --importance 8 --scope project --content "Steps: ..."
python3 scripts/mem.py store --type semantic --category feedback --title "Reviewer note" --visibility shared --content "Cross-DB searchable note"
python3 scripts/mem.py update 42 --field title="Updated note" --field visibility=shared
python3 scripts/mem.py delete 42
python3 scripts/mem.py purge 42 --hard --authorized
# 儲存記憶(stdin)
printf '%s' "Steps: ..." | python3 scripts/mem.py store semantic project "pgvector install" "postgres,pgvector,windows" 8 --scope session
# 列出 / 匯出 / 壓縮
python3 scripts/mem.py list --scope project --limit 20
python3 scripts/mem.py export --format json --scope global
python3 scripts/mem.py compact --scope project
# session 開頭自動撈出相關記憶
python3 scripts/mem.py context "pgvector ssh tunnel"
# 列出所有已使用的 tags / categories
python3 scripts/mem.py tags
python3 scripts/mem.py categories
# DB 不可用時,將 pending fallback 寫回 DB
python3 scripts/mem.py flush
# 保守升級 visibility(只影響本地 DB)
python3 scripts/mem.py visibility-upgrade --visibility shared --category feedback --dry-run
python3 scripts/mem.py visibility-upgrade --visibility global --tags reviewer,decision
Fallback behavior:
- DB 連線失敗時,
store會降級寫入.memory/pending/*.json,search/context會讀本地 pending 檔案並印出警告 list/export也會從 pending fallback 讀取;compact在 DB 不可用時只印 warning 不崩潰- DB 可連線但 memory schema 缺失時,
store會 warning + no-op,search/context/tags/categories會回空結果 + warning flush會在 DB 恢復後將.memory/pending/內容寫回 PostgreSQL
Scope model:
session(default): 記錄在metadata.scope=session,並盡量帶上session_idproject: 記錄在metadata.scope=project+metadata.project_id=<repo>global: 記錄在metadata.scope=global,仍需明確 federated read 才會跨 DB 查詢search/list/export不帶--scope時,會回傳所有 scope 並在結果中標記來源 scope
Visibility is distinct from scope:
private(default): local DB onlyshared: eligible for explicit cross-DB searchglobal: eligible for explicit cross-DB search and auto context injection
Mutation audit rules:
updatewrites selected field changes only, in the local DB onlydeleteis soft-delete only (deleted_at), preserving backward-compatible readspurgeis hard delete and must be explicitly authorized- every mutation writes a
memory_auditrow with old/new values plus actor metadata
CLI mutation examples:
python3 scripts/mem.py update 42 --field title="Updated note" --field visibility=shared
python3 scripts/mem.py delete 42
python3 scripts/mem.py purge 42 --hard --authorized
memory_audit is the canonical mutation trail for these operations. Each row records:
memory_idaction(update,delete,purge)old_valuenew_valueactor_idsession_idchanged_at
Warning: purge is destructive and bypasses soft-delete recovery. It stays local-only and requires explicit authorization flags; do not use it for routine cleanup.
Known federated read targets are configured in config/insight.yaml:
memory:
cross_db_targets:
- Work-memory
- skills-memory
- ExperimentPipeline-memory
- FraudDetect-memory
cross_db_context_visibility:
- global
This list controls explicit read fan-out only. Write paths still target the local SKILL_PGDATABASE database even if a caller passes target_db-style data.
Wrapper: scripts/mem.sh / scripts/mem.ps1 (shell fallback)
# 連線狀態
bash "scripts/mem.sh" status
# 搜尋
bash "scripts/mem.sh" search "pgvector windows install" 5
# 儲存 (content via stdin)
printf '%s' "Steps: ..." | bash "scripts/mem.sh" store semantic project "pgvector install" "postgres,pgvector,windows" 8
# 列出 tags / categories
bash "scripts/mem.sh" tags
bash "scripts/mem.sh" categories
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "scripts\mem.ps1" types
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "scripts\mem.ps1" search "pgvector windows install" 5
"Steps: ..." | powershell.exe -NoProfile -ExecutionPolicy Bypass -File "scripts\mem.ps1" store semantic project "pgvector install" "postgres,pgvector,windows" 8
Router Integration (optional)
If you use a Router skill that executes pinned pipelines, it can read a manifest embedded in this SKILL.md.
For portability, the manifest block is fenced as YAML but the content is JSON (valid YAML). The Router parses it.
{
"schema_version": "2.0",
"id": "skill-system-memory",
"version": "0.7.0",
"capabilities": ["memory-search", "memory-search-cross-db", "memory-role-scope", "memory-store", "memory-update", "memory-delete", "memory-purge", "memory-visibility-upgrade", "memory-list", "memory-compact", "memory-export", "memory-export-md", "memory-flush", "memory-health", "memory-types", "memory-auto-write", "memory-doctor", "plugin-debug", "plugin-eda", "plugin-gate", "memory-rebuild"],
"effects": ["proc.exec", "db.read", "db.write"],
"operations": {
"search": {
"description": "Search memories by natural language query. Returns ranked results with relevance scores.",
"input": {
"query": { "type": "string", "required": true, "description": "Natural language search query" },
"limit": { "type": "integer", "required": false, "default": 5, "description": "Max results" },
"scope": { "type": "string", "required": false, "description": "global | project | session filter; all enables explicit cross-DB federation" },
"cross_db": { "type": "boolean", "required": false, "description": "Explicitly fan out reads across configured memory DBs" },
"all_scopes": { "type": "boolean", "required": false, "description": "Hermes/admin override to bypass visitor search_path scoping for cross-project audit" }
},
"output": {
"description": "Array of memory matches with local scope labels and cross-DB source attribution when federation is enabled",
"fields": { "status": "ok | error", "data": "array of {id, title, content, relevance_score, scope, source_db?}" }
},
"entrypoints": {
"unix": ["bash", "scripts/router_mem.sh", "search", "{query}", "{limit}"],
"windows": ["powershell.exe", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "scripts\\router_mem.ps1", "search", "{query}", "{limit}"]
}
},
"store": {
"description": "Store a new memory. Auto-deduplicates by content hash and always writes to the local memory DB.",
"input": {
"memory_type": { "type": "string", "required": true, "description": "One of: semantic, episodic, procedural, working" },
"category": { "type": "string", "required": true, "description": "Category name" },
"title": { "type": "string", "required": true, "description": "One-line summary" },
"tags_csv": { "type": "string", "required": true, "description": "Comma-separated tags" },
"importance": { "type": "integer", "required": true, "description": "1-10 importance score" },
"scope": { "type": "string", "required": false, "description": "global | project | session" },
"visibility": { "type": "string", "required": false, "description": "private | shared | global" }
},
"output": {
"description": "Confirmation with stored memory id",
"fields": { "status": "ok | error", "id": "integer" }
},
"entrypoints": {
"unix": ["bash", "scripts/router_mem.sh", "store", "{memory_type}", "{category}", "{title}", "{tags_csv}", "{importance}"],
"windows": ["powershell.exe", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "scripts\\router_mem.ps1", "store", "{memory_type}", "{category}", "{title}", "{tags_csv}", "{importance}"]
}
},
"update": {
"description": "Update selected fields of a local memory row by id with audit logging.",
"input": {
"id": { "type": "integer", "required": true },
"fields": { "type": "object", "required": true }
},
"output": {
"description": "Update summary",
"fields": { "status": "ok | error", "id": "integer", "updated_fields": "array" }
},
"entrypoints": {
"unix": ["python3", "scripts/mem.py", "update"],
"windows": ["python", "scripts/mem.py", "update"]
}
},
"delete": {
"description": "Soft-delete a local memory row by id with audit logging.",
"input": {
"id": { "type": "integer", "required": true }
},
"output": {
"description": "Soft-delete summary",
"fields": { "status": "ok | error", "id": "integer", "deleted_at": "string" }
},
"entrypoints": {
"unix": ["python3", "scripts/mem.py", "delete"],
"windows": ["python", "scripts/mem.py", "delete"]
}
},
"purge": {
"description": "Hard-delete a local memory row only with explicit authorization.",
"input": {
"id": { "type": "integer", "required": true },
"hard": { "type": "boolean", "required": true },
"authorized": { "type": "boolean", "required": true }
},
"output": {
"description": "Hard-delete summary",
"fields": { "status": "ok | error", "id": "integer", "purged": "boolean" }
},
"entrypoints": {
"unix": ["python3", "scripts/mem.py", "purge"],
"windows": ["python", "scripts/mem.py", "purge"]
}
},
"list": {
"description": "List memories with optional scope/category filters.",
"input": {
"scope": { "type": "string", "required": false },
"category": { "type": "string", "required": false },
"limit": { "type": "integer", "required": false, "default": 20 }
},
"output": {
"description": "Memory listing with scope labels",
"fields": { "status": "ok | error", "results": "array" }
},
"entrypoints": {
"unix": ["python3", "scripts/mem.py", "list"],
"windows": ["python", "scripts/mem.py", "list"]
}
},
"compact": {
"description": "Compact duplicate memories within an optional scope.",
"input": {
"scope": { "type": "string", "required": false }
},
"output": {
"description": "Compaction result",
"fields": { "status": "ok | warn | error", "compacted_count": "integer" }
},
"entrypoints": {
"unix": ["python3", "scripts/mem.py", "compact"],
"windows": ["python", "scripts/mem.py", "compact"]
}
},
"export": {
"description": "Export memories in json or csv format.",
"input": {
"format": { "type": "string", "required": false },
"scope": { "type": "string", "required": false },
"limit": { "type": "integer", "required": false, "default": 1000 }
},
"output": {
"description": "Export payload",
"fields": { "status": "ok | error", "results": "array|string" }
},
"entrypoints": {
"unix": ["python3", "scripts/mem.py", "export"],
"windows": ["python", "scripts/mem.py", "export"]
}
},
"export-md": {
"description": "Export DB-only memories to markdown files that memory_sync can re-import.",
"input": {
"folder": { "type": "string", "required": true, "description": "Target folder for markdown exports" }
},
"output": {
"description": "Markdown export result",
"fields": { "status": "ok | error", "created": "integer", "skipped": "integer", "folder": "string" }
},
"entrypoints": {
"agent": "Use the memory_export MCP tool from skills/skill-system-memory/mcp/server.py"
}
},
"visibility-upgrade": {
"description": "Batch-upgrade local memory visibility conservatively by category and/or tag selectors.",
"input": {
"visibility": { "type": "string", "required": true, "description": "shared | global | private" },
"category": { "type": "string", "required": false },
"tags": { "type": "string", "required": false },
"dry_run": { "type": "boolean", "required": false, "default": false }
},
"output": {
"description": "Upgrade summary",
"fields": { "status": "ok | error", "matched": "integer", "updated": "integer" }
},
"entrypoints": {
"unix": ["python3", "scripts/mem.py", "visibility-upgrade"],
"windows": ["python", "scripts/mem.py", "visibility-upgrade"]
}
},
"flush": {
"description": "Flush local pending fallback files into PostgreSQL when the DB is back.",
"input": {},
"output": {
"description": "Confirmation that pending fallback files were replayed",
"fields": { "status": "ok | warn | error", "flushed_count": "integer" }
},
"entrypoints": {
"unix": ["python3", "scripts/mem.py", "flush"],
"windows": ["python", "scripts/mem.py", "flush"]
}
},
"health": {
"description": "Check memory system health: total count, average importance, stale count.",
"input": {},
"output": {
"description": "Health metrics",
"fields": { "status": "ok | error", "data": "array of {metric, value, status}" }
},
"entrypoints": {
"unix": ["bash", "scripts/router_mem.sh", "health"],
"windows": ["powershell.exe", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "scripts\\router_mem.ps1", "health"]
}
},
"types": {
"description": "List available memory types and their descriptions.",
"input": {},
"output": {
"description": "Memory type definitions",
"fields": { "status": "ok | error", "data": "array of {type, lifespan, description}" }
},
"entrypoints": {
"unix": ["bash", "scripts/router_mem.sh", "types"],
"windows": ["powershell.exe", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "scripts\\router_mem.ps1", "types"]
}
},
"auto-write": {
"description": "Procedure template for automatically storing a memory after solving a non-obvious problem.",
"input": {},
"output": {
"description": "Proposed memory fields to store",
"fields": {"memory_type": "string", "category": "string", "title": "string", "tags_csv": "string", "importance": "integer", "content": "string"}
},
"entrypoints": {
"agent": "Follow scripts/auto-write-template.md"
}
},
"doctor": {
"description": "Report the current runtime capability map, memory plugin drift, memory DB target, OMO resolution, canonical evolution stores, table/routine readiness, and evolution ledger status.",
"input": {},
"output": {
"description": "Doctor report for the current runtime state",
"fields": {"status": "ok | warn | error", "doctor_report": "object"}
},
"entrypoints": {
"unix": ["python3", "scripts/runtime_doctor.py", "--format", "json"],
"windows": ["python", "scripts/runtime_doctor.py", "--format", "json"]
}
},
"debug-diagnose": {
"description": "Expose skill-system-debug diagnose through the unified MCP server.",
"input": {
"symptom": { "type": "string", "required": true },
"context": { "type": "string", "required": false }
},
"output": {
"description": "Structured diagnosis payload",
"fields": { "status": "ok | error", "result": "object" }
},
"entrypoints": {
"agent": "Use the debug_diagnose MCP tool from skills/skill-system-memory/mcp/server.py"
}
},
"eda-profile": {
"description": "Expose skill-system-eda dataset profiling through the unified MCP server.",
"input": {
"input_path": { "type": "string", "required": true },
"sample": { "type": "integer", "required": false },
"target": { "type": "string", "required": false }
},
"output": {
"description": "EDA profile output",
"fields": { "status": "ok | error", "profile_path": "string", "report_path": "string" }
},
"entrypoints": {
"agent": "Use the eda_profile MCP tool from skills/skill-system-memory/mcp/server.py"
}
},
"gate-validate": {
"description": "Expose skill-system-gate validation through the unified MCP server.",
"input": {
"rules": { "type": "string", "required": false },
"artifact_root": { "type": "string", "required": false }
},
"output": {
"description": "Gate validation summary",
"fields": { "status": "ok | error", "passed": "boolean", "results": "array" }
},
"entrypoints": {
"agent": "Use the gate_validate MCP tool from skills/skill-system-memory/mcp/server.py"
}
},
"rebuild": {
"description": "Rebuild full agent context after compact or memory loss.",
"input": {
"user": { "type": "string", "required": false },
"recent_limit": { "type": "integer", "required": false }
},
"output": {
"description": "Soul, preferences, recent memories, and pending decisions",
"fields": { "status": "ok | error", "rebuild_context": "object" }
},
"entrypoints": {
"agent": "Use the memory_rebuild MCP tool from skills/skill-system-memory/mcp/server.py"
}
}
},
"stdout_contract": {
"last_line_json": true
},
"mcp": {
"server": {
"name": "skill-system",
"description": "Unified skill-system MCP server exposing memory, debug, eda, gate, and memory_rebuild tools",
"entrypoint": "python skills/skill-system-memory/mcp/server.py",
"transport": "stdio",
"tools": ["memory_search", "memory_store", "memory_auto_match", "memory_context", "memory_status", "memory_sync", "memory_export", "debug_diagnose", "eda_profile", "gate_validate", "memory_rebuild"],
"resources": ["memory://schema", "memory://status"]
}
}
}
Notes:
- The Router expects each step to print last-line JSON.
- These Router adapter scripts are separate from
mem.sh/mem.ps1to avoid breaking existing workflows.
Visualize Memories (Markdown export)
If querying PostgreSQL is too inconvenient for daily use, you can export memories into markdown files under ./Memory/ (current directory by default):
bash "<skill-dir>/scripts/sync_memory_to_md.sh" --out-dir "./Memory"
Outputs:
Memory/Long.md(semantic + procedural)Memory/Procedural.md(procedural only)Memory/Short.md(friction + compaction-daily + procedural highlights)Memory/Episodic.md(episodic)
Backups:
- Backups are stored under
Memory/.backups/to avoid noisygit status. - Use
--no-backupto disable.
The sync script will also create Memory/.gitignore if it doesn't exist (ignores .backups/ and SYNC_STATUS.txt).
Long index:
Memory/Long.mdincludes anIndexsection (top categories + tags) to make the export browsable.
search_memories(query, types[], categories[], tags[], agent_id, min_importance, limit)
Hybrid search: full-text (tsvector) + trigram similarity (pg_trgm) + tag filtering.
Accepts plain English queries — no tsquery syntax needed.
Relevance scoring: text_score * decay * recency * importance.
-- Natural language
SELECT * FROM search_memories('ssh tunnel port conflict', NULL, NULL, NULL, NULL, 7.0, 5);
-- Filter by type + tags
SELECT * FROM search_memories(
'troubleshooting steps',
ARRAY['procedural']::memory_type[],
NULL,
ARRAY['ssh'],
NULL, 0.0, 5
);
Returns: id, memory_type, category, title, content, importance_score, relevance_score, match_type
Where match_type is one of: fulltext, trigram_title, trigram_content, metadata.
memory_health_check()
Returns: metric | value | status for total_memories, avg_importance, stale_count.
apply_memory_decay()
Decays episodic memories by 0.9999^days_since_access. Run daily.
prune_stale_memories(age_days, max_importance, max_access_count)
Soft-deletes old episodic memories below thresholds. Default: 180 days, importance <= 3, never accessed.
Agent Workflow
Auto-Write Template
After fixing a bug or solving a non-obvious problem, store a memory using the standard template:
- Procedure:
scripts/auto-write-template.md
最佳實踐:優先使用
mem.pywrapper,避免 shell quoting 與認證問題。 Raw SQL 範例請見 Appendix: Raw SQL。
…(truncated)