Skip to content

Latest commit

 

History

History
1097 lines (832 loc) · 39.2 KB

File metadata and controls

1097 lines (832 loc) · 39.2 KB

EchoesVault Protocol 1.0.0

  • Status: stable
  • Protocol version: 1.0.0
  • Reference engine version: 1.1.1
  • Managed adapter version: 1.1.1
  • Marker schema version: 3
  • Local state schema version: 4
  • Reference runtime: .echoes-vault/echoes_vault.py
  • License: MIT

EchoesVault Protocol 1.0.0 defines a repository-local, agent-neutral format and command contract for persistent project memory. It allows Codex, OpenCode, Claude Code, custom agents, editor extensions, and ordinary scripts to share the same Markdown knowledge base without coupling its contents to one agent or plugin.

This document is the complete public implementer specification. Initialized repositories also contain EchoesVault/AGENT_PROTOCOL.md, a shorter generated operational guide intended for agents working inside that repository.

Contents

1. Normative language

The key words MUST, MUST NOT, REQUIRED, SHOULD, SHOULD NOT, and MAY describe conformance requirements.

Protocol 1.0.0 uses exact-version write compatibility. An implementation that does not support the marker's exact protocolVersion MAY inspect the Markdown as read-only data, but MUST NOT mutate the vault or its managed files.

2. Design goals

Protocol 1.0.0 is designed to provide:

  • durable project knowledge stored as human-readable UTF-8 Markdown;
  • one repository-portable writer shared by every agent;
  • deterministic discovery without loading every page body into model context;
  • safe local concurrency and explicit same-page conflict detection;
  • Git-friendly parallel work across branches and developers;
  • Obsidian-compatible links and directories;
  • explicit user control over session restoration and final memory saving;
  • fail-closed behavior for unsupported versions, unsafe paths, invalid metadata, and unresolved Git conflict markers;
  • no network service, database, API key, or third-party Python dependency at runtime.

Protocol 1.0.0 does not attempt to provide:

  • a remote synchronization service;
  • cross-clone locking between different computers;
  • automatic semantic reconciliation when two branches edit the same knowledge page;
  • encrypted or secret storage;
  • a general-purpose YAML parser;
  • automatic ingestion of the entire vault into an agent's context.

3. Terminology

  • Workspace: the resolved project root. If the supplied directory is inside a Git repository, the reference runtime uses the Git top-level directory. Otherwise it uses the supplied directory.
  • Vault: the EchoesVault/ directory inside the workspace.
  • Knowledge page: a top-level Markdown file in EchoesVault/pages/.
  • Daily entry: one immutable-by-convention scratchpad or session Markdown file below EchoesVault/daily/YYYY-MM-DD/.
  • Marker: EchoesVault/.echoes-vault.json, which declares the on-disk protocol.
  • Portable runtime: .echoes-vault/echoes_vault.py, committed with the project and used for all mutations.
  • Adapter: agent-specific instructions or commands that delegate to the portable runtime.
  • Generated index: EchoesVault/index.md, reconstructed from page filenames and frontmatter.
  • Durable knowledge: tracked pages, daily entries, assets, and raw sources.
  • Local state: runtime bookkeeping that is not durable knowledge and is not committed.

4. Conformance model

There are three useful conformance levels.

4.1 Reader

A conforming reader:

  1. Locates the workspace and marker.
  2. Reads the marker before interpreting managed files.
  3. Treats pages/*.md and daily/**/*.md as the durable sources of truth.
  4. Does not treat index.md or local state as authoritative knowledge.
  5. Does not write when protocolVersion is unsupported.

4.2 Runtime adapter

A conforming runtime adapter satisfies the reader requirements and invokes the repository's portable runtime for every mutation:

python3 .echoes-vault/echoes_vault.py --workspace . <command>

This is the recommended integration mode. It automatically shares validation, locking, index generation, migration, and error behavior with all other agents.

4.3 Native writer

A native writer MAY reimplement the storage engine, but it is conforming only if it reproduces all normative write behavior in this document, including:

  • exact protocol-version gating;
  • workspace and path confinement;
  • symlink refusal for managed write targets;
  • the shared .echoes-vault/lock algorithm;
  • atomic replacement writes;
  • required page validation;
  • current-content SHA-256 checks for existing-page updates;
  • deterministic index bytes;
  • unique daily-entry paths;
  • explicit authorization for final session saving.

