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: