mcpField
S
skill-system-memory

skill-system-memory

github.com/arthur0824haoAgent 工作流99 次安装
代码仓库

关于 skill-system-memory

skill-system-memory 为 AI Agent 提供基于 PostgreSQL 的持久共享记忆,并支持按项目隔离。它包含可选的 MCP 服务,可供 Agent 搜索、写入和管理记忆。

主要功能

  1. 01PostgreSQL 持久记忆
  2. 02按项目隔离数据库
  3. 03混合检索记忆
  4. 04管理记忆上下文与状态
  5. 05支持显式跨库读取

适用场景

  1. 01在会话间保存 Agent 记忆
  2. 02从项目记忆中检索信息
  3. 03重建压缩或丢失的上下文

MCP 相关

内置 MCP 服务,向客户端提供记忆搜索、存储、更新、删除、上下文和状态等工具,并提供数据库结构与状态资源。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/arthur0824hao/skills --skill skill-system-memory

安装后在 Claude Code 中输入/skill-system-memory确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

SKILL.behavior.yaml
SKILL.meta.yaml
SKILL.spec.yaml
ans-myelin-bridge-contract.yaml
close-report-ingestion-runbook.md
init.sql
mcp.json
memory-mirror-config.yaml
memory-mirror-contract.md
migrate-v2-postgres-first.sql
myelin-registry.schema.yaml
myelin-seeds.yaml
schema-diagram.md
artifacts/
myelin-registry.json
hooks/
log-compaction.ps1
log-compaction.sh
memory-rebuild-reminder.sh
test_log_compaction.py
test_memory_rebuild_reminder.py
mcp/
requirements.txt
server.py
test_mcp_server.py
plugins/
runtime_sync.js
runtime_sync.test.mjs
skill-system-memory.js
scripts/
auto-write-template.md
bootstrap.ps1
bootstrap.sh
consolidate-compactions.ps1
consolidate-compactions.sh

详细介绍

技能系统记忆(PostgreSQL)

为所有 AI Agent 提供持久化共享记忆。支持 Linux 或 Windows 上的 PostgreSQL 14+。 记忆故障看起来就像智能故障——此技能可确保在合适的时机检索到正确的记忆。

约定说明:

  • 模块优先:mem.py 和 MCP 工具是主要的运行时接口。
  • 插件可选:OpenCode 插件集成是一个适配层,并非必需依赖。
  • 优先使用项目范围的数据库命名:<project>-memory(例如 skills-memory)。

数据库目标 — 项目隔离

技能是全局安装的,但记忆是项目范围的。隔离在数据库级别实现:每个项目都有自己的 PostgreSQL 数据库,命名为 <project>-memory。

跨数据库回忆是一项显式的读取侧功能,而非默认模式。除非调用方通过 scope=all 或 cross_db=true 选择启用,否则搜索和上下文读取都只访问当前记忆数据库。所有写入路径始终固定到本地 SKILL_PGDATABASE 目标。

搜索路径角色架构(SK-C)

兼容的部署路径采用增量方式:

  • 旧版模式仍使用每个项目一个数据库:SKILL_PGDATABASE=<project>-memory
  • 共享数据库模式使用显式指定的共享数据库,并通过 schema 实现隔离
  • 运行时角色拆分为 admin、connector 和 visitor_<identity>

角色模型:

  • admin:仅用于迁移/初始化;创建 schema、授权和角色
  • connector:仅有 CONNECT 权限的凭据;打开数据库连接后立即执行 SET ROLE
  • visitor_<identity>:日常查询角色,强制使用 search_path

Visitor search_path 矩阵:

  • visitor_hermes:ep_scope, sk_scope, fd_scope, work_scope, public
  • visitor_atlas:ep_scope, public
  • visitor_athena:sk_scope, public
  • visitor_fd_coder:fd_scope, public
  • visitor_ep_coder:ep_scope, public
  • visitor_sk_coder:sk_scope, public
  • visitor_hephaestion:work_scope, sk_scope, public

共享数据库模式是显式且向后兼容的:

  • SKILL_PGSHARED_DB=<shared-db-name> 选择共享数据库
  • SKILL_PGSCHEMA=<scope-schema> 选择本地可写 schema
  • SKILL_PGDATABASE 在旧版的每个项目一个数据库模式下仍然有效

共享数据库模式下的运行时流程:

  1. 以 connector 身份连接
  2. 执行 SET ROLE visitor_<identity>
  3. 依靠 visitor 的 search_path 进行范围限定的查询
  4. 仅允许 Hermes 显式覆盖设置,以执行全范围审计查询

共享数据库示例:

# 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

跨数据库可见性约定

  • visibility=private(默认):只能在记忆所在的数据库内搜索;没有 visibility 字段的旧记录按 private 处理
  • visibility=shared:显式启用联邦查询时,可跨已配置的记忆数据库搜索
  • visibility=global:可跨已配置的记忆数据库搜索,也可用于跨数据库自动注入上下文
  • 跨数据库结果必须包含 source_db
  • 跨数据库排序使用归一化融合(RRF 风格),而非直接比较各数据库的原始分数
  • 已知的数据库扇出目标配置在 config/insight.yaml 的 memory.cross_db_targets 下
  • 即使启用了读取侧跨数据库联邦查询,所有变更路径(store、update、delete、purge)仍仅作用于当前 SKILL_PGDATABASE 目标
自动检测(推荐)

未设置环境变量时,会根据项目目录名称自动推导数据库名称:

  • 插件(JS):使用 OpenCode 主机传入的 directory → 最后一个路径段 → <dir>-memory
  • mem.py CLI:使用脚本的根目录或当前工作目录 → <dir>-memory
  • MCP 服务:在启动时使用 Path.cwd() → <dir>-memory

