diff --git a/Cargo.lock b/Cargo.lock
index 193c03f..ad03715 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1690,7 +1690,7 @@ checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109"
[[package]]
name = "tree-ring-memory-cli"
-version = "0.15.1"
+version = "0.15.2"
dependencies = [
"chrono",
"clap",
@@ -1709,7 +1709,7 @@ dependencies = [
[[package]]
name = "tree-ring-memory-core"
-version = "0.15.1"
+version = "0.15.2"
dependencies = [
"chrono",
"libc",
@@ -1725,7 +1725,7 @@ dependencies = [
[[package]]
name = "tree-ring-memory-sqlite"
-version = "0.15.1"
+version = "0.15.2"
dependencies = [
"rusqlite",
"serde",
diff --git a/Cargo.toml b/Cargo.toml
index b66eabe..e3e6b04 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -7,7 +7,7 @@ members = [
resolver = "2"
[workspace.package]
-version = "0.15.1"
+version = "0.15.2"
edition = "2021"
license = "MIT"
authors = ["TerminallyLazy"]
diff --git a/README.md b/README.md
index 8b73908..9204288 100644
--- a/README.md
+++ b/README.md
@@ -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:
-- Launch release:
+- Launch release:
- Launch discussion:
- Rust-native CLI article:
- Feedback issue:
@@ -259,8 +259,8 @@ 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 --release 0.15.1
-sh install.sh --archive-url https://example/tree-ring-memory-0.15.1-darwin-arm64.tar.gz --archive-sha256
+sh install.sh --release 0.15.2
+sh install.sh --archive-url https://example/tree-ring-memory-0.15.2-darwin-arm64.tar.gz --archive-sha256
```
After install, rerun onboarding anytime:
diff --git a/crates/tree-ring-memory-cli/Cargo.toml b/crates/tree-ring-memory-cli/Cargo.toml
index f053371..3105496 100644
--- a/crates/tree-ring-memory-cli/Cargo.toml
+++ b/crates/tree-ring-memory-cli/Cargo.toml
@@ -26,8 +26,8 @@ semver.workspace = true
sha2.workspace = true
tempfile.workspace = true
uuid.workspace = true
-tree-ring-memory-core = { path = "../tree-ring-memory-core", version = "0.15.1" }
-tree-ring-memory-sqlite = { path = "../tree-ring-memory-sqlite", version = "0.15.1" }
+tree-ring-memory-core = { path = "../tree-ring-memory-core", version = "0.15.2" }
+tree-ring-memory-sqlite = { path = "../tree-ring-memory-sqlite", version = "0.15.2" }
[dev-dependencies]
rusqlite.workspace = true
diff --git a/crates/tree-ring-memory-cli/src/agent_awareness.rs b/crates/tree-ring-memory-cli/src/agent_awareness.rs
index 6b895c2..00f31e9 100644
--- a/crates/tree-ring-memory-cli/src/agent_awareness.rs
+++ b/crates/tree-ring-memory-cli/src/agent_awareness.rs
@@ -293,13 +293,28 @@ fn maybe_backfill_generated_file(
};
let existing = fs::read_to_string(path).map_err(|err| err.to_string())?;
- if !recognizer(&existing) || existing.contains(section_heading) {
+ if !recognizer(&existing) {
return Ok(());
}
- let Some(updated) = insert_section_before_anchor(&existing, section, anchor) else {
- return Ok(());
- };
+ let updated =
+ if let Some((start, end)) = managed_section_range(&existing, section_heading, anchor) {
+ let section = if existing.contains("\r\n") {
+ Cow::Owned(section.replace('\n', "\r\n"))
+ } else {
+ Cow::Borrowed(section)
+ };
+ let mut updated = String::with_capacity(existing.len() + section.len() - (end - start));
+ updated.push_str(&existing[..start]);
+ updated.push_str(§ion);
+ updated.push_str(&existing[end..]);
+ updated
+ } else {
+ let Some(updated) = insert_section_before_anchor(&existing, section, anchor) else {
+ return Ok(());
+ };
+ updated
+ };
if updated != existing {
fs::write(path, updated).map_err(|err| err.to_string())?;
}
@@ -726,6 +741,55 @@ mod tests {
}
}
+ #[test]
+ fn generated_init_refreshes_existing_managed_runtime_sections() {
+ let dir = tempdir().unwrap();
+ let root = dir.path().join(".tree-ring");
+ fs::create_dir_all(&root).unwrap();
+ let canonical_agents = agent_contract(&root);
+ let custom_note = "\nCustom project note: preserve me.\n";
+
+ for (name, canonical, heading, anchor) in [
+ (
+ "AGENTS.md",
+ canonical_agents.as_str(),
+ AGENT_RUNTIME_HEADING,
+ AGENT_RUNTIME_ANCHOR,
+ ),
+ (
+ "SKILL.md",
+ SKILL_TEMPLATE,
+ SKILL_RUNTIME_HEADING,
+ SKILL_RUNTIME_ANCHOR,
+ ),
+ (
+ "CLI.md",
+ CLI_REFERENCE,
+ CLI_RUNTIME_HEADING,
+ CLI_RUNTIME_ANCHOR,
+ ),
+ ] {
+ let (start, end) = managed_section_range(canonical, heading, anchor).unwrap();
+ let mut stale = String::new();
+ stale.push_str(&canonical[..start]);
+ stale.push_str(heading);
+ stale.push_str("\n\nLegacy installer: main/install.sh | sh\n\n");
+ stale.push_str(&canonical[end..]);
+ stale.push_str(custom_note);
+ fs::write(root.join(name), stale).unwrap();
+ }
+
+ 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("ef0d5eb8f09cbe2e4c3abe80ee9a98a56759c89ad4ddd103d6c68314cd653ade"));
+ assert!(!content.contains("main/install.sh | sh"));
+ assert!(content.ends_with(custom_note));
+ }
+ }
+
#[test]
fn generated_backfills_runtime_guidance_into_recognized_stale_files() {
let dir = tempdir().unwrap();
diff --git a/crates/tree-ring-memory-sqlite/Cargo.toml b/crates/tree-ring-memory-sqlite/Cargo.toml
index 1e93d5f..64911c9 100644
--- a/crates/tree-ring-memory-sqlite/Cargo.toml
+++ b/crates/tree-ring-memory-sqlite/Cargo.toml
@@ -16,7 +16,7 @@ rusqlite.workspace = true
serde.workspace = true
serde_json.workspace = true
sha2.workspace = true
-tree-ring-memory-core = { path = "../tree-ring-memory-core", version = "0.15.1" }
+tree-ring-memory-core = { path = "../tree-ring-memory-core", version = "0.15.2" }
uuid.workspace = true
[dev-dependencies]
diff --git a/docs/press-kit.md b/docs/press-kit.md
index a4dcc26..eb73ff7 100644
--- a/docs/press-kit.md
+++ b/docs/press-kit.md
@@ -23,10 +23,10 @@ DOX/Revolve adapters, framework discovery, and a terminal TUI.
- Category: AI agents, developer tools, local-first software, Rust CLI
- License: MIT
- Status: protocol-preview
-- Current version: 0.15.1
+- Current version: 0.15.2
- Website:
- Repository:
-- Launch release:
+- Launch release:
- Launch discussion:
- Homebrew tap:
- Feedback:
diff --git a/marketing/README.md b/marketing/README.md
index 7943726..eca106c 100644
--- a/marketing/README.md
+++ b/marketing/README.md
@@ -309,7 +309,7 @@ python3 marketing/scripts/build-campaign-cards.py
- Repository: `https://github.com/TerminallyLazy/Tree-Ring-Memory`
- Launch page: `https://terminallylazy.github.io/Tree-Ring-Memory/`
-- Launch release: `https://github.com/TerminallyLazy/Tree-Ring-Memory/releases/tag/v0.15.1`
+- Launch release: `https://github.com/TerminallyLazy/Tree-Ring-Memory/releases/tag/v0.15.2`
- Launch discussion: `https://github.com/TerminallyLazy/Tree-Ring-Memory/discussions/27`
- Homebrew tap: `https://github.com/TerminallyLazy/homebrew-tree-ring`
- Agent-Skills.md main repo listing: