diff --git a/README.md b/README.md index 8da4772..5992456 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# echo-memory — v0.7 +# echo-memory — v0.7.1 Persistent memory for Claude / CoWork sessions via the **ECHO** Obsidian vault, driven over the [Obsidian Local REST API](https://github.com/coddingtonbear/obsidian-local-rest-api). No MCP server — the skill makes direct REST calls, now through a bundled validated client (`scripts/echo.sh`). @@ -89,9 +89,9 @@ Executable logic ships under `skills/echo-memory/scripts/`; the agent prefers it | Tool | Purpose | |------|---------| -| `echo.sh` | The validated API client. `get/ls/map/search/put/post/append/patch/fm/bump/delete/lock/unlock`. Injects auth, **checks HTTP status** (non-zero exit on ≥400 — a failed write can't masquerade as success), one bounded retry on transient 5xx/connection errors, read-back verify on PUT, idempotent `append` (read-before-POST), correct `::` heading targets. | +| `echo.sh` | The validated API client. `get/ls/map/search/put/post/append/patch/fm/bump/delete/lock/unlock/scope`. Injects auth, **checks HTTP status** (non-zero exit on ≥400 — a failed write can't masquerade as success), one bounded retry on transient 5xx/connection errors, read-back verify on PUT, idempotent `append` (read-before-POST), correct `::` heading targets. `scope show` reports the active scope + its freshness; `scope set ""` switches it atomically (archive prior → replace → stamp `scope_updated`). | | `routing.json` | The **canonical machine-readable** route manifest — one regex pattern per valid destination plus retired paths. The single source of truth for "what may be written where"; `vault-lint.sh` enforces it. | -| `vault-lint.sh` | Read-only invariant checker (Vault Health). Real YAML parsing, clock injected via `ECHO_TODAY`, exits `3` if the vault isn't bootstrapped (instead of falsely reporting "clean"). | +| `vault-lint.sh` | Read-only invariant checker (Vault Health). Real YAML parsing, clock injected via `ECHO_TODAY`, exits `3` if the vault isn't bootstrapped (instead of falsely reporting "clean"). Includes a **scope-drift** check (flags when ≥ `SCOPE_STALE_SESSIONS` session logs postdate `scope_updated`). | | `bootstrap.sh` | Deterministic, idempotent, probe-before-write vault setup/repair (`--dry-run` to preview). Resolves the scaffold relative to itself, so it works from any CWD. | | `migrate.sh` | Deterministic schema migration. Dry-run by default; destructive steps gated behind `--apply` and printed first. | @@ -195,7 +195,11 @@ Promotion = move the file **and** update `status:` in the same change. ### Scope switching -`_agent/context/current-context.md` tracks one active scope. When scope changes: (1) PATCH-prepend a dated bullet capturing the **prior** scope to `## Scope History`; (2) PATCH-replace `## Scope` with the new scope; (3) bump the frontmatter `updated:`. Scope History is trimmed to the last ~10 entries. +`_agent/context/current-context.md` tracks one active scope. It is the **most churn-prone state** — several sessions a day across different topics — so without care a new session silently inherits a stale scope (the same failure class as inbox auto-fire). 0.7.1 hardens this three ways: + +- **Freshness signal** — a `scope_updated:` frontmatter timestamp records when scope last changed. +- **One-command switch** — `echo.sh scope set ""` does it atomically: archive the prior scope to `## Scope History` (dated, truncated), replace `## Scope`, and stamp `scope_updated`. (Manual fallback: prepend history → replace `## Scope` → PATCH `scope_updated`; the field must already exist or PATCH returns `400 invalid-target`.) Scope History is trimmed to the last ~10 entries. +- **Drift detection** — at load the agent runs `echo.sh scope show` (prints the scope, its `scope_updated`, and how many sessions have been logged since) and *states + confirms* scope before working, switching if it diverges. As a backstop, `vault-lint.sh` flags when ≥ `SCOPE_STALE_SESSIONS` (default 3) session logs postdate `scope_updated` — surfaced in `/echo-health`, so drift is mechanically **evaluable** rather than invisible. ### Daily note — Agent Log @@ -215,7 +219,7 @@ The journal is one append-only time-series stream; rollups are coarser-grained e ### Vault Health (monthly) -Agent self-maintenance (not a journal entry), written to `_agent/health/YYYY-MM-vault-health.md`. Run `scripts/vault-lint.sh` (or `/echo-health`) with `ECHO_TODAY` = the conversation's date so stale/aging math uses one clock. It mechanically asserts: folder↔status mismatch, duplicate slugs across lifecycle folders, wikilinks in frontmatter (swept across all folders), duplicate `## Agent Log` headings, stale active projects (`updated:` > 30 days), aging inbox items (> 14 days), **paths matching no route in `routing.json` or sitting at a retired path**, and **frontmatter integrity** (missing required fields, `updated` < `created`, future dates, wikilinks leaking into `source_notes`). Exit codes: `0` clean · `1` violations · `2` unreachable · `3` not bootstrapped. Findings are reported, not auto-fixed. +Agent self-maintenance (not a journal entry), written to `_agent/health/YYYY-MM-vault-health.md`. Run `scripts/vault-lint.sh` (or `/echo-health`) with `ECHO_TODAY` = the conversation's date so stale/aging math uses one clock. It mechanically asserts: folder↔status mismatch, duplicate slugs across lifecycle folders, wikilinks in frontmatter (swept across all folders), duplicate `## Agent Log` headings, stale active projects (`updated:` > 30 days), aging inbox items (> 14 days), **paths matching no route in `routing.json` or sitting at a retired path**, **frontmatter integrity** (missing required fields, `updated` < `created`, future dates, wikilinks leaking into `source_notes`), and **scope drift** (≥ `SCOPE_STALE_SESSIONS` session logs dated after `scope_updated`). Exit codes: `0` clean · `1` violations · `2` unreachable · `3` not bootstrapped. Findings are reported, not auto-fixed. --- diff --git a/echo-memory-0.7.1.plugin b/echo-memory-0.7.1.plugin index 07f501f..d3810b8 100644 Binary files a/echo-memory-0.7.1.plugin and b/echo-memory-0.7.1.plugin differ diff --git a/echo-memory.plugin b/echo-memory.plugin index 07f501f..d3810b8 100644 Binary files a/echo-memory.plugin and b/echo-memory.plugin differ diff --git a/echo-memory.plugin.src/README.md b/echo-memory.plugin.src/README.md index 1e0ced6..1fe2982 100644 --- a/echo-memory.plugin.src/README.md +++ b/echo-memory.plugin.src/README.md @@ -60,7 +60,7 @@ skills/echo-memory/ │ ├── api-reference.md ← REST endpoint patterns + routing map │ └── session-log-template.md ├── scripts/ -│ ├── echo.sh ← validated API client (auth, status-check, retry, verify, lock) +│ ├── echo.sh ← validated API client (auth, status-check, retry, verify, lock, scope) │ ├── routing.json ← canonical machine-readable route manifest (linter enforces it) │ ├── vault-lint.sh ← read-only invariant checker (monthly Vault Health pass) │ ├── bootstrap.sh ← deterministic, idempotent vault setup/repair