请勿全局设置 SKILL_PGDATABASE。 它会覆盖所有项目的自动检测结果。

# 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
按项目覆盖(必要时)

如果必须覆盖,请在项目级别而非全局设置 SKILL_PGDATABASE:

  • 在项目的 .opencode 配置或启动脚本中
  • 在项目的 .env 文件中(如果你的主机读取该文件)
  • 作为命令前缀:SKILL_PGDATABASE=FraudDetect-memory opencode
故障时拒绝连接策略

如果设置了 PGDATABASE,但未设置 SKILL_PGDATABASE,所有入口点都会拒绝连接。这可以防止不同项目的记忆意外混杂。

多项目设置的 MCP 服务路径

如果技能全局安装在 ~/.agents/skills/,请将 MCP 配置为指向全局安装目录的绝对路径:

{
  "skill-system-memory": {
    "command": "python3",
    "args": ["~/.agents/skills/skill-system-memory/mcp/server.py"]
  }
}

请勿使用 skills/skill-system-memory/mcp/server.py 这类相对路径——在没有本地 skills/ 目录的项目中,这类路径会失效。

快速开始

数据库 <project>-memory 和所有函数均由此技能目录中的 init.sql 创建。 当前支持的运行时范围涵盖核心记忆、类型化上下文读取、类型化演进账本,以及 doctor/压缩支持。 会话/项目/上下文投影表和行为图刷新仍是由能力门控的可选功能,并非无条件保证的运行时功能。

# 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

注意:如果你的 PostgreSQL 安装中没有 postgres 角色,请使用实际的 PostgreSQL 超级用户名称。在许多 Linux 发行版中,该名称与操作系统用户名相同。 你可以随时在运行脚本前设置 PGUSER 来覆盖:export PGUSER=your_pg_username(Linux/macOS),或 $env:PGUSER = "your_pg_username"(PowerShell)。

验证:SELECT * FROM memory_health_check();

MCP 服务(阶段 6.1)

此技能包含一个 MCP(Model Context Protocol)服务,可将记忆操作作为 Agent 工具提供。

MCP 服务设置
# 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 环境变量
变量默认值说明
SKILL_PGDATABASE<project>-memory传统的每项目一个 PostgreSQL 数据库名称
SKILL_PGSHARED_DB(未设置)search_path 模式下共享的 PostgreSQL 数据库名称
SKILL_PGSCHEMA(未设置)search_path 模式下本地可写的 schema
PGHOSTlocalhostPostgreSQL 主机
PGPORT5432PostgreSQL 端口
PGUSER(可选)PostgreSQL 用户
MCP_TRANSPORTstdio传输模式(stdio 或 sse)
MCP_PORT8000SSE 传输端口
MCP 工具
工具说明
memory_search按自然语言查询搜索记忆(混合方式:FTS + trigram + pgvector)
memory_store存储新记忆,自动去重并隔离本地写入
memory_update按 ID 更新本地记忆行中的选定字段,并记录审计日志
memory_delete按 ID 软删除本地记忆行,并记录审计日志
memory_purge仅在明确授权后,硬删除本地记忆行
memory_auto_match根据输入文本自动匹配记忆,并写入 .sisyphus/tmp/mem-{session}.md
memory_context获取用户上下文(灵魂状态、偏好、近期特征)
memory_status检查记忆系统健康状况(连接、schema、pgvector)
ingest-close-reports将收件箱关闭报告解析为结构化的情景记忆候选项或写入记录
backfill-embeddings修复 pgvector 后,为现有记忆补齐缺失的向量嵌入
myelin_search按意图/上下文搜索 myelin 适配注册表,并仅返回 top-k 封装器/反射
myelin_get获取一条包含完整元数据的适配记录
myelin_validate根据参数和防护规则验证一条适配记录
debug_diagnose通过统一 MCP 服务运行调试工具诊断
eda_profile通过统一 MCP 服务运行 EDA 数据集分析
gate_validate通过统一 MCP 服务运行门控验证
memory_rebuild压缩或记忆丢失后重建完整的 Agent 上下文
MCP 资源
资源说明
memory://schema记忆数据库 schema 信息
memory://status当前记忆系统状态
MCP Agent 集成

要将 MCP 服务用于 Agent,请配置 Agent 的 MCP 设置,添加以下内容:

{
  "mcpServers": {
    "skill-system": {
      "command": "python",
      "args": ["skills/skill-system-memory/mcp/server.py"],
      "env": {
        "SKILL_PGDATABASE": "<project>-memory"
      }
    }
  }
}

共享数据库 MCP 示例:

