This commit is contained in:
Jason Stedwell
2026-06-19 21:12:14 -05:00
parent a860819bfb
commit 2fc3a0a80b
26 changed files with 1559 additions and 89 deletions
@@ -30,6 +30,49 @@ The endpoint has a **valid TLS certificate**, so `-k` is not needed (add it only
- Complete endpoint→logic routing map (every write destination, its trigger, and why it's distinct): `references/routing-map.md`
- Full API reference with every endpoint pattern and the memory routing map: `references/api-reference.md`
Executable logic ships under `scripts/`:
- `scripts/echo.sh` — the **validated API client**; prefer it over hand-built `curl` (below)
- `scripts/routing.json` — the **canonical, machine-readable** route manifest (the routing map's source of truth; the linter enforces it)
- `scripts/vault-lint.sh` — read-only invariant checker (Vault Health)
- `scripts/bootstrap.sh` / `scripts/migrate.sh` — deterministic vault setup/repair and schema migration
## Bundled Tooling (prefer over raw curl)
All paths below are under `${CLAUDE_PLUGIN_ROOT}/skills/echo-memory/`.
**`scripts/echo.sh` — use this for every read/write.** It centralizes auth, **HTTP-status checking** (a failed write exits non-zero instead of looking like success), one bounded retry on 5xx/connection errors, idempotent append, correct `::` heading targets, and frontmatter patches. The raw `curl` recipes later in this file are the underlying mechanics / fallback — reach for them only if `echo.sh` is unavailable, and if you do, **check the HTTP status yourself** (the PATCH-heading `400 invalid-target` failure silently loses writes otherwise).
```bash
ECHO="${CLAUDE_PLUGIN_ROOT}/skills/echo-memory/scripts/echo.sh"
"$ECHO" get <path> # 404 -> exit 44
"$ECHO" ls <dir> ; "$ECHO" map <path> # listing / document-map
"$ECHO" search <terms...>
"$ECHO" put <path> <file> # create/overwrite (read-back verified)
"$ECHO" append <path> "<line>" # idempotent: skips if the exact line exists
"$ECHO" patch <path> append heading "<H1::Sub>" <file>
"$ECHO" fm <path> updated '"2026-06-19"' ; "$ECHO" bump <path> # frontmatter
"$ECHO" lock <session-id> ; "$ECHO" unlock <session-id>
```
**Bootstrap / migrate** are scripts now, not hand-run curl loops: `scripts/bootstrap.sh [--dry-run]` (idempotent, probe-before-write, never overwrites) and `scripts/migrate.sh [--apply]` (reads the marker's `schema_version` and applies migrations; dry-run by default). See `references/bootstrap.md`.
### Concurrency — the vault is shared, so coordinate writes
ECHO is read/written by multiple clients (Claude Code **and** CoWork sessions). The single-line files (`heartbeat/last-session.md`, `current-context.md::Scope`, `inbox.md`) assume a single writer at a time. Before a burst of writes in a session that may overlap another, take the **advisory lock**, and release it at session end:
```bash
"$ECHO" lock "cc-$(date +%s)" # exit 75 if another session holds a fresh lock
# ... do the writes ...
"$ECHO" unlock "cc-$(date +%s)"
```
The lock is cooperative (a stale lock past `ECHO_LOCK_TTL`, default 15 min, is reclaimable) and lives at `_agent/locks/vault.lock`. It is a courtesy, not a hard mutex — if you can't take it, tell Jason another session may be active rather than racing it.
### Slash commands
`/echo-load` (cold-start read), `/echo-save <text>` (route + persist), `/echo-triage` (drain the inbox), `/echo-health` (run the linter). These are explicit entry points to the procedures below.
## Operating Contract & Safety
The vault is the **system of record** for long-term memory, not a scratchpad. Default to **additive updates, explicit status changes, and traceable summaries**. Keep agent-managed content (`agent_written: true` + `source_notes`) separable from human-authored content. Non-negotiable safety rules:
@@ -294,20 +337,22 @@ A weekly/monthly rollup is a **light digest** — open threads across `projects/
On the first substantive session of a calendar month, run a quick health pass and write findings to `_agent/health/YYYY-MM-vault-health.md`. This is **agent self-maintenance, not a journal entry** — it lives under `_agent/` because it's about the vault's mechanical integrity, not Jason's work narrative. Don't auto-fix without asking.
Run the bundled linter first — it mechanically checks the invariants below so you don't eyeball them:
Run the bundled linter first — it mechanically checks the invariants below so you don't eyeball them. **Pass `ECHO_TODAY` = the conversation's `currentDate`** so stale/aging math uses the same clock you write with (not the runner's machine date):
```bash
bash "${CLAUDE_PLUGIN_ROOT}/skills/echo-memory/scripts/vault-lint.sh"
ECHO_TODAY=<currentDate> "${CLAUDE_PLUGIN_ROOT}/skills/echo-memory/scripts/vault-lint.sh"
```
Checks (the linter asserts each and prints violations):
Exit codes: `0` clean · `1` violations · `2` unreachable · `3` not bootstrapped. Checks (the linter asserts each and prints violations):
1. **Stale active projects** — for each note in `projects/active/`, check `updated:` >30 days. Likely belongs in `on-hold/`.
2. **Unprocessed inbox** — GET `inbox/captures/inbox.md`. List items older than 14 days that never moved through the triage protocol.
3. **Duplicate slugs across lifecycle folders** — any slug appearing in more than one of `active/`, `incubating/`, `on-hold/`, `archived/` is broken state.
4. **Folder ↔ `status:` mismatch** — any `projects/<lifecycle>/` note whose `status:` frontmatter disagrees with its folder.
5. **Wikilinks in frontmatter** — any `[[...]]` inside a YAML frontmatter block (breaks Obsidian reading view).
5. **Wikilinks in frontmatter** — any `[[...]]` inside a YAML frontmatter block (breaks Obsidian reading view), swept across all folders.
6. **Duplicate `## Agent Log` headings** — any daily note with more than one.
7. **Unknown / retired paths** — any vault file that matches no route in `scripts/routing.json` (or sits at a retired path).
8. **Frontmatter integrity** — missing required fields, `updated` < `created`, future `updated`, and `[[wikilinks]]` leaking into `source_notes`.
The pass is cheap and pays for itself by catching drift before it requires a reorg. Write the findings as a digest; act on them only with Jason's go-ahead.