feat: add cross-harness memory vault (#2581)

Add a local-first, cross-harness memory vault with CLI and MCP surfaces, bounded search and storage, harness-scoped visibility, setup guidance, and comprehensive tests.
This commit is contained in:
Affaan Mustafa 2026-07-26 02:46:59 -07:00 committed by GitHub
parent 56d9302f02
commit 4d0b501b05
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
38 changed files with 5738 additions and 27 deletions

View file

@ -47,6 +47,18 @@ This document lists each slash command and the primary agent(s) or skills it inv
| `/pm2` | — | PM2 service lifecycle |
| `/security-scan` | security-reviewer (skill) | AgentShield via security-scan skill |
## Non-Slash CLI Surfaces
| CLI surface | Primary skill/runtime | Notes |
|-------------|-----------------------|-------|
| `ecc memory init` | unified-memory / `scripts/memory.js` | Initialize project, team, or user Markdown vault scopes |
| `ecc memory save` | unified-memory / `scripts/memory.js` | Create unreviewed memory; body must come from stdin or a regular file |
| `ecc memory handoff` | unified-memory / `scripts/memory.js` | Create a targeted, cross-harness handoff |
| `ecc memory search` | unified-memory / `scripts/memory.js` | Bounded lexical search over selected vault scopes |
| `ecc memory read` | unified-memory / `scripts/memory.js` | Read one memory plus derived backlinks |
| `ecc memory doctor` | unified-memory / `scripts/memory.js` | Audit malformed files, duplicate IDs, broken links, and symlinks |
| `ecc-memory-mcp` | unified-memory / `scripts/memory-mcp.mjs` | Optional stdio MCP adapter; exposes save/search/read/doctor only |
## Direct-Use Agents
| Direct agent | Purpose | Scope | Notes |
@ -60,6 +72,7 @@ This document lists each slash command and the primary agent(s) or skills it inv
- **eval-harness**: `/eval`
- **security-scan**: `/security-scan` (runs AgentShield)
- **strategic-compact**: suggested at compaction points (hooks)
- **unified-memory**: `ecc memory ...` and the opt-in `ecc-memory-mcp` server
## How to use this map

View file

@ -22,7 +22,7 @@ Telegram / CLI / TUI
Hermes
ECC skills + hooks + MCPs + generated workflow packs
ECC skills + hooks + MCPs + shared Memory Vault
Google Drive / GitHub / browser automation / research APIs / media tools / finance tools
```
@ -45,6 +45,79 @@ Use this as the minimal surface to reproduce the setup without leaking private s
- scheduled automation runs with explicit prompts and channels
- `~/.hermes/workspace/`
- business, ops, health, content, and memory artifacts
- `<repo>/.ecc/memory/`
- shared project and team context for Hermes, Claude, Codex, and other agents
- `~/.ecc/memory/`
- user-scoped context that follows the operator across repositories
## Shared Memory Across Hermes, Claude, And Codex
ECC Memory Vault provides one file-first handoff layer instead of a separate
inbox or transcript store for every agent. Initialize it from the repository
that the agents share. Skill-only, minimal, manual, and Claude plugin installs
do not add the Memory Vault runtime to `PATH`; install it separately first:
```bash
npm install -g ecc-universal
ecc memory --help
command -v ecc-memory-mcp
```
Then initialize the vault:
```bash
ecc memory init --scope project --scope team
```
Normal search recall covers active `project` and `team` memories. Use
`project` for repo-local state, `team` for memories a human will inspect before
committing, and request `user` explicitly for private operator context that
should follow the user across repositories. Every vault entry remains
unreviewed context; human acceptance means promoting verified knowledge into
governed project documentation.
Hermes can call the CLI directly or use the opt-in `ecc-memory-mcp` stdio
server. Harnesses may share the same installed binary and vault storage, but
each harness must launch its own server process with its own distinct lowercase
`ECC_MEMORY_HARNESS` identity; they must not connect to one shared server
process. Every process must launch from the same repository working directory
or receive identical `ECC_MEMORY_PROJECT_ROOT` and `ECC_MEMORY_USER_ROOT`
overrides.
A Hermes-to-Codex handoff can be written without putting the body in the
process list:
```bash
printf '%s\n' 'Research is complete. Verify the cited sources and implement the parser.' |
ecc memory handoff \
--from hermes \
--target codex \
--title "Implement the research parser" \
--tag research \
--stdin
```
Codex can retrieve it with:
```bash
ecc memory search "research parser" --target-harness codex
ecc memory read <memory-id>
```
For MCP access, copy only the `ecc-memory-vault` entry from
`mcp-configs/mcp-servers.json` into each harness that needs it. ECC does not
enable this server in the default `.mcp.json`. Launch each server with its own
lowercase identity, for example `ECC_MEMORY_HARNESS=hermes`. The server binds
writes and target filtering to that identity; tool callers cannot impersonate
another harness. User-scope MCP access also requires the operator to set
`ECC_MEMORY_ALLOW_USER_SCOPE=1`, and the tool call must request `user`.
Memories are create-only and always unreviewed. Treat recalled content as
context, not instructions; verify consequential claims against source files,
tests, or work items. Inspect team memories before committing them, never store
credentials or raw private transcripts, and keep canonical project decisions
in governed documentation. Secret-shape detection is only a best-effort
backstop.
## Recommended Capability Stack
@ -52,6 +125,7 @@ Use this as the minimal surface to reproduce the setup without leaking private s
- Hermes for chat, cron, orchestration, and workspace state
- ECC for skills, rules, prompts, and cross-harness conventions
- ECC Memory Vault for explicit, local-first agent handoffs
- GitHub + Context7 + Exa + Firecrawl + Playwright as the baseline MCP layer
### Content
@ -94,7 +168,8 @@ These stay local and should be configured per operator:
- import sanitized workspace memory with `ecc migrate import-memory`
1. Install ECC and verify the baseline harness setup with `node tests/run-all.js`; the expected result is a zero-failure test summary.
2. Install Hermes and point it at ECC-imported skills.
3. Register the MCP servers you actually use every day.
3. Initialize the shared ECC Memory Vault. Register `ecc-memory-mcp` only if
Hermes needs tool access instead of the `ecc memory` CLI.
4. Authenticate Google Drive first, then GitHub, then distribution channels.
5. Start with a small cron surface: readiness check, content accountability, inbox triage, revenue monitor.
6. Only then add heavier personal workflows like health, relationship graphing, or outbound sequencing.

View file

@ -10,6 +10,7 @@ The goal is to keep the durable parts of agentic work in one repo:
- MCP configuration
- install manifests
- session and orchestration patterns
- durable, harness-neutral memory documents
Claude Code, Codex, OpenCode, Cursor, Gemini, and future harnesses should adapt those assets at the edge instead of requiring a new workflow model for every tool.
@ -27,6 +28,7 @@ For the full-stack platform framing and product-integration loop, see
| Hooks | `hooks/hooks.json`, `scripts/hooks/` | Claude native hooks, OpenCode plugin events, Cursor hook adapter | Hook-backed in Claude/OpenCode/Cursor; instruction-backed in Codex |
| MCPs | `.mcp.json`, `mcp-configs/` | Native MCP config import per harness | Supported where the harness exposes MCP |
| Commands | `commands/`, CLI scripts | Claude slash commands, compatibility shims, CLI entrypoints | Supported, but command semantics vary |
| Memory | `.ecc/memory/`, `~/.ecc/memory/` | `ecc memory` CLI or opt-in `ecc-memory-mcp` stdio server | Supported with explicit recall and unreviewed writes |
| Sessions | `ecc2/`, session adapters, orchestration scripts | TUI/daemon, tmux/worktree orchestration, harness-specific runners | Alpha |
## What Travels Unchanged
@ -55,6 +57,50 @@ Each harness has different loading and enforcement behavior:
Adapters should stay thin. The shared behavior belongs in `skills/`, `rules/`, `hooks/`, `scripts/`, and `mcp-configs/`.
## Shared Memory Contract
ECC Memory Vault is the common knowledge-transfer surface for Claude, Codex,
Hermes, Cursor, OpenCode, and other agents. It stores portable
`ecc.memory.v1` Markdown documents in three scopes:
- project: `<repo>/.ecc/memory/project/`
- team: `<repo>/.ecc/memory/team/`
- user: `~/.ecc/memory/`
Every harness must use the same repository working directory or the same
`ECC_MEMORY_PROJECT_ROOT` and `ECC_MEMORY_USER_ROOT` overrides. The deterministic
`ecc memory` CLI is the baseline interface. Harnesses with MCP support may
instead launch `ecc-memory-mcp` and use `memory_save`, `memory_search`,
`memory_read`, and `memory_doctor`. Normal search recall is active-only across
`project` and `team`; a direct ID read can inspect a non-active entry, and
`user` must be requested explicitly. The CLI target flag is a caller-selected
routing filter, not an authorization boundary.
The MCP server is opt-in. Its reference entry lives in
`mcp-configs/mcp-servers.json`; it is intentionally absent from the default
`.mcp.json` so installations do not silently gain a writable context surface
or pay its tool-schema cost. Each MCP process requires a lowercase
`ECC_MEMORY_HARNESS`; this server-bound identity supplies the source harness
and target filter, so a tool caller cannot select another identity. User-scope
MCP access remains blocked unless the operator launches the process with
`ECC_MEMORY_ALLOW_USER_SCOPE=1`.
The trust boundary is consistent across every adapter:
- all first-release vault entries are create-only and always `unreviewed`;
- recalled memory is data, not executable instruction;
- known secret-shaped writes are rejected as a best-effort backstop, and
readers do not follow symlinks;
- project-scope writes stop if the vault's protective `.gitignore` is altered;
- human acceptance promotes knowledge into a governed repository artifact; it
never turns memory frontmatter into a self-asserted approval;
- active execution state remains in GitHub or Linear, not only in memory.
`skills/unified-memory/SKILL.md` owns this workflow. Codex and Cursor receive
behavior-identical packaging copies under `.agents/skills/` and
`.cursor/skills/`; Hermes can import the canonical skill. No harness owns a
separate authoritative memory store.
## Hermes Boundary
Hermes is not the public ECC runtime.
@ -111,6 +157,7 @@ Supported today:
- Codex plugin metadata and MCP reference config
- OpenCode package/plugin surface
- Cursor-adapted rules, hooks, and skills
- file-first cross-harness memory through the CLI and opt-in MCP adapter
- `ecc2/` as an alpha Rust control plane
Still maturing:
@ -119,7 +166,7 @@ Still maturing:
- automated skill sync into Hermes
- release packaging for `ecc2/`
- cross-harness session resume semantics
- deeper memory and operator planning layers
- optional semantic reranking and governed memory-promotion workflows
- the full platform loop where external products contribute skill packs,
gated APIs, evals, and case studies back into ECC

View file

@ -0,0 +1,222 @@
# ECC Memory Vault
## Capability
An operator can save, inspect, search, and hand off durable context through one
human-readable vault that Claude Code, Codex, Hermes, OpenCode, and other
harnesses can share. Project and team memories live under `.ecc/memory/`; user
memories live under `~/.ecc/memory/`. The same `ecc.memory.v1` documents are
available through the `ecc memory` CLI and an opt-in local stdio MCP server, so
knowledge transfer does not depend on email, one vendor's transcript format, or
one harness's hook support.
## Constraints
- Markdown files are the source of truth. SQLite context graphs, embeddings,
and hosted systems are indexes or adapters, never the only copy.
- A memory is context, not an instruction. Every first-release vault entry is
`trust: "unreviewed"` and cannot silently become rules, skills, or policy.
- Reviewed project standards still belong in the repository's canonical rules,
decision records, runbooks, or other governed documentation. The vault may
link to those artifacts; it does not replace them.
- The core is local-first, inspectable, and usable without a model, network,
database server, or embedding provider.
- Writes are create-only. The tool never overwrites an existing memory ID.
Supersession is represented by a new document with explicit links.
- Known credential shapes and private keys are rejected before a tool writes a
file. This scan is a best-effort backstop, not a complete secret classifier.
Memory readers do not follow symbolic links.
- Search is bounded lexical retrieval in the first release. Optional semantic
adapters may rerank results later without changing the document contract.
- Harness adapters stay thin. Shared behavior belongs in `scripts/`, `skills/`,
and the MCP server rather than separate Claude/Codex/Hermes stores.
- Procedural memory remains in rules and instincts, subject to their existing
promotion and validation gates.
### Threat boundary
The first-release runtime defends against hostile vault documents, stable
symlink/path escapes, accidental project-memory commits, cross-harness MCP
identity spoofing, known secret shapes, terminal control data, and bounded
resource exhaustion. Vault roots must remain writable only by the operator.
It is not a security boundary between concurrent processes running as the same
OS user: Node.js does not expose the directory-file-descriptor-relative
`openat2` guarantees needed to eliminate every parent-directory swap race.
Operators who need protection from a malicious local process must use separate
OS accounts, containers, or equivalent filesystem isolation.
## Implementation Contract
### Actors
- **Operator:** owns the vault, reviews files, commits team memories, and
decides when recalled context becomes governed project truth.
- **Harness agent:** writes unreviewed facts, notes, lessons, and handoffs; reads
active memories targeted to itself or all harnesses.
- **ECC CLI:** deterministic local create/read/search/doctor interface.
- **ECC Memory MCP:** stdio adapter exposing the same create/read/search/doctor
operations. It has no review or promotion tool.
- **ECC2 context graph:** optional projection populated from the Markdown
directory connector for richer relationship and session views.
### Surfaces
```text
<repo>/.ecc/memory/
├── project/
│ ├── contexts/
│ ├── decisions/
│ ├── facts/
│ ├── handoffs/
│ ├── lessons/
│ ├── notes/
│ ├── preferences/
│ └── runbooks/
└── team/
└── <same kind directories>
~/.ecc/memory/
└── <same kind directories>
```
The project scope is repo-local operator context and receives its own
fail-closed `.gitignore`: initialization and writes stop if the protection file
exists with unexpected content. The team scope is intended to be inspected by
a human before it is committed, but committed vault entries remain unreviewed
context. The user scope follows the operator across repos and is recalled only
when explicitly requested.
`ECC_MEMORY_PROJECT_ROOT` and `ECC_MEMORY_USER_ROOT` may override the two vault
locations explicitly.
### Document contract
Each memory is a Markdown file with strict JSON-valued YAML frontmatter:
```markdown
---
schema: "ecc.memory.v1"
id: "mem_20260726_01k123example"
title: "Authentication migration handoff"
kind: "handoff"
scope: "project"
trust: "unreviewed"
status: "active"
source_harness: "codex"
target_harnesses: ["claude"]
tags: ["auth", "migration"]
links: ["mem_20260725_01kolder"]
created_at: "2026-07-26T20:00:00.000Z"
updated_at: "2026-07-26T20:00:00.000Z"
---
The token rotation tests pass. The remaining task is ...
```
Required fields are schema, ID, title, kind, scope, trust, status, source
harness, targets, tags, links, and timestamps. IDs, kinds, tags, and harness
names use a bounded lowercase slug grammar. Bodies are bounded Markdown text.
Backlinks are derived from other documents' `links` fields.
### States and transitions
```text
tool save ──> active + unreviewed
├── human verifies evidence
│ └──> governed rule, decision record, runbook, or doc
└── new memory links with supersedes relation
└──> old item may be marked superseded manually
```
The initial runtime creates active, unreviewed memories only, and normal search
recall returns active entries only. A direct ID read may still retrieve a
non-active entry for inspection. Human review does not change a vault entry's
`trust` field; accepted knowledge is promoted into a governed repository
artifact. The runtime exposes no automated promotion transition. This is
intentional: a shell-capable agent cannot be treated as an independent human
approval boundary.
### Interfaces
CLI:
```text
ecc memory init [--scope project|team|user]
ecc memory save --title <text> [--body-file <path>|--stdin] [metadata flags]
ecc memory handoff --from <harness> --target <harness> --title <text> ...
ecc memory search <query> [--scope ...] [--target-harness ...] [--json]
ecc memory read <id> [--scope ...] [--json]
ecc memory doctor [--json]
```
MCP tools:
```text
memory_save
memory_search
memory_read
memory_doctor
```
The CLI searches active `project` and `team` memories by default. `user` recall
requires an explicit `--scope user`. Its `--target-harness` option is a
caller-selected routing filter, not an authorization boundary.
The MCP server requires a lowercase `ECC_MEMORY_HARNESS` identity at launch.
That server-side identity supplies `source_harness` for writes and constrains
search/read to memories targeted to that harness or `all`; clients cannot
override it in tool arguments. MCP access to `user` scope is disabled unless
the operator also sets `ECC_MEMORY_ALLOW_USER_SCOPE=1`, after which the client
must still request that scope explicitly. MCP writes always produce unreviewed
documents. Structured errors omit stack traces and secret values.
### Failure and recovery
- Invalid metadata, oversized input, duplicate IDs, suspected secrets, and path
escapes fail before writing.
- A malformed file is reported by `doctor` and excluded from search; it is
never deleted or rewritten automatically.
- Duplicate IDs and broken links are reported explicitly.
- Symlinks are skipped and reported.
- Missing vault directories are equivalent to an empty vault.
- A failed MCP request returns a bounded error and leaves existing files
unchanged.
### Observability
The first release reports operation results only. Write acknowledgements omit
the raw body and use a scope-relative vault path; only an explicit read returns
the full body. A later event-sourced ECC2 projection may record content hashes
and operation metadata, but it must not log raw memory bodies or credentials.
## Non-goals
- Building a vector database, hosted sync service, email transport, or new agent
framework.
- Importing raw Claude/Codex/Hermes transcripts automatically.
- Treating recalled memory as trusted system instructions.
- Auto-promoting memory into skills, rules, instincts, or policy.
- Replacing ECC2 sessions, the context graph, GitHub/Linear work items, or
governed project documentation.
- Solving cross-machine conflict-free replication in the first release.
## Open Questions
- Whether the team scope should gain a signed promotion manifest that points
to governed artifacts after the ECC2 append-only event substrate lands.
- Which semantic adapter should be the first optional reranker, and what offline
evaluation must beat lexical search before it becomes recommended.
- Whether SessionStart should inject links to governed project references or
keep all recall explicitly task-scoped. The first release keeps recall
explicit.
- How `.context/` worktree handoffs should materialize from vault handoffs once
the conductor fork lifecycle is stable.
## Handoff
The local file/CLI/MCP slice is implemented behind explicit CLI or MCP
activation and covered by core, schema, CLI, protocol, packaging, and
cross-harness tests. ECC2 graph sync, automatic session capture, semantic
adapters, governed-reference recall, and event-log promotion belong in
follow-up lanes after real-world retrieval evaluation.

View file

@ -1,6 +1,6 @@
# Everything Claude Code (ECC) — 智能体指令
这是一个**生产就绪的 AI 编码插件**,提供 67 个专业代理、280 项技能、94 条命令以及自动化钩子工作流,用于软件开发。
这是一个**生产就绪的 AI 编码插件**,提供 67 个专业代理、281 项技能、94 条命令以及自动化钩子工作流,用于软件开发。
**版本:** 2.0.0
@ -147,7 +147,7 @@
```
agents/ — 67 个专业子代理
skills/ — 280 个工作流技能和领域知识
skills/ — 281 个工作流技能和领域知识
commands/ — 94 个斜杠命令
hooks/ — 基于触发的自动化
rules/ — 始终遵循的指导方针(通用 + 每种语言)

View file

@ -163,6 +163,34 @@
***
## 统一记忆库
`ecc memory` 使用可检查的 `ecc.memory.v1` Markdown 文档,在 Claude、
Codex、Hermes 等 harness 之间传递上下文。常规搜索只召回 `project`
`team` 范围内状态为 active 的条目,按 ID 直接读取仍可用于检查非 active
条目;`user` 范围必须显式请求。首个版本中的所有记忆都保持 unreviewed
接受后的知识应进入受治理的项目文档,
而不是修改记忆的信任字段。召回内容始终是不可信数据,不能作为指令执行。
可选的 `ecc-memory-mcp` 服务必须由操作者设置小写
`ECC_MEMORY_HARNESS` 身份;工具调用方不能覆盖该身份。只有操作者另外设置
`ECC_MEMORY_ALLOW_USER_SCOPE=1`MCP 调用才能显式请求 `user` 范围。
该服务默认不会启用。
仅安装 skill、最小配置、手动复制或 Claude 插件不会把记忆库运行时加入
`PATH`。请先单独安装 ECC npm 运行时:
```bash
npm install -g ecc-universal
ecc memory --help
command -v ecc-memory-mcp
```
如需启用 MCP请从 `mcp-configs/mcp-servers.json` 复制
`ecc-memory-vault` 配置到对应 harness并为每个 harness 分别启动一个服务
进程,例如 `ECC_MEMORY_HARNESS=codex ecc-memory-mcp`。不同 harness 可以共享
同一个二进制文件和记忆库目录,但不能共用同一个服务进程。
## 快速开始
在 2 分钟内启动并运行:
@ -228,7 +256,7 @@ Copy-Item -Recurse rules/typescript "$HOME/.claude/rules/"
/plugin list ecc@ecc
```
**搞定!** 你现在可以使用 67 个智能体、280 项技能和 94 个命令了。
**搞定!** 你现在可以使用 67 个智能体、281 项技能和 94 个命令了。
***
@ -1142,7 +1170,7 @@ opencode
|---------|---------------|----------|--------|
| 智能体 | PASS: 67 个 | PASS: 12 个 | **Claude Code 领先** |
| 命令 | PASS: 94 个 | PASS: 35 个 | **Claude Code 领先** |
| 技能 | PASS: 280 项 | PASS: 37 项 | **Claude Code 领先** |
| 技能 | PASS: 281 项 | PASS: 37 项 | **Claude Code 领先** |
| 钩子 | PASS: 8 种事件类型 | PASS: 11 种事件 | **OpenCode 更多!** |
| 规则 | PASS: 29 条 | PASS: 13 条指令 | **Claude Code 领先** |
| MCP 服务器 | PASS: 14 个 | PASS: 完整 | **完全对等** |
@ -1250,7 +1278,7 @@ ECC 是**第一个最大化利用每个主要 AI 编码工具的插件**。以
|---------|-----------------------|------------|-----------|----------|
| **智能体** | 67 | 共享 (AGENTS.md) | 共享 (AGENTS.md) | 12 |
| **命令** | 94 | 共享 | 基于指令 | 35 |
| **技能** | 280 | 共享 | 10 (原生格式) | 37 |
| **技能** | 281 | 共享 | 10 (原生格式) | 37 |
| **钩子事件** | 8 种类型 | 15 种类型 | 暂无 | 11 种类型 |
| **钩子脚本** | 20+ 个脚本 | 16 个脚本 (DRY 适配器) | N/A | 插件钩子 |
| **规则** | 34 (通用 + 语言) | 34 (YAML 前页) | 基于指令 | 13 条指令 |