{
  "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 工具示例
# Search memories
mcp_tool: memory_search
args: { "query": "pgvector installation", "limit": 5 }

# Search memories with full content for the returned top-k rows
mcp_tool: memory_search
args: { "query": "pgvector installation", "limit": 5, "mode": "full" }

# 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 }

# Auto-match without hiding low-score candidates
mcp_tool: memory_auto_match
args: { "text": "I'm seeing an error with database connections", "threshold": 0.8, "include_below_threshold": true, "limit": 5, "mode": "full" }

# Get user context
mcp_tool: memory_context
args: { "user": "default" }

# Check system health
mcp_tool: memory_status
args: {}

对于现有安装,也请运行:

psql -U postgres -d <project>-memory -v ON_ERROR_STOP=1 -f migrate-v2-postgres-first.sql

纯 Skill 模式(默认)

此 Skill 无需安装任何插件即可运行。在纯 Skill 模式下:

  • 需要时手动运行脚本(渐进式披露)
  • 不会自动修改全局 OpenCode 配置
可选的引导程序(询问并记录选择 + 尝试安装)

注意:

  • 交互模式默认不安装占用资源较多的可选组件。
  • 只有在准备好安装所有内容时,才使用 -InstallAll / --install-all。

运行引导脚本以选择可选组件(pgpass、本地嵌入、pgvector)并记录选择。

引导程序还可以选择安装 OpenCode 压缩日志插件(会将插件复制到 OpenCode 插件目录)。

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"

选择记录存储于:

  • ~/.config/opencode/skill-system-memory/setup.json

Agent 规则:

  • 如果此文件不存在,询问用户是否要启用可选组件。
  • 建议:启用所有选项运行引导程序(然后修复它报告的任何失败)。

运行时能力模型

当前的实时能力分类刻意保持精简:

能力当前状态当前支持范围
core_memorySUPPORTED_NOWagent_memories 以及 store_memory、search_memories、memory_health_check
evolution_ledgerSUPPORTED_NOWevolution_snapshots 以及 insert_evolution_snapshot、get_evolution_history
compaction_logging在同步仓库插件时为 SUPPORTED_NOW本地 JSONL 压缩日志,以及受保护的 store_memory(...) 写回
typed_context_readsSUPPORTED_NOWget_agent_context、get_soul_state、get_recent_facets、get_user_preferences
runtime_sync_projectionsGATED_OPTIONAL仅当这些表存在时提供 session_summaries、project_summaries、context_rollups
behavior_refresh_graphGATED_OPTIONAL仅当这些表存在时提供 behavior_* 刷新
control_plane_refreshDEFERRED_UNSUPPORTED不属于当前面向用户的记忆运行时

存在持久化演进提案模型时,doctor 还会报告:

  • 规范的已接受存储:evolution_nodes
  • 规范的已拒绝存储:evolution_rejections
  • 规范的任务物化:evolution_tasks -> agent_tasks
  • agent_memories 的角色:可搜索的摘要/反向引用范围,包含明确的旧版兼容行
  • 批准/拒绝路径状态:在 CLI 边界具备事务安全性
  • 迁移/回填幂等性:可安全重复运行
  • 决策重放状态:通过 proposal_id 实现重放幂等
  • 协调机制:按提案使用 advisory lock,并在规范的已接受/已拒绝行上使用语义指纹
  • 负载不匹配策略:阻止操作且不做任何修改
  • 终态冲突策略:阻止操作且不做任何修改
  • 任务权威模型:agent_tasks 负责生命周期权威管理,evolution_tasks 仅用于映射

在此状态下,evolution_snapshots 对提案持久化被视为 LEGACY_COMPAT_SURFACE,同时仍用于快照/版本历史。

在 Windows 上,pgvector 安装遵循官方 pgvector 说明(Visual Studio C++ + nmake /F Makefile.win)。引导程序将尝试通过 winget 安装先决条件。

可选自动化:压缩日志记录(OpenCode 插件)

如果需要自动记录压缩日志,请安装此技能附带的 OpenCode 插件模板。

选项 A(推荐):运行 bootstrap 并选择插件选项。

  1. 将 plugins/skill-system-memory.js 和 plugins/runtime_sync.js 复制到 ~/.config/opencode/plugins/
  2. 重启 OpenCode

安全措施/回滚(如果 OpenCode 在启动时卡住):

  • 移除或重命名 ~/.config/opencode/plugins/skill-system-memory.js
  • 移除或重命名 ~/.config/opencode/plugins/runtime_sync.js
  • 重启 OpenCode
  • 查看日志:
    • macOS/Linux:~/.local/share/opencode/log/
    • Windows:%USERPROFILE%\.local\share\opencode\log

插件行为说明:

  • 除非通过 bootstrap 明确启用(setup.json 设置 selected.opencode_plugin=true),否则该插件不会执行任何操作。
  • 仅当 selected.pgpass=true 时才会尝试写入 Postgres(避免在身份验证提示处卡住)。
  • 压缩时,只要数据库目标有效,插件始终会保留本地 JSONL 日志记录以及核心 store_memory(...) 路径。
  • 运行时投影 upsert(session_summaries、project_summaries、context_rollups)受功能检测控制:如果这些表不存在,插件会跳过操作并明确说明原因,而不是尝试写入。
  • 将行为图刷新到 behavior_* 表也受功能检测控制;如果缺少必需的表,插件会明确跳过此操作。

卸载:

  • 移除 ~/.config/opencode/plugins/skill-system-memory.js
  • 移除 ~/.config/opencode/plugins/runtime_sync.js
  • 重启 OpenCode

凭据(psql)

不要在脚本、技能文档或配置文件中硬编码密码。

非交互式 psql 的推荐选项:

  • .pgpass / pgpass.conf(推荐)
    • Linux/macOS:~/.pgpass(必须执行 chmod 0600 ~/.pgpass,否则 libpq 会忽略它)
    • Windows:%APPDATA%\postgresql\pgpass.conf(示例:C:\Users\<you>\AppData\Roaming\postgresql\pgpass.conf)
    • 格式:hostname:port:database:username:password
    • 文档:https://www.postgresql.org/docs/current/libpq-pgpass.html
  • PGPASSFILE(可选覆盖项):指向密码文件的自定义位置
  • PGPASSWORD(不推荐):仅用于快速本地测试;在某些系统上,环境变量可能会泄露

提示:每个 shell 只需设置一次连接默认值,即可缩短命令:

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 复制粘贴安全提示:

  • 避免将行内 Markdown 反引号(例如 semantic)复制到 shell 中。在 zsh 中,反引号会进行命令替换。
  • 建议使用包装脚本(scripts/mem.sh、scripts/mem.ps1),或从围栏代码块中复制。
一次性设置辅助脚本

此技能附带辅助脚本(相对路径):

  • scripts/setup-pgpass.ps1
  • scripts/setup-pgpass.sh

OpenCode 用法:从技能目录运行这些脚本。

Windows 运行:

powershell.exe -NoProfile -ExecutionPolicy Bypass -File "scripts\setup-pgpass.ps1"

Linux/macOS 运行:

bash "scripts/setup-pgpass.sh"

记忆类型

类型生命周期使用场景
working24 小时后自动过期当前对话上下文(需要 session_id)
episodic永久保存 + 衰减问题解决经验、调试会话
semantic永久保存提取的事实、知识、模式
procedural永久保存分步流程、检查清单(重要性 >= 7)

核心函数

store_memory(type, category, tags[], title, content, metadata, agent_id, session_id, importance)

根据内容哈希自动去重。重复插入会增加 access_count 和 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
);
包装器:scripts/mem.py(推荐——参数化查询,无 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 "pgvector windows install" --limit 5 --mode full
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

回退行为:

  • DB 连接失败时,store 会降级写入 .memory/pending/*.json,search / context 会读取本地 pending 文件并打印警告
  • list / export 也会从 pending 回退读取;DB 不可用时,compact 只打印警告,不会崩溃
  • DB 可连接但 memory schema 缺失时,store 会发出警告并不执行操作,search / context / tags / categories 会返回空结果并发出警告
  • DB 恢复后,flush 会将 .memory/pending/ 的内容写回 PostgreSQL

作用域模型:

  • session(默认):记录在 metadata.scope=session,并尽可能带上 session_id
  • project:记录在 metadata.scope=project + metadata.project_id=<repo>
  • global:记录在 metadata.scope=global,仍需明确执行联邦读取才会跨 DB 查询
  • search / list / export 不带 --scope 时,会返回所有作用域,并在结果中标记来源作用域

可见性与作用域不同:

  • private(默认):仅本地 DB
  • shared:可用于显式跨 DB 搜索
  • global:可用于显式跨 DB 搜索和自动上下文注入

变更审计规则:

  • update 仅写入选定字段的变更,且仅写入本地 DB
  • delete 仅执行软删除(deleted_at),保留向后兼容的读取方式
  • purge 执行硬删除,且必须获得明确授权
  • 每次变更都会写入一条 memory_audit 记录,包含旧值/新值及操作者元数据

CLI 变更示例:

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 是这些操作的规范变更记录。每条记录包含:

  • memory_id
  • action(update、delete、purge)
  • old_value
  • new_value
  • actor_id
  • session_id
  • changed_at

警告:purge 会造成破坏性影响,并绕过软删除恢复机制。它仅限本地操作,且需要明确的授权标志;请勿将其用于常规清理。

已知的联邦读取目标在 config/insight.yaml 中配置:

memory:
  cross_db_targets:
    - Work-memory
    - skills-memory
    - ExperimentPipeline-memory
    - FraudDetect-memory
  cross_db_context_visibility:
    - global

此列表仅控制显式读取的扇出范围。即使调用方传入类似 target_db 的数据,写入路径仍会指向本地 SKILL_PGDATABASE 数据库。

包装器:scripts/mem.sh / scripts/mem.ps1(Shell 回退)
# 連線狀態
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 技能,它可以读取嵌入在此 SKILL.md 中的清单。

为确保可移植性,清单块采用 YAML 围栏格式,但内容是 JSON(有效的 YAML)。Router 会对其进行解析。

{
  "schema_version": "2.0",
  "id": "skill-system-memory",
  "version": "1.0.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-mirror-capture", "memory-reconcile-note-live", "memory-ingest-close-reports", "memory-backfill-embeddings", "myelin-search", "myelin-get", "myelin-validate", "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"]
      }
    },
    "mirror-capture": {
      "description": "Mirror changed decision-critical file sections into the selected project memory DB with fail-open behavior.",
      "input": {
        "file": { "type": "string", "required": true, "description": "Changed file path" },
        "content": { "type": "string", "required": false, "description": "New file content" },
        "content_file": { "type": "string", "required": false, "description": "Path containing new file content" },
        "old_content": { "type": "string", "required": false, "description": "Previous file content" },
        "old_content_file": { "type": "string", "required": false, "description": "Path containing previous file content" },
        "config": { "type": "string", "required": false, "description": "Whitelist config path" },
        "pattern": { "type": "string", "required": false, "description": "Additional whitelist glob pattern" },
        "work_root": { "type": "string", "required": false, "description": "Optional root for relative whitelist matching" },
        "db_target": { "type": "string", "required": false, "description": "Explicit project memory DB target" },
        "log_path": { "type": "string", "required": false, "description": "Caller-configurable JSONL log path" },
        "pane": { "type": "string", "required": false, "description": "Origin pane/session metadata" },
        "dry_run": { "type": "boolean", "required": false, "default": false }
      },
      "output": {
        "description": "Mirror result with changed sections, store ids, and fail-open warnings",
        "fields": { "status": "ok | warn | error", "sections": "array", "store_ids": "array", "errors": "array" }
      },
      "entrypoints": {
        "unix": ["python3", "scripts/memory_mirror.py", "capture"],
        "windows": ["python", "scripts/memory_mirror.py", "capture"]
      }
    },
    "reconcile-note-live": {
      "description": "Reconcile live note decisions against memory backrefs before compact or close flows.",
      "input": {
        "note_file": { "type": "string", "required": true, "description": "Path to note_live style markdown" },
        "db_target": { "type": "string", "required": false, "description": "Explicit project memory DB target" },
        "log_path": { "type": "string", "required": false, "description": "Caller-configurable JSONL log path" },
        "pane": { "type": "string", "required": false, "description": "Origin pane/session metadata" },
        "dry_run": { "type": "boolean", "required": false, "default": false },
        "strict": { "type": "boolean", "required": false, "default": false },
        "store_missing": { "type": "boolean", "required": false, "default": true }
      },
      "output": {
        "description": "Reconcile result including checked titles, missing backrefs, and auto-store ids",
        "fields": { "status": "ok | warn | error", "checked_titles": "array", "missing_titles": "array", "store_ids": "array" }
      },
      "entrypoints": {
        "unix": ["python3", "scripts/memory_mirror.py", "reconcile"],
        "windows": ["python", "scripts/memory_mirror.py", "reconcile"]
      }
    },
    "ingest-close-reports": {
      "description": "Parse milestone close reports from inbox markdown and ingest them into episodic memory with dedup.",
      "input": {
        "inbox": { "type": "string", "required": true, "description": "Path to inbox markdown file" },
        "dry_run": { "type": "boolean", "required": false, "default": false },
        "limit": { "type": "integer", "required": false }
      },
      "output": {
        "description": "Structured candidates, stored ids, and dedup skips",
        "fields": { "status": "ok | error", "candidate_count": "integer", "candidates": "array", "stored_ids": "array", "skipped": "array" }
      },
      "entrypoints": {
        "unix": ["python3", "scripts/mem.py", "ingest-close-reports"],
        "windows": ["python", "scripts/mem.py", "ingest-close-reports"]
      }
    },
    "backfill-embeddings": {
      "description": "Backfill missing vector embeddings for existing memories after pgvector repair.",
      "input": {
        "limit": { "type": "integer", "required": false, "default": 50 },
        "model": { "type": "string", "required": false }
      },
      "output": {
        "description": "Updated ids, skipped ids, and provider/model summary",
        "fields": { "status": "ok | error", "updated_count": "integer", "updated_ids": "array", "skipped": "array" }
      },
      "entrypoints": {
        "unix": ["python3", "scripts/mem.py", "backfill-embeddings"],
        "windows": ["python", "scripts/mem.py", "backfill-embeddings"]
      }
    },
    "myelin-search": {
      "description": "Search the myelin affordance registry by intent/context and return top-k relevant wrappers/reflexes.",
      "input": {
        "intent": { "type": "string", "required": true, "description": "Intent label such as dispatch, inbox, or EP-status" },
        "context": { "type": "string", "required": false, "description": "Free text or JSON context payload" },
        "limit": { "type": "integer", "required": false, "default": 5 }
      },
      "output": {
        "description": "Ranked affordance results with guard warnings and bridge metadata",
        "fields": { "status": "ok | error", "results": "array", "warnings": "array", "bridge_contract": "object" }
      },
      "entrypoints": {
        "unix": ["python3", "scripts/myelin_registry.py", "search", "{intent}"],
        "windows": ["python", "scripts/myelin_registry.py", "search", "{intent}"]
      }
    },
    "myelin-get": {
      "description": "Get one affordance record with full metadata.",
      "input": {
        "id": { "type": "string", "required": true, "description": "Affordance identifier" }
      },
      "output": {
        "description": "Affordance record",
        "fields": { "status": "ok | error", "record": "object" }
      },
      "entrypoints": {
        "unix": ["python3", "scripts/myelin_registry.py", "get", "{id}"],
        "windows": ["python", "scripts/myelin_registry.py", "get", "{id}"]
      }
    },
    "myelin-validate": {
      "description": "Validate one affordance against args and guard raw-shell fallbacks.",
      "input": {
        "id": { "type": "string", "required": true },
        "args": { "type": "string", "required": false, "description": "JSON args/context payload" }
      },
      "output": {
        "description": "Validation result",
        "fields": { "status": "ok | error", "valid": "boolean", "warnings": "array", "missing_required_context": "array" }
      },
      "entrypoints": {
        "unix": ["python3", "scripts/myelin_registry.py", "validate", "{id}"],
        "windows": ["python", "scripts/myelin_registry.py", "validate", "{id}"]
      }
    },
    "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, myelin, 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", "myelin_search", "myelin_get", "myelin_validate", "debug_diagnose", "eda_profile", "gate_validate", "memory_rebuild"],
      "resources": ["memory://schema", "memory://status"]
    }
  }
}

说明:

  • Router 要求每个步骤都打印最后一行 JSON。
  • 这些 Router 适配器脚本与 mem.sh / mem.ps1 分开,以避免破坏现有工作流。

Memory Mirror 引擎(SK-005)

scripts/memory_mirror.py 是由 SK 负责的故障开放引擎,用于自动镜像记忆并在压缩前进行协调。

python3 scripts/memory_mirror.py capture --file Work/note/note_live.md --content-file /tmp/new.md --old-content-file /tmp/old.md --db-target Work-memory --log-path Work/.tkt/memory-mirror.log
python3 scripts/memory_mirror.py reconcile --note-file Work/note/note_live.md --db-target Work-memory --log-path Work/.tkt/memory-mirror.log
  • 默认白名单位于 memory-mirror-config.yaml
  • Work 负责的包装器应明确传入 --db-target Work-memory
  • 结构化日志输出为 JSONL,且可由调用方配置
  • 决策日志事务加固契约见 memory-mirror-contract.md

Close Report 摄取

./sk mem ingest-close-reports --inbox /share/nas165/arthur0824hao/Work/.tkt/inbox/hermes/inbox.md --dry-run
./sk mem ingest-close-reports --inbox /share/nas165/arthur0824hao/Work/.tkt/inbox/hermes/inbox.md
  • 目的:将里程碑关闭/阻塞报告转为可搜索的情景记忆
  • 去重:使用 bundle id + actor + timestamp + report status 作为摄取键
  • 操作手册:close-report-ingestion-runbook.md

向量 / 嵌入健康状态

memory_status 现在将语义/向量检索视为受能力门控的可选健康功能:

  • pgvector_enablement_status:enabled | disabled | unavailable-on-host
  • pgvector_blocker:不可用时的确切主机/安装阻碍
  • embedding_dependency_installed:本地嵌入运行时是否存在
  • semantic_search_mode:hybrid-ready | hybrid-schema-no-vectors | vector-installable-but-disabled | fts-trgm-only

当 pgvector 或 sentence-transformers 不存在时,FTS + pg_trgm 回退仍是默认安全路径。

语义检索修复命令

SKILL_PGDATABASE=Work-memory python3 scripts/mem.py backfill-embeddings --limit 100
SKILL_PGDATABASE=Work-memory python3 scripts/semantic_smoke.py --db-target Work-memory
  • 加载 sentence-transformers 模型时,mem.py 现在默认禁用 HuggingFace Xet,以避免 CAS 重试故障;该故障曾阻止在当前 MCP 环境中冷下载 all-MiniLM-L6-v2。
  • semantic_smoke.py 会存储一条改述后的语义记忆,并用一种非平凡的表述查询它,以验证混合检索路径。

Codex MCP 传输恢复备用方案

如果原生 MCP 会话报告 Transport closed,请先在 MCP 之外使用规范 CLI/脚本:

python3 scripts/mcp_health_probe.py --db-target Work-memory --tool-error "Transport closed"
python3 scripts/mem_work.py status
python3 scripts/mem_work.py search "Hermes inbox triage latest 14:35 Talos Sisyphus Daedalus memory MCP fallback mem.py" --limit 5
python3 scripts/mem_work.py store --type episodic --category scratch --title "transport recovery check" --content "explicit fallback path" --scope project
  • mem_work.py 是对规范 mem.py 的轻量封装
  • 它会注入 SKILL_PGDATABASE=Work-memory、PGDATABASE=Work-memory、PGHOST=localhost 和 PGPORT=5432
  • Finch/Wren 的备用方案请使用它,无需每次手动输入环境变量

恢复规则(故障时关闭):

  • 如果 mcp_health_probe.py 返回 diagnosis=client_transport_stale,则无法纯粹在服务端修复当前客户端/工具传输。
  • 不要盲目终止记忆 MCP 进程,也不要重启无关的窗格。
  • 仅重启受影响的客户端会话/工具传输(经操作员批准),然后重新验证:
    1. MCP memory_status 恢复正常
    2. python3 scripts/mem_work.py status 保持健康
    3. nvidia-smi --query-compute-apps 显示 GPU0 上没有 skill-system-memory 支持上下文

Myelin Registry + ANS Bridge

scripts/myelin_registry.py 将 SK MCP 转换为髓鞘索引/可供性接口。

python3 scripts/myelin_registry.py build --output artifacts/myelin-registry.json
python3 scripts/myelin_registry.py search dispatch --context '{"pane":"dev_coder:SK-coder","message_file":"/tmp/spec.txt"}' --limit 3
python3 scripts/myelin_registry.py get dispatch:hermes-dispatch
python3 scripts/myelin_registry.py validate cli:raw-tmux-sendkeys --args '{"pane":"dev_coder:SK-coder","message":"hi","intent":"dispatch","urgent":false}'
  • 元数据架构:myelin-registry.schema.yaml
  • 预置的高价值可供性:myelin-seeds.yaml
  • ANS 事件/响应契约:ans-myelin-bridge-contract.yaml
  • 策略:索引所有可供性,仅按意图/上下文注入最相关的 top-k 项

可视化记忆(Markdown 导出)

如果查询 PostgreSQL 对日常使用来说太不方便,可以将记忆导出到 ./Memory/ 下的 Markdown 文件中(默认使用当前目录):

bash "<skill-dir>/scripts/sync_memory_to_md.sh" --out-dir "./Memory"

输出:

  • Memory/Long.md(语义 + 程序性)
  • Memory/Procedural.md(仅程序性)
  • Memory/Short.md(摩擦 + 每日压缩 + 程序性要点)
  • Memory/Episodic.md(情景性)

备份:

  • 备份存储在 Memory/.backups/ 下,以避免 git status 输出过多内容。
  • 使用 --no-backup 禁用备份。

如果 Memory/.gitignore 不存在,同步脚本也会创建该文件(忽略 .backups/ 和 SYNC_STATUS.txt)。

长记忆索引:

  • Memory/Long.md 包含一个 Index 部分(主要类别 + 标签),便于浏览导出内容。
search_memories(query, types[], categories[], tags[], agent_id, min_importance, limit)

混合搜索:全文搜索(tsvector)+ 三元组相似度(pg_trgm)+ 标签筛选。 接受自然英语查询——无需 tsquery 语法。 相关性评分: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
);

返回:id, memory_type, category, title, content, importance_score, relevance_score, match_type 其中 match_type 的值包括:fulltext、trigram_title、trigram_content、metadata。

memory_health_check()

返回 metric | value | status,对应 total_memories、avg_importance、stale_count。

apply_memory_decay()

按 0.9999^days_since_access 衰减情景记忆。每日运行。

prune_stale_memories(age_days, max_importance, max_access_count)

软删除低于阈值的陈旧情景记忆。默认值:180 天、重要性 <= 3、从未访问。

Agent 工作流

自动写入模板

修复 bug 或解决非显而易见的问题后,使用标准模板存储记忆:

  • 流程:scripts/auto-write-template.md

最佳实践:优先使用 mem.py wrapper,避免 shell quoting 与认证问题。 Raw SQL 范例请见 Appendix: Raw SQL。

任务开始前
# 自動撈出相關記憶摘要(推薦)
python3 scripts/mem.py context "keywords from user request"

# 或搜尋並手動閱讀
python3 scripts/mem.py search "keywords from user request" 5

如果找到相关记忆,请引用它们:“根据以往经验(记忆 #1)……”

解决问题后
python3 scripts/mem.py store semantic category-name "One-line problem summary" \
  "tag1,tag2,tag3" 8 --content "Detailed problem + solution"
委派给子 Agent 时

在提示词中包含:

MUST DO FIRST:
  python3 scripts/mem.py context 'relevant keywords'

MUST DO AFTER:
  If you solved something new:
  python3 scripts/mem.py store semantic <category> '<title>' '<tags>' <importance> --content '<solution>'
检查记忆系统健康状况
python3 scripts/mem.py status

任务记忆层(可选)

此技能还提供一个受 Beads 启发的精简任务/问题层:图语义 + 确定性的“就绪任务”查询。

对象:

  • agent_tasks:任务(状态、优先级、负责人)
  • task_links:类型化链接(blocks、parent_child、related 等)
  • blocked_tasks_cache:物化缓存,用于加快就绪任务查询
  • task_memory_links:将任务链接到记忆(agent_memories),以记录结果/备注

创建任务:

INSERT INTO agent_tasks(title, description, created_by, priority)
VALUES ('Install pgvector', 'Windows build + enable extension', 'user', 1);

添加依赖:

-- Task 1 blocks task 2
INSERT INTO task_links(from_task_id, to_task_id, link_type)
VALUES (1, 2, 'blocks');

-- Task 2 is parent of task 3 (used for transitive blocking)
INSERT INTO task_links(from_task_id, to_task_id, link_type)
VALUES (2, 3, 'parent_child');

重建阻塞缓存(通常由触发器自动完成):

SELECT rebuild_blocked_tasks_cache();

就绪任务查询:

SELECT id, title, priority
FROM agent_tasks t
WHERE t.deleted_at IS NULL
  AND t.status IN ('open','in_progress')
  AND NOT EXISTS (SELECT 1 FROM blocked_tasks_cache b WHERE b.task_id = t.id)
ORDER BY priority ASC, updated_at ASC
LIMIT 50;

认领任务(原子操作):

SELECT claim_task(2, 'agent-1');

将任务链接到记忆:

INSERT INTO task_memory_links(task_id, memory_id, link_type)
VALUES (2, 123, 'outcome');

可选扩展:conditional_blocks(尚未实现)

  • 这是有意推迟的,直到核心工作流足够稳定。
  • 如果现在就需要,可将条件存储在 task_links.metadata 中(例如,{ "os": "windows" }),并将其作为文档说明处理。
包装脚本(推荐)

为避免反复输入 SQL,请使用此技能附带的包装脚本:

Windows:

powershell.exe -NoProfile -ExecutionPolicy Bypass -File "scripts\tasks.ps1" ready 50
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "scripts\tasks.ps1" create "Install pgvector" 1
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "scripts\tasks.ps1" claim 2 agent-1

Linux/macOS:

bash "scripts/tasks.sh" ready 50
bash "scripts/tasks.sh" create "Install pgvector" 1
bash "scripts/tasks.sh" claim 2 agent-1

压缩日志(高价值)

压缩可能会删除上下文。请将每次压缩都视为重要事件并记录下来。

如果你使用 OpenCode,建议优先采用 OpenCode 插件方式自动记录压缩日志。

OpenCode 插件(experimental.session.compacting)
  1. 将 plugins/skill-system-memory.js 和 plugins/runtime_sync.js 复制到 ~/.config/opencode/plugins/
  2. 重启 OpenCode

它会将本地压缩事件写入:

  • ~/.config/opencode/skill-system-memory/compaction-events.jsonl

它还会尽力写入 Postgres store_memory(...)(需要 pgpass)。

验证
SELECT id, title, relevance_score
FROM search_memories('compaction', NULL, NULL, NULL, NULL, 0, 10);

如果没有插入任何内容,请设置 .pgpass / pgpass.conf,以便 psql 无需提示即可进行身份验证。

每日压缩整合

原始压缩事件内容杂乱。请运行每日整合作业,将多个压缩事件合并为一条每日记忆。

整合脚本默认使用 OpenCode 插件事件日志路径。

  • OpenCode 事件:~/.config/opencode/skill-system-memory/compaction-events.jsonl
  • 输出目录:~/.config/opencode/skill-system-memory/compaction-daily/

Windows 手动运行:

powershell.exe -NoProfile -ExecutionPolicy Bypass -File "scripts\consolidate-compactions.ps1"

Linux/macOS 手动运行:

bash "scripts/consolidate-compactions.sh"

计划任务:

  • Windows 任务计划程序:创建一个每日任务,运行上方的 PowerShell 命令
  • Linux cron 示例:
# every day at 02:10 UTC
10 2 * * * bash "<skill-dir>/scripts/consolidate-compactions.sh" >/dev/null 2>&1

摩擦日志(将痛点转化为工具)

每当遇到令人烦恼、脆弱或失败的情况时:

  1. 存储一条类别为 friction、标签包含工具/操作系统/错误信息的 episodic 记忆。
  2. 如果重复出现(2 次以上),将其提升为 procedural 记忆(重要性 >= 7),并附上检查清单。
  3. 当修复方案成为稳定的规则/工作流时,更新此技能文档(让每个 Agent 都能学到)。

架构概览

agent_memories — 通用事件日志。全文搜索、三元组索引、JSONB 元数据、软删除。 soul_states — 每位用户一行。包含结构化的个性/情绪/缓冲区 JSONB。外键 → agent_memories。 insight_facets — 每个会话的特征,包含结构化字段。外键 → agent_memories。 evolution_snapshots — 带有变更 JSONB 的版本化演进记录。外键 → agent_memories。当前状态:用于提案持久化的 LEGACY_COMPAT_SURFACE,同时仍用于快照/版本历史记录。 user_preferences — 带有置信度分数的键值型用户偏好。 memory_links — 图关系(引用、取代、矛盾)。 working_memory — 带自动过期机制的临时会话上下文。

类型化表函数(同时写入类型化表和 agent_memories):

  • upsert_soul_state(user, yaml, personality, emotion, ...) → soul_states
  • insert_insight_facet(user, session_id, yaml, ...) → insight_facets
  • insert_evolution_snapshot(user, version_tag, target, ...) → evolution_snapshots
  • upsert_user_preference(user, key, value, source, confidence) → user_preferences
  • get_soul_state(user)、get_recent_facets(user, limit)、get_evolution_history(user, limit)、get_user_preferences(user) → 类型化读取
  • get_agent_context(user, facet_limit) → 用于插件注入的聚合上下文

目前没有由代码仓库支持的 migrate-typed-tables.sql 文件。请将旧版类型化表回填视为已延期;不要声称它是受支持的迁移路径。

可选的 PostgreSQL 优先运行时投影表(session_summaries、project_summaries、context_rollups、behavior_*)由 migrate-v2-postgres-first.sql 创建,前提是你明确选择启用该功能。

关键列:memory_type、category、tags[]、title、content、content_hash(自动生成)、metadata(JSONB)、importance_score、access_count、relevance_decay、search_vector(自动生成)。

反模式

不要应该这样做
什么都存只存储不明显的解决方案
不添加标签全面添加标签:技术、错误代码、平台
直接使用 to_tsquerysearch_memories() 会通过 plainto_tsquery 处理
所有数据只用一种类型根据内容使用正确的 memory_type
忘记重要性评分如实评分:9-10 表示经过实战验证,5-6 表示部分验证

注意事项

问题严重性缓解措施
分块会丢失上下文严重将完整的问题和解决方案作为一个整体存储
过时的技术记忆高每天运行 apply_memory_decay();清除过时内容
重复记忆中store_memory() 会根据 content_hash 自动去重
无向量搜索信息pg_trgm 提供模糊匹配;之后可添加 pgvector

跨平台说明

  • PostgreSQL 14-18 受支持(不使用分区或 GENERATED ALWAYS)
  • pg_trgm 是唯一必需的扩展(随所有 PG 发行版提供)
  • Linux:psql -U postgres -d <project>-memory -f init.sql
  • Windows:使用 psql.exe 的完整路径,或将 PG bin 添加到 PATH
  • MCP postgres_query:可用于读取操作;DDL 需要使用 psql

维护

SELECT apply_memory_decay();                         -- daily
SELECT prune_stale_memories(180, 3.0, 0);            -- monthly
DELETE FROM working_memory WHERE expires_at < NOW();  -- daily
SELECT * FROM memory_health_check();                  -- anytime

可选:pgvector 语义搜索

如果 PostgreSQL 服务上已安装 pgvector,init.sql 将会:

  • 创建扩展 vector(若缺失则不会导致失败)
  • 添加 agent_memories.embedding vector(维度可变)
  • 创建 search_memories_vector(p_embedding, p_embedding_dim, ...)

说明:

  • 这不会生成嵌入。你必须自行填充 agent_memories.embedding。
  • 嵌入数据准备好后,你可以进行最近邻搜索:
-- p_embedding is a pgvector literal; pass it from your app.
-- Optionally filter by dimension (recommended when using multiple models).
SELECT id, title, similarity
FROM search_memories_vector('[0.01, 0.02, ...]'::vector, 768, NULL, NULL, NULL, NULL, 0.0, 10);

注意:pgvector 索引无法为维度可变的向量建立索引。为了支持嵌入维度不同的本地模型,这是一个权衡。

如果未安装 pgvector,其他所有功能仍可正常工作(fts + pg_trgm)。

嵌入向量摄取管道

只有填充 agent_memories.embedding 后,pgvector 搜索才能正常工作。

此技能附带摄取脚本(相对路径)。请在技能目录中运行:

  • scripts/ingest-embeddings.ps1
  • scripts/ingest-embeddings.sh

这些脚本会:

  • 查找 embedding IS NULL 的记忆
  • 调用兼容 OpenAI 的嵌入向量 API 端点(包括 Ollama)
  • 将向量写入 agent_memories.embedding vector

要求:

  • 已安装 pgvector 且已应用 init.sql(以便 agent_memories.embedding 存在)
  • 已配置 .pgpass / pgpass.conf(以便 psql -w 无需提示即可写入)
  • 嵌入向量 API 环境变量:
    • EMBEDDING_PROVIDER(ollama 或 openai;默认值为 openai)
    • EMBEDDING_API_KEY(openai 必需;ollama 可选)
    • EMBEDDING_API_URL(默认值取决于提供方)
    • EMBEDDING_MODEL(默认值取决于提供方)
    • EMBEDDING_DIMENSIONS(可选;如果嵌入向量 API 端点支持,则会将其转发)

Windows 示例:

$env:EMBEDDING_PROVIDER = "ollama"
$env:EMBEDDING_MODEL = "nomic-embed-text"
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "scripts\ingest-embeddings.ps1" -Limit 25

Linux/macOS 示例:

export EMBEDDING_API_KEY=...
export EMBEDDING_MODEL=text-embedding-3-small
bash "scripts/ingest-embeddings.sh"

调度:

  • 添加新记忆后,每天(或每小时)运行一次
  • 在确认其可靠之前,将 Limit 设为较小值

稳健性说明:

  • 在 Windows 上,通过 psql -c 传递很长的 SQL 字符串可能不可靠。摄取脚本会将逐行更新写入临时 .sql 文件,并运行 psql -f,以避免命令行长度和引号处理方面的边界问题。

相关技能

systematic-debugging、postgres-pro、postgresql-table-design 共享数据库模式需要在运行时切换角色:

  • 使用连接器凭据连接
  • 每个请求执行一次 SET ROLE visitor_<identity>
  • 仅在 Hermes/管理员跨项目审计流程中使用 --all-scopes

评论

支持 Markdown