Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
"name": "TerminallyLazy",
"url": "https://github.com/TerminallyLazy"
},
"description": "Claude Code marketplace for Tree Ring Memory v0.14 local-first recall and receipt-backed harness readiness.",
"version": "0.3.1",
"description": "Claude Code marketplace for Tree Ring Memory v0.15 verified bootstrap, local-first recall, and receipt-backed harness readiness.",
"version": "0.3.2",
"plugins": [
{
"name": "tree-ring-memory",
"source": "./plugins/tree-ring-memory",
"displayName": "Tree Ring Memory",
"description": "Local-first memory lifecycle and receipt-backed harness guidance for Claude Code using Tree Ring Memory v0.14+.",
"description": "Local-first memory lifecycle, project bootstrap, and receipt-backed harness guidance for Claude Code using Tree Ring Memory v0.15+.",
"author": {
"name": "TerminallyLazy",
"url": "https://github.com/TerminallyLazy"
Expand Down
7 changes: 4 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ members = [
resolver = "2"

[workspace.package]
version = "0.14.0"
version = "0.15.0"
edition = "2021"
license = "MIT"
authors = ["TerminallyLazy"]
Expand All @@ -22,6 +22,7 @@ regex = "1"
rusqlite = { version = "0.32", features = ["bundled", "functions"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
semver = "1"
sha2 = "0.10"
tempfile = "3"
thiserror = "1"
Expand Down
76 changes: 57 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ framework-agnostic and does not replace either protocol.
Tree Ring Memory is in protocol-preview status. Current launch links:

- Launch page: <https://terminallylazy.github.io/Tree-Ring-Memory/>
- Launch release: <https://github.com/TerminallyLazy/Tree-Ring-Memory/releases/tag/v0.14.0>
- Launch release: <https://github.com/TerminallyLazy/Tree-Ring-Memory/releases/tag/v0.15.0>
- Launch discussion: <https://github.com/TerminallyLazy/Tree-Ring-Memory/discussions/27>
- Rust-native CLI article: <https://terminallylazy.github.io/Tree-Ring-Memory/launch/rust-native-agent-memory-cli.md>
- Feedback issue: <https://github.com/TerminallyLazy/Tree-Ring-Memory/issues/26>
Expand All @@ -40,6 +40,7 @@ Tree Ring Memory is in protocol-preview status. Current launch links:
- v0.12 adds a controlled, retained agent-workflow proof with explicit model identity and exact structured-output checks; it reports observed outcomes without claiming a universal memory advantage.
- v0.13 adds same-host multi-agent identities and idempotency, opt-in coordinator authorization for shared writes, a protected-write audit, and a schema-v3 fence for old memory inserts, updates, and deletes.
- v0.14 adds project-local harness activation with receipt-backed readiness, so configured bridges do not imply that an agent has used memory.
- v0.15 adds verified release bootstrap, project-root-aware agent guidance, and scope-preserving CLI updates.

</details>

Expand Down Expand Up @@ -147,7 +148,9 @@ Add and install the same package in Claude Code:
/plugin install tree-ring-memory@tree-ring-memory
```

The plugin still requires Tree Ring Memory CLI v0.14.0 or newer. See the
The plugin requires Tree Ring Memory CLI v0.15.0 or newer and teaches agents how
to install a verified project-local runtime when setup is already authorized.
See the
[plugin README](plugins/tree-ring-memory/README.md) for the platform manifests,
commands, DOX contract flow, and certification boundary.

Expand All @@ -174,18 +177,17 @@ The matching Tree Ring core and Agent Zero plugin release must both be
installed; a source checkout, a passive binding, or an older bundled CLI is not
an installed-capability claim.

Source install (requires Rust and Cargo):
Verified prebuilt install for macOS ARM64 or Linux x86_64:

```bash
curl -fsSL https://raw.githubusercontent.com/TerminallyLazy/Tree-Ring-Memory/main/install.sh | sh
curl -fsSL https://raw.githubusercontent.com/TerminallyLazy/Tree-Ring-Memory/main/install.sh | sh -s -- --release latest
```

Linux x86_64 prebuilt install (glibc 2.36 or newer):
Recommended project-local install with first-run initialization:

```bash
curl -fsSL https://raw.githubusercontent.com/TerminallyLazy/Tree-Ring-Memory/main/install.sh | sh -s -- \
--archive-url https://github.com/TerminallyLazy/Tree-Ring-Memory/releases/download/v0.14.0/tree-ring-memory-0.14.0-linux-x86_64.tar.gz \
--archive-sha256 c72191aca81f195472272a1962df354fe0af04a08b01a7472a1faf987cd177fa
cd <project-root>
curl -fsSL https://raw.githubusercontent.com/TerminallyLazy/Tree-Ring-Memory/main/install.sh | sh -s -- --project --init --release latest --no-animation
```

macOS ARM64 install with Homebrew:
Expand All @@ -195,10 +197,10 @@ brew tap TerminallyLazy/tree-ring
brew install tree-ring
```

Project-local source install with first-run initialization (requires Cargo):
Source install (requires Rust and Cargo):

```bash
curl -fsSL https://raw.githubusercontent.com/TerminallyLazy/Tree-Ring-Memory/main/install.sh | sh -s -- --project --init
curl -fsSL https://raw.githubusercontent.com/TerminallyLazy/Tree-Ring-Memory/main/install.sh | sh
```

Store the first project memory:
Expand All @@ -222,11 +224,13 @@ tree-ring tui

## Install Details

The installer builds the Rust CLI with `cargo`, installs `tree-ring`, then shows
one stable terminal onboarding screen with a branded terminal ring and the next
useful commands. For global installs, it also adds the install bin directory to your
shell profile when that directory is not already on `PATH`. It does not
initialize memory unless `--init` is passed.
With `--release latest`, the installer downloads the official platform archive,
downloads its published SHA-256, verifies it, and installs `tree-ring` without
requiring Rust. Without `--release`, it builds the Rust CLI with `cargo`. It then
shows one terminal onboarding screen with a branded terminal ring and useful
commands. For global installs, it can add the install bin directory to the shell
profile when that directory is not already on `PATH`. It does not initialize
memory unless `--init` is passed.

The installer command streams only the installer script into `sh`. It does not
put memory in a temporary location and it does not remove `.tree-ring`,
Expand All @@ -251,11 +255,12 @@ Useful installer options:

```bash
sh install.sh --help
sh install.sh --project --init
sh install.sh --project --init --release latest
sh install.sh --global --install-dir "$HOME/.local"
sh install.sh --no-animation # stable output; kept for explicit script usage
sh install.sh --no-path-update
sh install.sh --archive-url https://example/tree-ring-memory-0.14.0-darwin-arm64.tar.gz --archive-sha256 <sha256>
sh install.sh --release 0.15.0
sh install.sh --archive-url https://example/tree-ring-memory-0.15.0-darwin-arm64.tar.gz --archive-sha256 <sha256>
```

After install, rerun onboarding anytime:
Expand All @@ -267,8 +272,41 @@ tree-ring
```

By default, the installer uses `cargo install` from the Git repository or a
local `--source` checkout. Release builds can use `--archive-url` plus
`--archive-sha256` to install a prebuilt `tree-ring` binary archive.
local `--source` checkout. `--release latest` or `--release <version>` resolves
and verifies the matching official prebuilt archive. Advanced callers can still
use `--archive-url` plus `--archive-sha256` explicitly.

## Update Tree Ring Memory

Check the official release without changing files:

```bash
tree-ring update --check
```

After authorizing an update, update the active executable in its existing
project-local, direct-prefix, or Homebrew-managed scope:

```bash
tree-ring update
tree-ring --version
```

The updater verifies the official release archive and checksum and does not
install a second copy in a different prefix. After updating, return to each
project root and safely backfill its managed guidance:

```bash
tree-ring --root .tree-ring init
tree-ring --root .tree-ring integrations status --verbose
```

CLIs older than v0.15 do not contain `tree-ring update`. Upgrade those with the
same manager or install prefix first: Homebrew with `brew upgrade tree-ring`, a
project-local install with `install.sh --project --release latest`, or another
direct install with `install.sh --install-dir <existing-prefix> --release
latest`. Use `command -v tree-ring` and `which -a tree-ring` afterward to find
an older binary that may still shadow the updated executable.

Open the terminal console after a global install:

Expand Down
7 changes: 4 additions & 3 deletions crates/tree-ring-memory-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,12 @@ libc.workspace = true
ratatui.workspace = true
serde.workspace = true
serde_json.workspace = true
semver.workspace = true
sha2.workspace = true
tempfile.workspace = true
uuid.workspace = true
tree-ring-memory-core = { path = "../tree-ring-memory-core", version = "0.14.0" }
tree-ring-memory-sqlite = { path = "../tree-ring-memory-sqlite", version = "0.14.0" }
tree-ring-memory-core = { path = "../tree-ring-memory-core", version = "0.15.0" }
tree-ring-memory-sqlite = { path = "../tree-ring-memory-sqlite", version = "0.15.0" }

[dev-dependencies]
rusqlite.workspace = true
tempfile.workspace = true
124 changes: 124 additions & 0 deletions crates/tree-ring-memory-cli/src/agent_awareness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ const SKILL_QUALITY_GATES_HEADING: &str = "## Memory Quality Gates";
const SKILL_QUALITY_GATES_ANCHOR: &str = "## Ring Selection";
const SKILL_POLICY_HEADING: &str = "## Coordinated Write Policy";
const SKILL_POLICY_ANCHOR: &str = "## Agent-Mediated Updates";
const AGENT_RUNTIME_HEADING: &str = "## Local Runtime Bootstrap And Updates";
const AGENT_RUNTIME_ANCHOR: &str = "## Harness Bridges";
const SKILL_RUNTIME_HEADING: &str = "## Runtime Bootstrap And Updates";
const SKILL_RUNTIME_ANCHOR: &str = "## When To Recall";
const CLI_RUNTIME_HEADING: &str = "Runtime bootstrap and updates:";
const CLI_RUNTIME_ANCHOR: &str = "Core commands:";
const PREFLIGHT_HEADING: &str = "## Harness Preflight";
const PREFLIGHT_GUIDANCE: &str = r#"## Harness Preflight

Expand Down Expand Up @@ -49,10 +55,20 @@ Use memory deliberately:
- use seeds for future work and hypotheses
- forget, redact, or supersede stale or sensitive memory

Runtime bootstrap and updates:

- Resolve the real project root before initialization. Never initialize a plugin cache, package directory, home directory, or incidental working directory.
- Prefer `<project-root>/.tree-ring/bin/tree-ring` when present; otherwise use the active `tree-ring` on `PATH`.
- With existing user authorization for setup, install the verified project-local release from the project root with `curl -fsSL https://raw.githubusercontent.com/TerminallyLazy/Tree-Ring-Memory/main/install.sh | sh -s -- --project --init --release latest --no-animation`. Otherwise obtain permission before downloading or installing software.
- Use `tree-ring --root .tree-ring init` for a global CLI or `.tree-ring/bin/tree-ring --root .tree-ring init` for a project-local CLI. Verify that `memory.sqlite`, `AGENTS.md`, `SKILL.md`, and `CLI.md` are under the intended project.
- `tree-ring update --check` is read-only. Run `tree-ring update` only with update authorization; it preserves the active installation scope and verifies official release assets. Re-run project initialization afterward to backfill managed guidance.
- A pre-0.15 CLI must be upgraded with its existing package manager or install prefix. Check `command -v tree-ring` and `which -a tree-ring` so an old binary does not shadow the update.

Core commands:

```bash
tree-ring init
tree-ring update --check
tree-ring recall "project startup warnings"
tree-ring remember "Use project-scoped recall before risky changes." --event-type lesson --scope project
tree-ring evidence "Snapshot invalidation fixed stale unread chat state." --outcome promoted --evidence-ref evals/chat-state/run-042 --score 0.91
Expand Down Expand Up @@ -176,6 +192,27 @@ pub fn ensure_agent_awareness(root: &Path) -> Result<AgentAwarenessReport, Strin
CLI_QUALITY_GATES_ANCHOR,
),
)?;
maybe_backfill_generated_file(
&root.join("AGENTS.md"),
is_generated_agents_file,
AGENT_RUNTIME_HEADING,
AGENT_RUNTIME_ANCHOR,
extract_section(&agent_contract, AGENT_RUNTIME_HEADING, AGENT_RUNTIME_ANCHOR),
)?;
maybe_backfill_generated_file(
&root.join("SKILL.md"),
is_generated_skill_file,
SKILL_RUNTIME_HEADING,
SKILL_RUNTIME_ANCHOR,
extract_section(SKILL_TEMPLATE, SKILL_RUNTIME_HEADING, SKILL_RUNTIME_ANCHOR),
)?;
maybe_backfill_generated_file(
&root.join("CLI.md"),
is_generated_cli_file,
CLI_RUNTIME_HEADING,
CLI_RUNTIME_ANCHOR,
extract_section(CLI_REFERENCE, CLI_RUNTIME_HEADING, CLI_RUNTIME_ANCHOR),
)?;
maybe_backfill_generated_file(
&root.join("AGENTS.md"),
is_generated_agents_file,
Expand Down Expand Up @@ -355,6 +392,31 @@ tree-ring --root {root} integrations scan --source-root .
tree-ring --root {root} tui
```

## Local Runtime Bootstrap And Updates

This store belongs to the project that contains `{root}`. Do not run `init`
from a plugin cache, downloaded package directory, home directory, or unrelated
working directory. Prefer `{root}/bin/tree-ring` when it exists; otherwise use
the active `tree-ring` on `PATH`.

If the CLI is absent and the user's request already authorizes Tree Ring setup,
install the official verified project-local release from the real project root:

```bash
curl -fsSL https://raw.githubusercontent.com/TerminallyLazy/Tree-Ring-Memory/main/install.sh | sh -s -- --project --init --release latest --no-animation
```

Otherwise obtain permission before downloading or installing software. Run
`tree-ring --root {root} init` for a global CLI or `{root}/bin/tree-ring --root
{root} init` for a project-local CLI. Verify all generated files remain under
the intended root, then inspect `integrations status` with the same executable.

Use `tree-ring update --check` for a read-only release check. Run `tree-ring
update` only with update authorization; preserve the current package manager or
install prefix and do not create a shadowing second binary. Re-run `init` after
an update to backfill managed guidance without replacing custom files. A
pre-0.15 CLI must be upgraded through its existing manager or prefix first.

## Harness Bridges

Harness-native bridge files should point back to this directory instead of
Expand Down Expand Up @@ -635,6 +697,68 @@ mod tests {
}
}

#[test]
fn generated_guidance_bootstraps_and_updates_from_the_project_root() {
let dir = tempdir().unwrap();
let root = dir.path().join(".tree-ring");

ensure_agent_awareness(&root).unwrap();

for name in ["AGENTS.md", "SKILL.md", "CLI.md"] {
let content = fs::read_to_string(root.join(name)).unwrap();
assert!(
content.contains("Runtime Bootstrap And Updates")
|| content.contains("Runtime bootstrap and updates:")
);
assert!(content.contains("--project --init --release latest --no-animation"));
assert!(content.contains("tree-ring update --check"));
assert!(content.contains("project root"));
assert!(content.contains("shadow"));
}
}

#[test]
fn generated_backfills_runtime_guidance_into_recognized_stale_files() {
let dir = tempdir().unwrap();
let root = dir.path().join(".tree-ring");
fs::create_dir_all(&root).unwrap();
let canonical_agents = agent_contract(&root);

fs::write(
root.join("AGENTS.md"),
remove_managed_section(
&canonical_agents,
AGENT_RUNTIME_HEADING,
AGENT_RUNTIME_ANCHOR,
)
.unwrap(),
)
.unwrap();
fs::write(
root.join("CLI.md"),
remove_managed_section(CLI_REFERENCE, CLI_RUNTIME_HEADING, CLI_RUNTIME_ANCHOR).unwrap(),
)
.unwrap();
fs::write(
root.join("SKILL.md"),
remove_managed_section(SKILL_TEMPLATE, SKILL_RUNTIME_HEADING, SKILL_RUNTIME_ANCHOR)
.unwrap(),
)
.unwrap();

ensure_agent_awareness(&root).unwrap();

let agents = fs::read_to_string(root.join("AGENTS.md")).unwrap();
let cli = fs::read_to_string(root.join("CLI.md")).unwrap();
let skill = fs::read_to_string(root.join("SKILL.md")).unwrap();
assert_eq!(agents.matches(AGENT_RUNTIME_HEADING).count(), 1);
assert_eq!(cli.matches(CLI_RUNTIME_HEADING).count(), 1);
assert_eq!(skill.matches(SKILL_RUNTIME_HEADING).count(), 1);
assert!(agents.contains("--project --init --release latest"));
assert!(cli.contains("tree-ring update --check"));
assert!(skill.contains("which -a tree-ring"));
}

#[test]
fn generated_backfills_quality_gates_into_recognized_stale_generated_files() {
let dir = tempdir().unwrap();
Expand Down
Loading