1
0
forked from jason/echo

Phase 5: group-voice docs, onboarding runbook, CHORUS icon — v2.0.0-rc.1

The final phase of CHORUS-PLAN.md. Code- and doc-complete for group use;
rc pends live deployment at chorusapi.mpm.to.

- Repo README rewritten for CHORUS: group model (schema 5), concurrency
  posture, configuration, baked-build onboarding, layout, testing, 2.0
  version history (ECHO history referenced at the fork tag).
- Operator→member voice sweep across SKILL.md (incl. the trigger
  description, now group-aware), all references, 8 command docs, plugin
  README; member preferences / semantic layer / triage guidance describe
  the group model.
- docs/ONBOARDING.md: member runbook — vault stand-up, per-member config,
  bake, deliver, self-onboarding first load, norms, offboarding.
- docs/USAGE.md rewritten as the member usage guide.
- New icon: chorus-icon.svg + 1024/512/64 PNGs (three voices, one center).
- Removed ECHO-era assets (icons, spec PDF, perf briefs); ECHO planning
  docs retired to docs/history/. All preserved at echo-fork-point.
- eval/README documents test_multimember.py. Manifest -> 2.0.0-rc.1;
  rebuilt chorus-memory.plugin.

Verified: routing-sync, 25/25 unit, scaffold, 5 mock e2e suites,
run_eval metrics green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-21 15:41:58 -05:00
parent 1a7690426f
commit f2bfd70dd4
36 changed files with 324 additions and 807 deletions
+40 -61
View File
@@ -1,89 +1,68 @@
# ECHO Memory — Usage Guide
# CHORUS Memory — Usage Guide
*Written for Bryan (and anyone else coming back to ECHO after a break). Current as of v1.5.1, July 2026.*
*Written for any group member coming to CHORUS (or back to it after a break). Current as of v2.0.0-rc.1, July 2026. Setup itself is in [ONBOARDING.md](ONBOARDING.md).*
ECHO gives Claude persistent memory across sessions. Everything durable — people, companies, projects, decisions, preferences, session history — lives as markdown notes in an Obsidian vault, read and written over the Obsidian Local REST API. The plugin ships the whole toolchain (pure Python, stdlib only — works the same on Windows/macOS/Linux) plus the operating procedure Claude follows.
CHORUS gives Claude persistent **group memory** across sessions. Everything durable — people, companies, projects, decisions, session history, each member's preferences — lives as markdown notes in one shared Obsidian vault, read and written over the Obsidian Local REST API. The whole team's sessions work against the same knowledge graph, and every agent write is attributed (`author: <member>`), so you always know who knows what.
The short version of how to use it: **you mostly don't have to do anything.** Since v1.5 the system loads itself at session start and nudges itself to save at session end. The slash commands below are for when you want to drive it explicitly.
The short version of how to use it: **you mostly don't have to do anything.** The system loads itself at session start (and onboards you automatically on your very first session), and nudges itself to save at session end. The slash commands below are for when you want to drive it explicitly.
---
## One-time setup
If Jason handed you a **per-user baked plugin** (`echo-memory-1.x.x-bryan.plugin`), just install it. Your vault credentials are baked into the artifact — no config file, no key pasting, works on desktop and in every CoWork session. This is the normal path.
You were handed a **per-member baked plugin** (`chorus-memory-2.x-<you>.plugin`). Just install it — your member id, the endpoint, and the vault key are baked in. No config file, no key pasting, works on desktop and in every CoWork session. Treat the file like a password: it contains the live vault key. Don't share or commit it.
If you have the **generic plugin** instead, it will report `NOT CONFIGURED` on first use and ask for your config file. Install it once with:
```bash
python3 echo.py config import <your-config.json>
```
That writes `~/.claude/echo-memory/config.json` (owner, endpoint, API key). It survives plugin updates — one time per machine.
**Verify either way:** run `/echo-doctor`. Green across the board (Python, vault reachable, auth, bootstrapped, key source) means you're live.
**Verify:** run `/chorus-doctor`. Green across the board (Python, endpoint, key, **member id**, group, vault reachable, bootstrapped schema 5) means you're live. Your first `load` creates your `_agent/members/<you>/` namespace and adds you to the group roster — nothing to do on your side.
---
## Day-to-day usage
### What happens automatically (v1.5+)
### What happens automatically
- **Session start** — a hook runs the cold-start load and injects your memory into context: your profile/preferences, current scope, the last session log, today's journal note, and inbox depth. You don't have to ask Claude to "load memory" anymore.
- **Session end** — if the session was substantive and nothing was saved, a hook nudges (once) to run `/echo-reflect` and write the session log. Reflection always previews before writing — nothing lands without your OK.
- **If the vault is unreachable**, writes queue to a local outbox and replay automatically next time it's up; reads fall back to a cached last-known-good. An outage degrades gracefully instead of erroring.
- **Session start** — a hook runs the cold-start load and injects memory into context: the **group profile**, *your* preferences, *your* current scope, *your* last session, today's **shared** journal note, and both inbox depths (yours + the group's).
- **Session end** — if the session was substantive and nothing was saved, a hook nudges (once) to run `/chorus-reflect` and write the session log. Reflection always previews before writing — nothing lands without your OK.
- **If the vault is unreachable**, writes queue to a local outbox and replay automatically next time it's up; reads fall back to a cached last-known-good.
### The slash commands
| Command | When to use it |
|---|---|
| `/echo-load` | Manually load memory context. Rarely needed now — the session-start hook does this — but useful mid-session after a lot of vault writes, or if the hook didn't fire. |
| `/echo-save <thing>` | Save something right now: "remember the Henagar tower password is in the vault", "log that we decided X". Routes it to the right note automatically. |
| `/echo-recall <topic>` | Ask what memory knows about a topic. Returns ranked matches **plus their linked neighbourhood** — a project comes back with its people, decisions, and recent session mentions attached. |
| `/echo-reflect` | End-of-session sweep: extracts durable facts, decisions, and new entities from the conversation, shows you the proposed writes, applies on confirm. The main way memory grows. |
| `/echo-triage` | Empty the inbox: classifies each quick capture, previews destinations, routes accepted items with an audit trail. Run when load reports the inbox is getting deep. |
| `/echo-doctor` | Readiness check — Python, vault reachability, auth, bootstrap/schema version, where the key came from. First stop when anything seems off. |
| `/echo-health` | Full vault lint: routing violations, broken wikilinks, orphan notes, stale scope, incomplete frontmatter, index drift. Run occasionally or when things feel inconsistent. |
| `/echo-sweep` | Bring the vault up to the current plugin spec after an upgrade — rebuilds the entity index, backfills frontmatter, fixes one-way links. Dry-run by default; **run this once right after updating from an old version.** |
| `/chorus-load` | Manually load memory context (the session-start hook usually does this). `load --all-members` adds a group-wide view: every member's scope and last session. |
| `/chorus-save <thing>` | Save something right now: "remember the Henagar tower password is in the vault", "log that we decided X". Routes it to the right note automatically, attributed to you. |
| `/chorus-recall <topic>` | Ask what the GROUP's memory knows about a topic — including things teammates saved. Returns ranked matches plus their linked neighbourhood; add `--author <member>` to see one person's notes only. |
| `/chorus-reflect` | End-of-session sweep: extracts durable facts, decisions, and new entities from the conversation, previews, applies on confirm. The main way memory grows. |
| `/chorus-triage` | Empty the inboxes — **yours and the group's**: classifies each capture, previews destinations, routes accepted items with a who-routed-what audit trail. |
| `/chorus-doctor` | Readiness check — Python, vault reachability, auth, member id, bootstrap/schema, key source. First stop when anything seems off. |
| `/chorus-health` | Full vault lint: routing violations, broken wikilinks, orphans, per-member stale scopes and aging inboxes, unattributed agent notes, index drift. |
| `/chorus-sweep` | Bring the vault up to the current plugin spec after an upgrade — rebuilds indexes, backfills frontmatter, fixes one-way links. Dry-run by default. |
### A typical session
1. Start a conversation — memory loads itself. Claude knows who you are, what's active, and what happened last session.
2. Work normally. Say "save that" / "remember this" whenever something durable comes up (or `/echo-save` explicitly). Not sure where something belongs? Save it anyway — it lands in the inbox and `/echo-triage` sorts it later.
3. At the end, accept the reflection nudge (or run `/echo-reflect` yourself). Confirm the preview. Done — next session picks up from here.
1. Start a conversation — memory loads itself. Claude knows who *you* are, what the group is, what you were doing, and what happened in your last session.
2. Work normally. Say "save that" / "remember this" whenever something durable comes up. Not sure where it belongs? It lands in **your** inbox; something the *team* should see lands in the **group inbox**.
3. At the end, accept the reflection nudge (or run `/chorus-reflect`). Confirm the preview. Done — your next session picks up from here, and your teammates' sessions can already see what you saved.
### Group etiquette (the short list)
- **Shared knowledge is everyone's.** Projects, people, companies, decisions — read them, update them (your updates are member-tagged), link to them.
- **Namespaces are personal.** Never edit another member's `_agent/members/<id>/` files. A fact about a person goes in `resources/people/`; a teammate's *preference* is theirs to record.
- **The duplicate gate is a teammate detector.** If a save is blocked with "likely already exists — created by jason", that's the system telling you the group already tracks it. Merge into the existing note.
- **Everything is group-visible.** One vault, one key. Truly private material belongs in a personal vault, not CHORUS.
---
## What the memory system can do (current capabilities)
## What the memory system can do
**Smart, deduplicating capture.** One `capture` call routes content to its canonical home via an entity index, stamps complete frontmatter (status, tags, timestamps), cross-links every entity it mentions, and logs the write. Names resolve through aliases and fuzzy matching, so "echo memory" finds the `echo` project instead of spawning a duplicate note. If a new title strongly resembles an existing **same-kind** entity, a pre-write duplicate gate *stops* the write and shows you the candidates — you choose merge or create. Duplicates get blocked before they exist, not cleaned up after.
**Smart, attributed, deduplicating capture.** One `capture` call routes content to its canonical home via a shared entity index, stamps complete frontmatter (status, tags, timestamps, **author**), cross-links every entity it mentions, and writes a member-tagged line on the team's daily log. Names resolve through aliases and fuzzy matching; a pre-write duplicate gate stops near-duplicates *before* they exist and names whose entity you collided with.
**Real retrieval, not keyword grep.** Recall fuses BM25 full-text search with graph expansion along note links, over entities *and* session logs *and* journal entries. Ranking is freshness- and status-aware: recently updated and `active` notes float up, `archived` sinks. You get a topic's connected neighbourhood, not one isolated file.
**Real retrieval over the whole group's knowledge.** Recall fuses BM25 full-text search with graph expansion along note links, over entities *and* every member's session logs *and* the journal. Ranking is freshness- and status-aware. Filter to one member with `--author`.
**Structured memory model.** Working (transient) / episodic (what happened, when) / semantic (durable facts and preferences) memory layers, plus a current-context scope, per-session logs, an append-only journal with rollups, and PARA-style projects/areas/resources/decisions. A machine-readable routing manifest defines what may be written where, and the linter enforces it.
**Structured memory model.** Working / episodic / semantic layers plus the group profile, per-member scope + preferences + inbox + sessions, an append-only shared journal with rollups, and PARA-style projects/areas/resources/decisions. A machine-readable routing manifest defines what may be written where, and the linter enforces it.
**Reflection.** `/echo-reflect` turns a conversation into memory: extract → classify → dedup against the index → confidence-filter → preview → apply. Low-confidence items go to the inbox instead of polluting the graph.
**Durability and safety.** Every write is HTTP-status-checked and read-back-verified. Appends are idempotent. Offline writes queue and replay. Shared indexes are lock-guarded with retry, and lock owners are member-attributed. The per-member namespacing means teammates' sessions can't clobber your scope or heartbeat even in principle.
**Durability and safety.** Every write is HTTP-status-checked and read-back-verified (a failed write fails loudly, never silently). Appends are idempotent — retries can't double-write. Offline writes queue and replay. A cooperative advisory lock keeps Claude Code and CoWork from trampling each other on the shared vault.
**Self-maintaining.** The vault bootstraps itself from an empty Obsidian vault, migrates its own schema on version bumps, and `/echo-sweep` + `/echo-health` keep the graph honest (index rebuilds, link symmetry, frontmatter backfill, orphan/broken-link detection).
**Fast.** Connection pooling + concurrent reads mean full-vault operations that used to time out in the sandbox now finish in under a second.
---
## What's new since 0.7 (your last consistent version)
You left off right after the toolchain got its executable spine (`echo.py`, routing manifest, linter). Since then, in rough order of what you'll actually notice:
- **You don't route anything by hand anymore.** 0.7 was "pick the path, write with the right verb." Now `capture`/`recall`/`resolve`/`link` do routing, frontmatter, indexing, and cross-linking in one call — and in practice you just talk to Claude and it uses them.
- **Memory loads and saves itself** (v1.5 hooks). No more remembering to run the loading procedure or write the session log.
- **Recall is actually good now** (v0.91.5): entity index + hybrid BM25/graph search + freshness/status ranking, spanning sessions and journal too.
- **Duplicates get blocked at write time** (v1.5 gate) instead of accumulating.
- **Offline resilience** (v1.0): vault down ≠ data lost; writes queue and replay.
- **Everything is pure Python** (v0.8): no bash, works identically on Windows.
- **Credentials moved out of the plugin** (v1.31.4): generic builds prompt once per machine; your baked build carries them invisibly. Treat a baked `.plugin` file like a password — it contains your vault key. Don't share or commit it.
**After installing the new version, run `/echo-doctor`, then `/echo-sweep` once** to bring your vault up to the current schema (it dry-runs first and shows the plan).
**Self-maintaining, self-onboarding.** The vault bootstraps itself from empty, onboards new members on their first load, migrates its own schema on version bumps, and `/chorus-sweep` + `/chorus-health` keep the graph honest.
---
@@ -91,9 +70,9 @@ You left off right after the toolchain got its executable spine (`echo.py`, rout
| Symptom | Fix |
|---|---|
| `NOT CONFIGURED` banner / doctor shows red config | Generic build with no config on this machine — `echo.py config import <file>`, or ask Jason for your baked build. |
| Vault unreachable | Check that Obsidian + the Local REST API plugin are running on the backend and the endpoint is reachable. Meanwhile writes queue safely and replay on reconnect. |
| Save blocked with "duplicate gate" (exit 76) | Not an error — it found a likely-existing entity. Review the candidates: merge into the existing note, or force-create if it's genuinely distinct. |
| Memory feels stale or inconsistent | `/echo-health` to see what's off, `/echo-sweep` to repair index/links/frontmatter. |
| Inbox keeps getting mentioned at load | `/echo-triage` — one pass empties it. |
| Anything else weird | `/echo-doctor` first, then ask Jason. |
| `NOT CONFIGURED` banner / doctor shows red config | Your build isn't baked or the config is missing this machine — see [ONBOARDING.md](ONBOARDING.md), or ask the vault admin for your baked build. |
| Vault unreachable | Obsidian + the Local REST API + the proxy at `chorusapi.mpm.to` must be up. Meanwhile writes queue safely and replay on reconnect. |
| Save blocked with "duplicate gate … created by \<member\>" (exit 76) | Not an error — the group already tracks that entity. Merge into the existing note (`--merge-into <slug>`), or force-create if genuinely distinct. |
| Memory feels stale or inconsistent | `/chorus-health` to see what's off, `/chorus-sweep` to repair. |
| Inboxes keep getting mentioned at load | `/chorus-triage` — one pass empties both. |
| Anything else weird | `/chorus-doctor` first, then ask the vault admin. |