A plugin that writes directly to index.md, appends to daily/YYYY-MM-DD.md, or overwrites an existing page without its current hash is not a Protocol 1.0.0 writer.

5. Repository layout

An initialized workspace has the following managed layout:

<workspace>/
├── EchoesVault/
│   ├── .echoes-vault.json
│   ├── .gitignore
│   ├── AGENT_PROTOCOL.md
│   ├── index.md
│   ├── pages/
│   │   └── <page-slug>.md
│   ├── daily/
│   │   └── YYYY-MM-DD/
│   │       └── <unique-entry>.md
│   ├── assets/
│   └── raw/
├── .echoes-vault/
│   ├── .gitignore
│   ├── echoes_vault.py
│   ├── state.json
│   └── lock
├── AGENTS.md
├── CLAUDE.md
├── .claude/skills/echoes-vault/SKILL.md
├── .opencode/skills/echoes-vault/SKILL.md
└── .opencode/commands/
    ├── echoes-init.md
    ├── echoes-start.md
    ├── echoes-status.md
    └── echoes-end.md

5.1 Durable sources of truth

The durable knowledge sources are:

EchoesVault/pages/*.md
EchoesVault/daily/**/*.md
EchoesVault/assets/**
EchoesVault/raw/**

Knowledge pages contain curated, reusable facts. Daily entries contain chronological scratchpad and final-session records. Assets contain referenced binary or text artifacts. Raw sources contain material preserved for later interpretation.

5.2 Generated and local files

The following files are derived or machine-local and MUST NOT be treated as durable knowledge:

EchoesVault/index.md
.echoes-vault/state.json
.echoes-vault/lock

Initialization creates scoped ignore rules automatically.

EchoesVault/.gitignore contains:

# Generated locally by EchoesVault
/index.md

.echoes-vault/.gitignore contains:

# EchoesVault runtime files
/state.json
/lock

Existing ignore files are preserved and missing rules are appended.

5.3 Managed adapters

AGENTS.md and CLAUDE.md receive exactly one managed block delimited by:

<!-- echoes-vault:start -->
<!-- echoes-vault:end -->

Implementations MUST preserve content outside this block. The generated Claude and OpenCode skills and commands are adapters; they MUST delegate mutations to the portable runtime rather than implement an independent storage model.

6. Protocol marker

EchoesVault/.echoes-vault.json is tracked in Git and has this Protocol 1.0.0 value:

{
  "schemaVersion": 3,
  "protocolVersion": "1.0.0",
  "generatedIndex": true,
  "dailyLayout": "unique-files-v1",
  "runtime": ".echoes-vault/echoes_vault.py",
  "requiredFrontmatter": [
    "type",
    "stack",
    "status",
    "summary"
  ]
}

Writers MUST read the marker before every operation that can mutate managed files. A missing marker may indicate an uninitialized or legacy vault and requires a recognized initialization or migration path; init is the canonical path. A value other than protocolVersion: "1.0.0" MUST stop Protocol 1.0.0 writes.

schemaVersion, engine version, adapter version, plugin version, and protocol version are different concepts:

  • protocolVersion identifies this interoperability contract;
  • schemaVersion identifies the marker shape;
  • engineVersion identifies a particular portable storage-engine build;
  • adapterVersion identifies the invoking agent adapter;
  • a plugin-package version identifies one distributable integration release.

Only protocolVersion establishes on-disk write compatibility. Engine and adapter versions MUST NOT be compared with one another. In particular, an OpenCode plugin version is not a Python engine version.

7. Knowledge pages

7.1 Location and filename rules

Knowledge pages MUST be regular .md files directly inside EchoesVault/pages/. Nested page directories are not part of Protocol 1.0.0.

A writer MUST normalize a page name to Unicode NFC and enforce all of these rules:

  • the name is non-empty;
  • an optional final .md is normalized to exactly one .md suffix;
  • / and \ are forbidden;
  • .. is forbidden anywhere in the name;
  • a leading . is forbidden;
  • the target MUST NOT be a symbolic link;
  • two page stems MUST NOT collide after NFC normalization and case folding.

The collision rule prevents repositories that work on one filesystem from becoming ambiguous on a case-insensitive or Unicode-normalizing filesystem.

7.2 Required frontmatter

After surrounding whitespace normalization, every page MUST begin with a frontmatter block and MUST contain values for type, stack, status, and summary:

---
type: architecture
stack: [python, postgresql]
status: active
summary: Authentication boundaries, token validation, and service ownership.
---

# Authentication architecture

Protocol 1.0.0 uses a deliberately restricted frontmatter contract rather than requiring a full YAML implementation:

  • top-level keys use [A-Za-z][A-Za-z0-9_-]* followed by :;
  • duplicate top-level keys are invalid;
  • type, status, and summary require non-empty inline scalar values;
  • stack requires either a non-empty inline representation such as [] or [python], or a following indented value;
  • type, status, and summary are scalar strings for protocol processing;
  • plain, single-quoted, and JSON-compatible double-quoted scalar strings are accepted;
  • status comparisons are case-insensitive;
  • additional frontmatter fields MAY be present and are preserved;
  • the full document MUST be valid UTF-8 text;
  • unresolved Git conflict markers are forbidden.

The protocol does not prescribe a closed vocabulary for type, stack, or status. Teams MAY define their own values. status: deprecated has standardized index behavior.

7.3 Summary rules

summary is the only page-body-independent description used to construct the index. It MUST:

  • be a non-empty string;
  • fit on one physical line;
  • contain no unresolved Git conflict marker;
  • contain no more than 160 Unicode characters;
  • remain useful without reading the page body.

Repeated whitespace is normalized to single spaces for index generation. Changing only a page body does not change the index. Changing a filename, summary, or deprecated state can change it.

7.4 Page contents

Pages SHOULD store durable technical knowledge such as:

  • architectural decisions and rationale;
  • API and schema contracts;
  • configuration and deployment facts;
  • verified fixes and their constraints;
  • hardware or infrastructure mappings;
  • durable blockers and follow-up decisions.

Pages SHOULD NOT be raw chat transcripts. Use [[page-slug]] for links to other pages and ![[asset-name.ext]] for assets in EchoesVault/assets/.

7.5 Deprecation

Obsolete knowledge SHOULD be deprecated rather than deleted. A deprecated page SHOULD:

  1. set status: deprecated;
  2. begin its body with > [!warning] DEPRECATED;
  3. link to its replacement when one exists.

If the status is deprecated and the summary does not already begin with deprecated case-insensitively, the generated index prefixes it with DEPRECATED — .

8. Deterministic index

EchoesVault/index.md is a generated local discovery view. Agents and integrations MUST NOT edit it manually and MUST NOT commit it.

The exact Protocol 1.0.0 header is:

# EchoesVault Index

<!-- Generated by EchoesVault. Do not edit manually. -->

This registry tracks all structured pages in the project knowledge vault.

## Pages

For each valid page, the runtime emits one row:

- [[<NFC page stem>]]: <normalized summary>

Rows are sorted by this stable key:

  1. NFC-normalized filename, case-folded;
  2. NFC-normalized filename as a deterministic tie-breaker.

The generator reads filenames and frontmatter but does not use page bodies. Output uses UTF-8, Unix line endings, and a final newline. The same valid page set therefore produces the same index bytes and SHA-256 digest on every supported agent.

Generation is all-or-nothing with respect to validation: if any page is invalid, a new index is not installed and the previous index remains available. Health reporting then identifies the page and index-build error.

9. Daily entries

Every new scratchpad or final-session record MUST use a unique file. Writers MUST NOT append new entries to a shared EchoesVault/daily/YYYY-MM-DD.md file.

The reference filename format is:

EchoesVault/daily/YYYY-MM-DD/
YYYYMMDDTHHMMSSffffffZ-<kind>[-<agent>]-<8-lowercase-hex>.md

Where:

  • the directory date and filename timestamp use UTC, and Z is mandatory for new files;
  • kind is scratchpad or session;
  • agent is optional provenance;
  • the final eight hexadecimal characters come from four random bytes.

Agent names are case-folded, unsupported characters are replaced by -, leading and trailing ./- are removed, and the result is limited to 40 characters. Valid output characters are a-z, 0-9, ., _, and -.

A scratchpad entry has this form:

### Scratchpad — 2026-09-04T12:34:56+03:00

Agent: `codex`

- Confirmed the authentication boundary.

The Markdown heading records local wall-clock time with an explicit UTC offset for human reading. Ordering and filenames use UTC so agents in different time zones agree on the latest entries.

A final-session entry uses ### Session — <timestamp> and otherwise has the same optional agent line and Markdown body structure.

Legacy flat daily files MAY remain readable during migration, but Protocol 1.0.0 writers MUST create only unique nested files.

10. Local state

.echoes-vault/state.json is ignored by Git and is not durable project memory. The reference engine 1.1.1 writes state schema version 4:

{
  "version": 4,
  "protocolVersion": "1.0.0",
  "engineVersion": "1.1.1",
  "initialized": true,
  "session": {
    "started": true,
    "saved": false,
    "lastStart": "2026-09-04T12:00:00+03:00",
    "lastSave": null
  },
  "stats": {
    "totalPages": 12,
    "totalDailyLogs": 8,
    "deprecatedPages": 1
  },
  "lastWriter": {
    "agent": "codex",
    "adapterVersion": "1.1.1"
  }
}

Consumers MUST NOT use state as the source of truth for knowledge. It MAY be deleted and rebuilt. An invalid, missing, symlinked, or protocol-mismatched state file lowers health status but does not replace the marker or Markdown sources.

11. Locking and write safety

11.1 Shared local lock

Every command that writes managed files runs while holding .echoes-vault/lock. inspect, status, protocol, search, and hash are read-only and do not create the lock. hydrate may briefly create the ignored lock while refreshing only ignored generated files.

A conforming native writer MUST interoperate with this lock:

  1. Attempt exclusive file creation equivalent to O_CREAT | O_EXCL | O_WRONLY.
  2. Write an ownership token unique to the process.
  3. Wait up to 8 seconds when another valid lock exists, retrying at short intervals.
  4. Treat a lock older than 60 seconds as stale and remove it before retrying.
  5. Remove the lock on exit only if its contents still match the writer's ownership token.

This lock serializes processes in one checkout. It does not coordinate separate clones or Git branches on different machines.

11.2 Atomic replacement

Managed replacement writes use a temporary file in the target directory, flush and fsync its contents, and atomically replace the destination. Writers MUST avoid exposing partially written individual files.

Multi-file operations validate their inputs before the first durable knowledge write, but Protocol 1.0.0 does not promise a crash-recoverable multi-file database transaction. Each individual file replacement is atomic.

11.3 Optimistic concurrency

Creating a new page does not require a hash. Replacing an existing page requires expectedSha256, calculated from the exact current UTF-8 file bytes immediately before the update.

The update sequence is:

  1. Read the complete current page.
  2. Run hash <filename> or calculate the equivalent SHA-256.
  3. Prepare the complete replacement page.
  4. Submit expectedSha256 with upsert or the page item in end.
  5. If the actual hash differs, stop without overwriting, reread, reconcile, obtain a new hash, and retry.

The project lock protects concurrent local runtime calls. The optimistic hash additionally protects against stale agent context and edits made outside the runtime.

12. Portable runtime contract

12.1 Invocation

The canonical command form is:

python3 .echoes-vault/echoes_vault.py --workspace <path> <command> [arguments]

--workspace defaults to the current directory. When the path is inside a Git repository, the runtime resolves it to the repository root. Payload-bearing commands accept a JSON object from standard input with --payload -, or from a UTF-8 JSON file path.

Adapters SHOULD identify themselves without changing protocol negotiation:

python3 .echoes-vault/echoes_vault.py --workspace . \
  --agent codex --adapter-version 1.1.1 <command>

After initialization, the project-local runtime is the execution source. A bundled plugin runtime MAY be used only for initial bootstrap, explicit upgrade, or recovery of a missing project runtime. A launcher MUST delegate or re-execute through a compatible project runtime. It MUST NOT continue mutating with its bundled code after discovering a newer compatible project runtime, and MUST NOT downgrade that runtime.

Shell adapters SHOULD send untrusted Markdown through standard input or a temporary payload file. They MUST NOT interpolate untrusted Markdown into a shell command.

On success, the reference runtime exits with code 0 and writes either UTF-8 JSON or documented Markdown context to stdout. Expected protocol errors exit with code 2 and write this shape to stderr:

{"ok": false, "error": "Human-readable explanation."}

An adapter MUST NOT report success when the runtime returns a non-zero exit status.

12.2 init

python3 .echoes-vault/echoes_vault.py --workspace . init

init is idempotent. It:

  • creates or upgrades the vault structure and marker;
  • migrates eligible legacy page summaries;
  • installs or refreshes the portable runtime;
  • creates scoped .gitignore rules;
  • generates the compact agent protocol;
  • adds or refreshes managed root instruction blocks;
  • creates Claude and OpenCode adapters;
  • deterministically rebuilds the index;
  • writes local state.

It preserves unrelated root instructions. Recognized legacy EchoesVault OpenCode commands may be replaced with protocol-aware adapters; unrelated files using the same command paths are preserved and reported as a health issue for manual reconciliation.

The JSON result includes ok, created, vault, index, indexRefresh, agentAdapters, and state.

migrate and upgrade use the same full installation boundary. migrate communicates explicit legacy conversion intent; upgrade communicates explicit project runtime and adapter upgrade intent. Neither command may downgrade a newer compatible engine.

12.3 protocol

python3 .echoes-vault/echoes_vault.py --workspace . protocol

Reports engineVersion, managedAdapterVersion, the runtime's supported protocol, the marker's protocol when present, managed protocol and runtime paths, and the available command names. Reference engine 1.1.1 also reports deprecated codexAdapterVersion as an alias of managedAdapterVersion; integrations SHOULD migrate to the neutral field. Integrations SHOULD use it for diagnostics, but MUST still fail closed when an operation encounters an unsupported marker.

12.4 configure-agents

python3 .echoes-vault/echoes_vault.py --workspace . configure-agents

Repairs or refreshes the generated protocol, root managed blocks, Claude/OpenCode skills, OpenCode commands, ignore rules, and index. Runtime replacement belongs to explicit upgrade or missing-runtime recovery. This command does not author new knowledge. Recognized legacy OpenCode skills are replaced with short redirect skills; unknown user-owned files are preserved and reported as adapter configuration conflicts. It requires an initialized vault. Legacy conversion belongs to init or migrate.

12.5 inspect and status

python3 .echoes-vault/echoes_vault.py --workspace . inspect
python3 .echoes-vault/echoes_vault.py --workspace . status
python3 .echoes-vault/echoes_vault.py --workspace . status --format card

inspect returns JSON by default. --format card returns a compact Markdown status card suitable for a user interface. status is an exact read-only alias. Neither command creates, rewrites, migrates, hydrates, repairs, or locks any file. A SessionStart integration MUST use this boundary. When only a legacy vault is found, the card reports Legacy vault detected and directs the user to explicit init/migrate.

The JSON result contains:

  • workspace, vault, local state, and indexRefresh;
  • page, daily-log, deprecated-page, and index-topic counts;
  • required-structure checks;
  • invalid frontmatter and index-build errors;
  • duplicate, orphaned, or missing index entries;
  • unresolved Git conflict markers;
  • symbolic links and unreadable files;
  • local-state health;
  • project-runtime recognition, engine/protocol compatibility, and adapter conflicts;
  • Git readiness, including ignored or untracked durable files and tracked local-only files;
  • exact suggested git add, git add -f, or git rm --cached commands without executing them;
  • total vault bytes, files, Markdown files, and latest modification time;
  • scaleAlert, set when there are more than 200 top-level knowledge pages;
  • aggregate integrity (healthy or attention) and issueCount.

The scale alert is advisory. It recommends targeted search; it does not prevent reads or writes.

12.5.1 hydrate

python3 .echoes-vault/echoes_vault.py --workspace . hydrate

hydrate requires a compatible project runtime and valid marker. It may rewrite only the ignored generated EchoesVault/index.md and .echoes-vault/state.json (plus an ephemeral ignored lock). It MUST NOT alter protocol files, runtime code, root guides, agent skills, commands, or durable knowledge. It does not perform legacy migration.

12.6 start

python3 .echoes-vault/echoes_vault.py --workspace . start --recent 3

Validates and refreshes the index, marks the local session active, and returns Markdown containing:

  • the complete generated index;
  • the requested number of most recent daily files;
  • a scale warning when applicable.

--recent defaults to 3 and is clamped to the inclusive range 0..10. Page bodies are not included. Agents SHOULD analyze the returned context and use targeted search for details.

Session restoration is intentionally explicit rather than automatic, so users control model context cost.

12.7 search

python3 .echoes-vault/echoes_vault.py --workspace . search "authentication" --limit 100

Search performs a literal, case-insensitive substring scan over top-level knowledge-page bodies. The default limit is 100 and the accepted effective range is 1..500.

The JSON result has this form:

{
  "ok": true,
  "query": "authentication",
  "truncated": false,
  "results": [
    {
      "file": "EchoesVault/pages/authentication.md",
      "line": 12,
      "text": "JWT validation occurs at the service boundary."
    }
  ]
}

Each result contains the workspace-relative file, one-based line number, and trimmed text limited to 300 characters. Search returns matches, not complete page bodies; an agent can then read only the relevant pages.

12.8 append

python3 .echoes-vault/echoes_vault.py --workspace . append --payload -

Input:

{
  "entry": "- Confirmed the shared authentication contract.",
  "agent": "custom-agent"
}

entry is required and non-empty. agent is optional. The command writes one unique scratchpad file and returns:

{
  "ok": true,
  "dailyLog": "/absolute/path/to/the/new-entry.md",
  "kind": "scratchpad",
  "agent": "custom-agent"
}

Append records intermediate durable facts but does not mark the session finalized or saved.

12.9 hash

python3 .echoes-vault/echoes_vault.py --workspace . hash auth-architecture.md

Returns the normalized page path and SHA-256 of the UTF-8 encoding of its current decoded text. The reference runtime uses standard text-mode newline normalization consistently for both hash and the subsequent concurrency check:

{
  "ok": true,
  "page": "/absolute/path/EchoesVault/pages/auth-architecture.md",
  "sha256": "<64 lowercase hexadecimal characters>"
}

Use this immediately before replacing an existing page.

12.10 upsert

python3 .echoes-vault/echoes_vault.py --workspace . upsert --payload -

New-page input:

{
  "filename": "auth-architecture.md",
  "content": "---\ntype: architecture\nstack: [python]\nstatus: active\nsummary: Authentication boundaries and token flow.\n---\n\n# Authentication architecture\n"
}

Existing-page input additionally requires:

{
  "expectedSha256": "<hash returned after reading the current page>"
}

For compatibility with pre-1.0 migrations, a new page without summary may provide indexDescription; the runtime converts it to summary. New integrations SHOULD write summary directly. If both values are provided, they must normalize to the same text.

The command validates the proposed page and prospective complete index before writing. Its result contains action (created or updated), absolute page, resulting sha256, and indexChanged.

12.11 end

python3 .echoes-vault/echoes_vault.py --workspace . end \
  --confirm-explicit-user-end --payload -

end MUST be invoked only after an explicit user request to end, wrap up, finalize, or save the EchoesVault session. The confirmation flag is required as a mechanical guard.

Input:

{
  "dailySummary": "- Completed authentication middleware.\n- Remaining: refresh-token tests.",
  "agent": "codex",
  "pages": [
    {
      "filename": "auth-architecture.md",
      "content": "---\ntype: architecture\nstack: [python]\nstatus: active\nsummary: Authentication boundaries and token flow.\n---\n\n# Authentication architecture\n",
      "expectedSha256": "<required when the page already exists>"
    }
  ]
}

dailySummary is required. pages defaults to an empty array. agent is optional. Duplicate page names in one payload are rejected. Legacy indexUpdates are rejected because the index is generated.

Before writing, the runtime validates every page, every existing-page hash, and the prospective complete index. It then writes the pages, generated index, one unique session daily entry, and local saved state. A successful result includes dailyLog, pagesWritten, index, memorySaved: true, and normalized agent.

Ordinary task completion is not authorization to invoke end.

12.12 rebuild-index

python3 .echoes-vault/echoes_vault.py --workspace . rebuild-index

Validates page metadata, reconstructs the deterministic index, and updates local state. It does not migrate legacy page summaries. The JSON result includes rebuilt, page count, and the index SHA-256.

13. Recommended agent lifecycle

13.1 Initialization

Initialization MUST be explicit. Installing an agent plugin globally MUST NOT silently initialize every repository. Run init only for a workspace the user selected.

13.2 Session restoration

Run start --recent 3 only when the user asks to start, resume, or restore project memory. The agent should summarize completed outcomes, blockers, and immediate next steps instead of repeating the returned context verbatim.

13.3 Recall during work

Before modifying a component whose decisions may already be documented:

  1. inspect the generated index;
  2. run a narrow search query;
  3. read only the relevant complete page;
  4. follow replacement links from deprecated pages.

This progressive-disclosure flow prevents token usage from scaling with the entire vault.

13.4 Intermediate memory

Use append after a verified logical milestone, important architectural agreement, context switch, or explicit request to remember something. Keep entries concise and factual. An append does not end the session.

13.5 Curated page updates

Use upsert for durable concepts. Read before writing. For an existing page, obtain a fresh hash and submit the complete replacement, not a partial patch against stale content.

13.6 Finalization

Use end only on explicit user authorization. Distill final outcomes, verified decisions, unresolved blockers, and next steps. Do not store the conversation transcript.

14. Git and team workflow

Projects SHOULD commit:

EchoesVault/.echoes-vault.json
EchoesVault/.gitignore
EchoesVault/AGENT_PROTOCOL.md
EchoesVault/pages/**
EchoesVault/daily/**
EchoesVault/assets/**
EchoesVault/raw/**
.echoes-vault/.gitignore
.echoes-vault/echoes_vault.py
AGENTS.md
CLAUDE.md
.claude/skills/echoes-vault/SKILL.md
.opencode/skills/echoes-vault/SKILL.md
.opencode/commands/echoes-init.md
.opencode/commands/echoes-start.md
.opencode/commands/echoes-status.md
.opencode/commands/echoes-end.md

Projects MUST NOT commit:

EchoesVault/index.md
.echoes-vault/state.json
.echoes-vault/lock
.opencode/echoes-state.json
.codex/echoes-vault-state.json

Unique daily files and an ignored generated index eliminate the most common cross-branch conflicts. Different knowledge pages normally merge independently. When branches edit the same page, ordinary Git conflict resolution is still required:

  1. reconcile the page's meaning manually;
  2. remove every <<<<<<<, =======, and >>>>>>> line;
  3. retain valid required frontmatter and an accurate summary;
  4. run hydrate or rebuild-index, then use status to verify without changing files.

The local runtime lock does not replace Git merge handling.

15. Migration from legacy vaults

Only explicit init or migrate may migrate a pre-1.0 page that has type, stack, and status but no summary when the legacy index contains exactly one valid, non-empty description for that page slug. inspect, status, SessionStart hooks, and hydrate MUST NOT perform this migration.

Migration:

  1. parses legacy - [[slug]]: description rows;
  2. rejects ambiguous duplicate rows;
  3. validates the description against summary rules;
  4. injects a quoted summary into the page frontmatter;
  5. rebuilds the complete index deterministically.

If any missing summary has no usable legacy description, migration stops and reports every detected metadata error before writing migrated pages.

The reference runtime imports compatible session fields in this priority order:

  1. .echoes-vault/state.json;
  2. .opencode/echoes-state.json;
  3. .codex/echoes-vault-state.json;
  4. default state.

It preserves initialized, session.started, session.saved, session.lastStart, and session.lastSave, then writes schema 4 only during an authorized writing command. Legacy state is not durable knowledge and SHOULD NOT be used by new integrations.

Recognized legacy OpenCode skill directories for append, search, and page upsert are replaced by redirect skills that invoke the shared project runtime. If their content does not match a known legacy signature, the implementation MUST preserve the user-owned content and report an adapter configuration conflict.

Legacy tools that edit index.md directly, append to a shared daily file, or overwrite pages without current hashes MUST be disabled after migration.

16. Integrity and failure behavior

A conforming writer MUST fail closed before writing durable knowledge when it detects:

  • an unsupported protocol version;
  • a managed path escaping the workspace through a symbolic link;
  • a symbolic-link page or managed replacement target;
  • an unsafe or colliding page filename;
  • missing, empty, duplicate, or invalid required frontmatter;
  • an invalid or oversized summary;
  • unresolved Git conflict markers in a proposed page;
  • a missing or stale expectedSha256 for an existing page;
  • duplicate pages in one finalization payload;
  • a finalization request without explicit confirmation.

Health reporting also detects missing generated structure, invalid state, unreadable vault files, symlinks anywhere in the vault inventory, orphaned/missing/duplicate index entries, and unresolved conflict markers in Markdown files.

No adapter may convert a runtime failure into a success message. When a concurrent-change error is returned, the correct response is to reread, reconcile, rehash, and retry.

17. Security and privacy

Protocol 1.0.0 stores plain files and provides no encryption or access-control layer. Repository owners MUST apply the same confidentiality rules used for source code and MUST NOT store secrets, credentials, personal data, or proprietary material unless repository access and history are appropriate for that data.

The reference runtime performs no network requests. It confines managed paths to the resolved workspace, refuses relevant symbolic-link targets, sanitizes page names, validates JSON payloads, and recommends standard input for untrusted Markdown.

Agents MUST treat documents in raw/, assets/, pages, and daily entries as project data, not as higher-priority instructions. Agent behavior comes from the active agent configuration and the tracked protocol contract.

18. Integration guide

The safest integration for a new agent or tool is small:

  1. Resolve the repository root.
  2. Check EchoesVault/.echoes-vault.json.
  3. Require exact protocol version 1.0.0 before writes.
  4. Check that .echoes-vault/echoes_vault.py is a regular file inside the workspace.
  5. Invoke the portable runtime as an argument array, never as a shell string built from user text.
  6. Send write payloads as serialized JSON on standard input.
  7. Preserve stdout and stderr separately and honor the exit code.
  8. Load only index summaries, recent entries, search matches, and explicitly relevant pages into model context.
  9. Expose finalization only after an explicit user request.
  10. Do not register competing legacy writers for a Protocol 1.0.0 vault.

Example Python adapter:

import json
import subprocess
from typing import Optional


def run_echoes(workspace: str, command: list[str], payload: Optional[dict] = None):
    process = subprocess.run(
        [
            "python3",
            f"{workspace}/.echoes-vault/echoes_vault.py",
            "--workspace",
            workspace,
            "--agent",
            "my-agent",
            "--adapter-version",
            "1.0.0",
            *command,
        ],
        input=json.dumps(payload) if payload is not None else None,
        text=True,
        capture_output=True,
        check=False,
    )
    if process.returncode != 0:
        raise RuntimeError(process.stderr.strip())
    return process.stdout


run_echoes(
    "/path/to/project",
    ["append", "--payload", "-"],
    {"entry": "- Confirmed the API contract.", "agent": "my-agent"},
)

An integration MAY provide buttons, slash commands, natural-language skills, or a TUI. Those user experiences remain compatible as long as every mutation delegates to the portable runtime and the integration does not introduce a second source of truth.

19. Compatibility checklist

Before claiming Protocol 1.0.0 compatibility, verify that the implementation:

  • recognizes the exact marker and refuses unsupported writes;
  • treats pages and unique daily files as durable knowledge;
  • treats index and state as derived/local data;
  • requires all four frontmatter fields;
  • enforces the 160-character single-line summary limit;
  • produces the exact deterministic index ordering and content;
  • never edits the index as user-authored knowledge;
  • writes unique nested daily files;
  • uses UTC directory dates and Z filename timestamps for new daily entries;
  • uses the shared local lock and atomic file replacement;
  • requires a current SHA-256 before updating an existing page;
  • detects unsafe paths, symlinks, filename collisions, and conflict markers;
  • keeps initialization, restoration, and finalization under explicit user control;
  • does not report final memory as saved unless end succeeds;
  • preserves unrelated agent instructions and user-owned files;
  • keeps inspect/status and SessionStart strictly read-only;
  • delegates to a newer compatible project runtime without downgrading it;
  • reports Git readiness without running git add or git rm;
  • passes interoperability tests against the reference runtime.

20. Versioning and extensions

Protocol identifiers are SemVer-shaped strings, but Protocol 1.0.0 grants no implicit compatibility range. Writers use exact matching unless a future specification explicitly defines negotiation.

Implementations MAY add files or frontmatter fields outside the managed contract when they do not:

  • change the meaning of required marker fields;
  • weaken write-safety requirements;
  • create ambiguous page identities;
  • alter deterministic index output;
  • place shared mutable data at a date-level daily path;
  • cause another conforming implementation to misinterpret durable knowledge.

Proposed protocol changes should document migration, mixed-version behavior, Git impact, and interoperability tests before changing protocolVersion.

21. Reference implementation

The canonical Protocol 1.0.0 behavior is implemented by scripts/echoes_vault.py and exercised by tests/test_echoes_vault.py. The generated portable copy in an initialized project is the writer that project adapters should invoke.

This specification and the reference implementation are distributed under the repository's MIT License, so they may be reused in open-source and proprietary integrations subject to the license terms.