diff --git a/.agents/plugins/marketplace.json b/.agents/plugins/marketplace.json new file mode 100644 index 0000000..ee64012 --- /dev/null +++ b/.agents/plugins/marketplace.json @@ -0,0 +1,20 @@ +{ + "name": "tree-ring-memory", + "interface": { + "displayName": "Tree Ring Memory" + }, + "plugins": [ + { + "name": "tree-ring-memory", + "source": { + "source": "local", + "path": "./plugins/tree-ring-memory" + }, + "policy": { + "installation": "AVAILABLE", + "authentication": "ON_INSTALL" + }, + "category": "Developer Tools" + } + ] +} diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json new file mode 100644 index 0000000..1a0698c --- /dev/null +++ b/.claude-plugin/marketplace.json @@ -0,0 +1,42 @@ +{ + "name": "tree-ring-memory", + "owner": { + "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.0", + "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+.", + "author": { + "name": "TerminallyLazy", + "url": "https://github.com/TerminallyLazy" + }, + "homepage": "https://terminallylazy.github.io/Tree-Ring-Memory/", + "repository": "https://github.com/TerminallyLazy/Tree-Ring-Memory", + "license": "MIT", + "category": "Workflow Orchestration", + "tags": [ + "agent-memory", + "harness-activation", + "multi-agent", + "local-first", + "privacy", + "recall", + "claude-code" + ], + "keywords": [ + "agent-memory", + "ai-memory", + "local-first", + "privacy", + "recall", + "sqlite" + ] + } + ] +} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 66c94b4..7a6e76c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,6 +13,9 @@ jobs: - name: Checkout uses: actions/checkout@v5 + - name: Plugin packages + run: python3 scripts/validate-plugin-packages.py + - name: Install Rust uses: dtolnay/rust-toolchain@stable with: diff --git a/README.md b/README.md index d8de998..0decf01 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,36 @@ same-host local filesystem with matching project-store identity. It does not claim safe SQLite sharing across hosts, NFS/network filesystems, or containers on different hosts. +### Install the agent guidance plugin (optional) + +The repository includes an instruction-only package for ChatGPT/Codex and +Claude Code under `plugins/tree-ring-memory/`. It adds the reviewed Tree Ring +workflow, DOX dry-run guidance, and installed-runtime certification commands; +it does not bundle the CLI, the full source certification script, or an MCP +server. + +Add the marketplace to Codex: + +```bash +codex plugin marketplace add TerminallyLazy/Tree-Ring-Memory +``` + +Then restart the ChatGPT desktop app and install Tree Ring Memory from the +Plugins Directory. The repo-local `.agents/plugins/marketplace.json` is also +available automatically when this repository is open in a supported Work or +Codex surface. + +Add and install the same package in Claude Code: + +```text +/plugin marketplace add TerminallyLazy/Tree-Ring-Memory +/plugin install tree-ring-memory@tree-ring-memory +``` + +The plugin still requires Tree Ring Memory CLI v0.14.0 or newer. See the +[plugin README](plugins/tree-ring-memory/README.md) for the platform manifests, +commands, DOX contract flow, and certification boundary. + ### Agent Zero uses its separate plugin Agent Zero is intentionally a two-part setup. `tree-ring init` creates the diff --git a/plugins/tree-ring-memory/.claude-plugin/plugin.json b/plugins/tree-ring-memory/.claude-plugin/plugin.json new file mode 100644 index 0000000..d6f50eb --- /dev/null +++ b/plugins/tree-ring-memory/.claude-plugin/plugin.json @@ -0,0 +1,26 @@ +{ + "name": "tree-ring-memory", + "displayName": "Tree Ring Memory", + "version": "0.3.0", + "description": "Local-first memory lifecycle and receipt-backed harness guidance for Claude Code using Tree Ring Memory v0.14+.", + "author": { + "name": "TerminallyLazy", + "url": "https://github.com/TerminallyLazy" + }, + "homepage": "https://terminallylazy.github.io/Tree-Ring-Memory/", + "repository": "https://github.com/TerminallyLazy/Tree-Ring-Memory", + "license": "MIT", + "keywords": [ + "claude-code", + "agent-memory", + "ai-memory", + "local-first", + "harness-activation", + "multi-agent", + "privacy", + "recall", + "sqlite", + "skills" + ], + "skills": "./skills/" +} diff --git a/plugins/tree-ring-memory/.codex-plugin/plugin.json b/plugins/tree-ring-memory/.codex-plugin/plugin.json new file mode 100644 index 0000000..34eb7f8 --- /dev/null +++ b/plugins/tree-ring-memory/.codex-plugin/plugin.json @@ -0,0 +1,48 @@ +{ + "name": "tree-ring-memory", + "version": "0.3.1", + "description": "Local-first memory lifecycle and receipt-backed harness guidance for coding agents using Tree Ring Memory v0.14+.", + "author": { + "name": "TerminallyLazy", + "url": "https://github.com/TerminallyLazy" + }, + "homepage": "https://github.com/TerminallyLazy/Tree-Ring-Memory", + "repository": "https://github.com/TerminallyLazy/Tree-Ring-Memory", + "license": "MIT", + "keywords": [ + "codex", + "memory", + "agent-memory", + "multi-agent", + "harness-activation", + "idempotency", + "local-first", + "recall", + "sqlite", + "skills" + ], + "skills": "./skills/", + "interface": { + "displayName": "Tree Ring Memory", + "shortDescription": "Local-first memory lifecycle guidance for Codex agents.", + "longDescription": "Tree Ring Memory gives coding agents a lifecycle-aware practice for project recall, durable decisions, receipt-backed harness readiness, same-host fan-out/fan-in, idempotent worker writes, coordinator-authorized shared publication, explicit forgetting, and privacy-safe memory capture using Tree Ring Memory v0.14 or newer.", + "developerName": "TerminallyLazy", + "category": "Developer Tools", + "capabilities": [ + "Read", + "Write", + "Interactive" + ], + "websiteURL": "https://terminallylazy.github.io/Tree-Ring-Memory/", + "privacyPolicyURL": "https://github.com/TerminallyLazy/Tree-Ring-Memory/blob/main/plugins/tree-ring-memory/PRIVACY.md", + "termsOfServiceURL": "https://github.com/TerminallyLazy/Tree-Ring-Memory/blob/main/plugins/tree-ring-memory/TERMS.md", + "defaultPrompt": [ + "Recall durable project context before changing release behavior.", + "Capture this validated lesson without storing a transcript.", + "Check Tree Ring harness readiness and explain any non-active state." + ], + "brandColor": "#2F7D5C", + "composerIcon": "./assets/tree-ring-memory-logo.png", + "logo": "./assets/tree-ring-memory-logo.png" + } +} diff --git a/plugins/tree-ring-memory/LICENSE b/plugins/tree-ring-memory/LICENSE new file mode 100644 index 0000000..14e7e5a --- /dev/null +++ b/plugins/tree-ring-memory/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 TerminallyLazy + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/plugins/tree-ring-memory/PRIVACY.md b/plugins/tree-ring-memory/PRIVACY.md new file mode 100644 index 0000000..5e67fbe --- /dev/null +++ b/plugins/tree-ring-memory/PRIVACY.md @@ -0,0 +1,24 @@ +# Tree Ring Memory Plugin Privacy Notice + +Effective August 23, 2026 + +The Tree Ring Memory plugin is an instruction package for AI coding agents. It +does not operate a hosted service, create a user account, collect analytics, +send telemetry, or include a remote MCP server. + +When an agent runs the separately installed Tree Ring Memory CLI, the CLI stores +the memory content the user chooses in a local SQLite database under the +configured Tree Ring root. The project does not receive that database or its +contents. Data leaves the local environment only when the user or another tool +explicitly exports, syncs, publishes, or otherwise transmits it. + +The plugin instructs agents to avoid transcripts, credentials, secrets, private +keys, raw chain-of-thought, and unnecessary sensitive personal data. It also +provides explicit redaction, deletion, supersession, audit, and consolidation +workflows. These safeguards do not replace the privacy and data-use terms of the +AI host, operating system, source-control provider, or any other tool the user +chooses to invoke. + +Support and privacy questions may be filed at +. +Do not include secrets or private memory content in a public issue. diff --git a/plugins/tree-ring-memory/README.md b/plugins/tree-ring-memory/README.md new file mode 100644 index 0000000..7aad89c --- /dev/null +++ b/plugins/tree-ring-memory/README.md @@ -0,0 +1,83 @@ +# Tree Ring Memory Agent Plugin + +This directory is the repository-distributed Tree Ring Memory plugin for +ChatGPT/Codex and Claude Code. It packages instruction files only; the local +Tree Ring Memory CLI remains the runtime and data owner. + +The Codex manifest is version `0.3.1`. The Claude Code manifest is version +`0.3.0`. Both target Tree Ring Memory CLI `0.14.0` or newer and share the same +reviewed wrapper skill. + +The package does not run a background service, scrape chats, install hooks, or +ship an MCP server. The active agent decides when a local, source-linked, +privacy-safe memory action is warranted. + +## Install Tree Ring Memory + +On macOS ARM64: + +```bash +brew tap TerminallyLazy/tree-ring +brew install tree-ring +tree-ring --version +``` + +For other platforms, use the +[canonical installation guide](https://github.com/TerminallyLazy/Tree-Ring-Memory#install). +The plugin must not install or upgrade the CLI, edit shell configuration, or +claim a memory action ran without explicit permission and observed output. + +## Install In ChatGPT And Codex + +Add this repository as a marketplace: + +```bash +codex plugin marketplace add TerminallyLazy/Tree-Ring-Memory +``` + +Restart the ChatGPT desktop app, open the Plugins Directory, select the Tree +Ring Memory marketplace, and install Tree Ring Memory. When the repository is +already open in Work mode or Codex, `.agents/plugins/marketplace.json` also +exposes the repo-scoped package. + +OpenAI ZIP submission remains a separate public-directory channel. Its +skills-only package intentionally includes the logo and composer icon but no +`interface.screenshots` field. + +## Install In Claude Code + +From Claude Code: + +```text +/plugin marketplace add TerminallyLazy/Tree-Ring-Memory +/plugin install tree-ring-memory@tree-ring-memory +``` + +The package adds the `tree-ring-memory` skill and these commands: + +- `/tree-ring-memory:tree-ring-recall` +- `/tree-ring-memory:tree-ring-capture` +- `/tree-ring-memory:tree-ring-audit` +- `/tree-ring-memory:tree-ring-status` +- `/tree-ring-memory:tree-ring-dox-sync` +- `/tree-ring-memory:tree-ring-certify` + +## DOX And Certification Boundaries + +The wrapper skill includes a DOX contract flow. It reads the applicable live +`AGENTS.md` chain, previews `tree-ring dox sync` before persistence, keeps +source contracts authoritative, and never rewrites them. + +Installed runtimes can produce bounded evidence with +`tree-ring integrations certify` and `tree-ring recall-quality`. The full +`scripts/certify-tree-ring.sh` release suite depends on the Rust workspace, +fixtures, installer, and build tools in a complete Tree Ring Memory source +checkout. It is intentionally not copied into this plugin. The TUI and plugin +may point to that command, but neither silently runs it nor turns its absence +into a false certification claim. + +## Security + +This plugin ships instructions and local assets only. It includes no remote MCP +server, webhooks, analytics, credentials, or networked runtime code. See +[PRIVACY.md](PRIVACY.md), [SECURITY.md](SECURITY.md), and [TERMS.md](TERMS.md). diff --git a/plugins/tree-ring-memory/SECURITY.md b/plugins/tree-ring-memory/SECURITY.md new file mode 100644 index 0000000..3e81a3f --- /dev/null +++ b/plugins/tree-ring-memory/SECURITY.md @@ -0,0 +1,30 @@ +# Security Policy + +## Supported Versions + +The `main` branch is the supported version of this Codex plugin wrapper. + +The Tree Ring Memory framework and CLI are maintained in the canonical +repository: + + + +## Reporting A Vulnerability + +Open a private security advisory on GitHub when available, or open a public +issue with sensitive details removed: + + + +Do not include secrets, tokens, private memory contents, or personal data in a +public issue. + +## Data Handling + +This wrapper plugin contains guidance files only. It does not run a background +service, include remote MCP servers, collect telemetry, or store credentials. + +Tree Ring Memory is designed for explicit agent-mediated memory actions. Store +only concise decisions, lessons, warnings, and evidence references that are +useful, source-linked, and privacy-safe. Do not store raw transcripts, secrets, +private keys, tokens, or raw chain-of-thought. diff --git a/plugins/tree-ring-memory/TERMS.md b/plugins/tree-ring-memory/TERMS.md new file mode 100644 index 0000000..63add90 --- /dev/null +++ b/plugins/tree-ring-memory/TERMS.md @@ -0,0 +1,20 @@ +# Tree Ring Memory Plugin Terms of Use + +Effective August 23, 2026 + +The Tree Ring Memory plugin is open-source software distributed under the MIT +License. By using it, you agree to the license and these operational terms. + +The plugin provides agent instructions only. It is not a hosted memory service, +backup service, access-control system, medical or legal record system, or +guarantee that an AI host will follow every instruction. The user is responsible +for choosing what to store, maintaining backups, controlling local filesystem +access, reviewing agent actions, and complying with applicable policies and +law. + +Tree Ring Memory is provided without warranty, including warranties of fitness, +availability, accuracy, non-infringement, or data durability, to the maximum +extent permitted by law. The limitations in the included MIT License apply. + +Questions may be filed at +. diff --git a/plugins/tree-ring-memory/assets/tree-ring-memory-logo.png b/plugins/tree-ring-memory/assets/tree-ring-memory-logo.png new file mode 100644 index 0000000..530360c Binary files /dev/null and b/plugins/tree-ring-memory/assets/tree-ring-memory-logo.png differ diff --git a/plugins/tree-ring-memory/commands/tree-ring-audit.md b/plugins/tree-ring-memory/commands/tree-ring-audit.md new file mode 100644 index 0000000..7fb3b61 --- /dev/null +++ b/plugins/tree-ring-memory/commands/tree-ring-audit.md @@ -0,0 +1,65 @@ +--- +description: Audit consolidate or forget stale sensitive or superseded Tree Ring Memory entries +argument-hint: "[audit focus]" +allowed-tools: ["Bash"] +--- + +# Tree Ring Audit + +Audit memory when work is closing, when privacy may matter, or when older +entries may be stale. + +Read project-local `.tree-ring/SKILL.md` and `.tree-ring/CLI.md` first when +present. Confirm `tree-ring --version` reports 0.14.0 or newer. If the runtime +is missing or older, stop and explain the limitation; do not install, upgrade, +or invent results without explicit user permission. + +Before any current command other than `policy status` or `policy audit` opens +an existing pre-v0.13 store, stop every Tree Ring process, checkpoint and back +up the complete store, and upgrade every CLI, plugin, and bundled worker. All +mixed-version operation is unsupported. + +These policy preflight commands never create or migrate a store: + +```bash +tree-ring policy status +tree-ring policy audit --limit 100 +``` + +After the verified schema-v3 upgrade, start with non-mutating inspection: + +```bash +tree-ring audit --audit-type sensitive +tree-ring consolidate --period-type manual --dry-run +tree-ring maintain +``` + +If the user names a focus, use it to narrow recall before changing memory: + +```bash +tree-ring recall "$ARGUMENTS" +``` + +Use explicit forget operations only when justified: + +```bash +tree-ring forget mem_example --mode redact --reason "remove sensitive detail" +tree-ring forget mem_example --mode delete --reason "should not be retained" +``` + +The CLI forget modes are `redact` and `delete`. For an explicit supersession, +use the TUI's `/supersede ` lifecycle action. Clarify the exact memory +identifier and mutation before running any lifecycle write. + +In Coordinated mode, forget/redact, supersede, persisted consolidation, and +applied maintenance such as `--repair-fts` require +`TREE_RING_COORDINATOR_TOKEN` in the coordinator process environment. Never put +the capability value in a prompt, CLI argument, memory, log, source reference, +or committed file. `policy status`, `policy audit`, ordinary audit, +consolidation dry-run, and plain `maintain` do not change memory content on an +already-upgraded schema-v3 store. Only the two policy commands are guaranteed +not to create or migrate a store. + +Do not delete, redact, or supersede memory without a clear reason. The +coordinator policy is not a read ACL, and its shared-root support is bounded to +cooperative processes on one host using a local filesystem. diff --git a/plugins/tree-ring-memory/commands/tree-ring-capture.md b/plugins/tree-ring-memory/commands/tree-ring-capture.md new file mode 100644 index 0000000..759d776 --- /dev/null +++ b/plugins/tree-ring-memory/commands/tree-ring-capture.md @@ -0,0 +1,62 @@ +--- +description: Capture a concise validated lesson decision warning or preference in Tree Ring Memory +argument-hint: "" +allowed-tools: ["Bash"] +--- + +# Tree Ring Capture + +Capture only durable, useful memory. Do not store transcripts, secrets, +credentials, raw chain-of-thought, or unverified claims as truth. + +Read project-local `.tree-ring/SKILL.md` and `.tree-ring/CLI.md` first when +present. Confirm `tree-ring --version` reports 0.14.0 or newer. If the runtime +is missing or older, stop and explain the limitation; do not install, upgrade, +or invent a stored memory without explicit user permission. + +For a single agent or a store in Open mode, use the user's argument as the +memory summary: + +```bash +tree-ring remember "$ARGUMENTS" \ + --event-type lesson \ + --scope project +``` + +For an ordinary worker in Coordinated mode, use agent scope with the +server/task-derived identity and stable retry metadata: + +```bash +tree-ring remember "$ARGUMENTS" \ + --event-type lesson \ + --scope agent \ + --agent-profile "$TREE_RING_AGENT_PROFILE" \ + --workflow-id "$TREE_RING_WORKFLOW_ID" \ + --session-id "$TREE_RING_SESSION_ID" \ + --operation-id "" \ + --source-ref "" +``` + +Do not invent identity values. Reuse the same session and operation IDs only +for an exact retry; conflicting reuse fails closed. Keep +`TREE_RING_COORDINATOR_TOKEN` unset in ordinary worker environments. + +Adjust `--event-type`, scope, project, identity, source, and tags to match the +actual memory: + +- `decision` for selected architecture, release, storage, or policy choices +- `lesson` for validated work patterns +- `warning` for failures and regressions to avoid +- `user_preference` for durable user preferences +- `hypothesis` for future work that should be revisited as a seed + +If the memory comes from a run, test, evaluation, incident, PR, or checkpoint, +prefer `tree-ring evidence` with an `--evidence-ref` and outcome. + +In Coordinated mode, project/shared writes, `tree-ring evidence`, heartwood, +and lifecycle mutations require the one-time coordinator capability already +present only in the coordinator process environment. Never put its value in the +prompt, a CLI argument, memory, logs, source references, or committed files. + +The shared-root concurrency contract covers cooperative processes on one host +and a local filesystem. Identity and scope are routing fields, not read ACLs. diff --git a/plugins/tree-ring-memory/commands/tree-ring-certify.md b/plugins/tree-ring-memory/commands/tree-ring-certify.md new file mode 100644 index 0000000..d58fa73 --- /dev/null +++ b/plugins/tree-ring-memory/commands/tree-ring-certify.md @@ -0,0 +1,33 @@ +--- +description: Generate Tree Ring harness or recall-quality evidence without confusing it with the full framework release suite +argument-hint: "[harness|quality] [project root]" +allowed-tools: ["Bash", "Read"] +--- + +# Tree Ring Certify + +Read project-local `.tree-ring/SKILL.md` and `.tree-ring/CLI.md` when present, +then confirm `tree-ring --version` reports 0.14.0 or newer. If the runtime is +missing or older, explain the limitation and do not install or upgrade it, +edit shell configuration, or invent certification results. + +For an installed runtime, choose the requested self-contained evidence path: + +```bash +tree-ring integrations certify --source-root +tree-ring recall-quality --source-root +``` + +Default to harness certification and the current project root. Report the +observed pass/fail/skip counts, evidence directory, and any next steps. These +commands write evidence under `target/tree-ring-certification/`, but they do not +activate a harness or prove that an agent used recalled context; check +receipt-backed integration status separately. + +The full `sh scripts/certify-tree-ring.sh` release suite is repository-only. +Run it only when the current directory is a canonical Tree Ring Memory source +checkout containing that script, the Rust workspace, `install.sh`, fixtures, +and build tooling. Never copy or download the script into another project and +never represent the installed CLI checks as full framework release +certification. The TUI's `/evidence refresh` action only displays that external +command; it does not execute the suite. diff --git a/plugins/tree-ring-memory/commands/tree-ring-dox-sync.md b/plugins/tree-ring-memory/commands/tree-ring-dox-sync.md new file mode 100644 index 0000000..865d42d --- /dev/null +++ b/plugins/tree-ring-memory/commands/tree-ring-dox-sync.md @@ -0,0 +1,35 @@ +--- +description: Preview and synchronize DOX-style AGENTS.md guidance as source-linked Tree Ring memory +argument-hint: "[project root or AGENTS.md path]" +allowed-tools: ["Bash", "Read", "Grep", "Glob"] +--- + +# Tree Ring DOX Sync + +Use the argument as the DOX source root or single `AGENTS.md` path. Default to +the current project root when no argument is supplied. + +1. Read the applicable `AGENTS.md` chain from the project root to the working + directory. Current source contracts are authoritative; a memory summary + never overrides them. +2. Read project-local `.tree-ring/SKILL.md` and `.tree-ring/CLI.md` when present, + then confirm `tree-ring --version` reports 0.14.0 or newer. If the runtime is + missing or older, explain the limitation and do not install or upgrade it, + edit shell configuration, or invent adapter results. +3. Preview without writing: + + ```bash + tree-ring dox sync --source-root "${ARGUMENTS:-.}" --dry-run + ``` + +4. Inspect the proposed summaries and source references. Reject raw contract + copies, secrets, low-value duplication, or output that weakens a child + contract. +5. Persist only when the user requested synchronization and the preview is + concise and source-linked. Run the same command without `--dry-run`. In a + Coordinated store, persistence requires `TREE_RING_COORDINATOR_TOKEN` in the + authorized coordinator process; dry-run discovery does not. + +The adapter must not rewrite root or child `AGENTS.md` files. Re-read the live +contract chain before editing files and repeat the dry run after contract +changes. diff --git a/plugins/tree-ring-memory/commands/tree-ring-recall.md b/plugins/tree-ring-memory/commands/tree-ring-recall.md new file mode 100644 index 0000000..2eae9c6 --- /dev/null +++ b/plugins/tree-ring-memory/commands/tree-ring-recall.md @@ -0,0 +1,48 @@ +--- +description: Recall durable Tree Ring Memory context before starting or resuming work +argument-hint: "[focused query]" +allowed-tools: ["Bash", "Read", "Grep", "Glob"] +--- + +# Tree Ring Recall + +Recall useful project memory before acting on context-dependent work. + +1. Check for project-local guidance first: + + ```bash + test -f .tree-ring/SKILL.md && sed -n '1,520p' .tree-ring/SKILL.md + test -f .tree-ring/CLI.md && sed -n '1,520p' .tree-ring/CLI.md + ``` + + Confirm `tree-ring --version` reports 0.14.0 or newer. If the runtime is + missing or older, explain the limitation and do not fabricate recall or + install software without explicit user permission. + +2. Use the user's argument as the focused recall query when present: + + ```bash + tree-ring recall "$ARGUMENTS" + ``` + +3. If no argument is provided, choose a narrow query from the current task and + include project scope when known. + +4. In a fan-out worker, filter recall with its agent profile plus the shared + workflow and current session. At coordinator fan-in, omit only the + agent-profile filter deliberately so all worker results remain visible: + + ```bash + env -u TREE_RING_AGENT_PROFILE tree-ring recall "$ARGUMENTS" \ + --workflow-id "$TREE_RING_WORKFLOW_ID" \ + --session-id "$TREE_RING_SESSION_ID" \ + --scope agent + ``` + +5. Treat recall as context, not authority. Prefer source-linked, + high-confidence, non-superseded entries and verify drift-prone facts before + relying on them. + +Identity and scope partition and route local memory; they are not read ACLs. +The supported shared-root boundary is cooperative processes on one host and a +local filesystem, not cross-host or network-filesystem coordination. diff --git a/plugins/tree-ring-memory/commands/tree-ring-status.md b/plugins/tree-ring-memory/commands/tree-ring-status.md new file mode 100644 index 0000000..4e25308 --- /dev/null +++ b/plugins/tree-ring-memory/commands/tree-ring-status.md @@ -0,0 +1,34 @@ +--- +description: Check receipt-backed Tree Ring harness readiness without claiming configuration is activation +allowed-tools: ["Bash", "Read"] +--- + +# Tree Ring Status + +Read project-local `.tree-ring/SKILL.md` and `.tree-ring/CLI.md` when present, +then confirm the local runtime is Tree Ring Memory 0.14.0 or newer: + +```bash +tree-ring --version +``` + +If the runtime is missing or older, explain the limitation. Do not install or +upgrade software, edit shell configuration, or invent a status without the +user's explicit permission. + +Inspect receipt-backed readiness without changing it: + +```bash +tree-ring integrations status --json --verbose +``` + +Report the exact harness `state`, `capability`, and `next_step`. A bridge, +marker, generated skill, passive binding, or successful `init` is not activation +proof. Only a fresh matching receipt from a new session's scoped recall and safe +context injection can produce `active`. + +Treat `configured-awaiting-proof`, `active-isolated`, `needs-trust`, +`needs-project-mount`, `needs-plugin`, `needs-user-review`, `unsupported`, and +`failed` as non-active outcomes. Do not modify global trust, manufacture a +receipt, hand-author an Agent Zero capability descriptor, or replace a contested +bridge while checking status. diff --git a/plugins/tree-ring-memory/skills/tree-ring-memory/SKILL.md b/plugins/tree-ring-memory/skills/tree-ring-memory/SKILL.md new file mode 100644 index 0000000..f12d071 --- /dev/null +++ b/plugins/tree-ring-memory/skills/tree-ring-memory/SKILL.md @@ -0,0 +1,495 @@ +--- +name: tree-ring-memory +description: Guides AI agents in using Tree Ring Memory for durable recall, project decisions, user preferences, warnings, future seeds, privacy-safe memory capture, and lifecycle-aware forgetting. +version: 0.14.0 +license: MIT +tags: ["memory", "agents", "recall", "privacy", "projects", "dox", "revolve", "skills", "cli"] +triggers: + - "remember this" + - "recall what we decided" + - "what did we learn" + - "tree ring memory" + - "consolidate memory" + - "forget this" + - "project memory" + - "sync DOX" + - "sync Revolve" + - "evidence loop" + - "multi-agent memory" +--- + +# Tree Ring Memory + +Use Tree Ring Memory as a lifecycle-aware memory layer, not as a transcript dump. + +Tree Ring Memory preserves meaningful agent learning like tree rings: + +- fresh work stays detailed +- older learning compresses into stable rings +- important warnings remain visible as scars +- durable truths become heartwood +- speculative future work stays as seeds +- sensitive data is blocked, redacted, or kept out by default + +## Runtime Preflight + +Before running a Tree Ring command: + +1. Read project-local `.tree-ring/SKILL.md` and `.tree-ring/CLI.md` when they + exist. They describe the configured root and exact installed commands. +2. Confirm that the local runtime is available: + + ```bash + tree-ring --version + ``` + +3. This package targets Tree Ring Memory CLI 0.14.0 or newer. If the command is + missing or older, do not invent results, edit shell configuration, or install + or upgrade software without the user's explicit permission. Explain the + limitation and point to the canonical install guide: + + +If the current host cannot execute a local shell or access project files, use +this skill only as memory-lifecycle guidance. Do not claim that recall, capture, +audit, activation, or forgetting occurred unless the corresponding command ran +and its result was observed. + +## Agent Operating Loop + +Use this sequence for meaningful project work: + +1. Resolve the project root and read its local Tree Ring contract when present. +2. Run the runtime preflight, then recall narrowly scoped, source-linked memory + before making a material decision or repeating a failure-prone workflow. +3. Treat recalled memory as context, not authority. Recheck facts that may have + changed and defer to current source files, tests, policies, and user input. +4. Do the work. Do not write memory merely because a session is active. +5. At a natural checkpoint or closeout, capture only durable decisions, + corrections, validated lessons, warnings, or future seeds. Never store raw + transcripts, secrets, or sensitive data. +6. Observe the command result and report the actual outcome. A proposed memory, + dry run, bridge file, or generated marker is not proof that a durable write, + sync, activation, correction, or deletion occurred. + +In a Coordinated store, do not attempt persistent writes without the required +coordinator capability. If the capability is unavailable, provide a concise +candidate memory for an authorized coordinator instead of claiming it was +stored. + +## When To Recall + +Recall memory before: + +- starting or resuming a project +- changing architecture, storage, security, privacy, or release behavior +- repeating a workflow where prior failures may matter +- responding to a user correction +- making a decision that depends on previous preferences or constraints +- editing files in a repo that has a Tree Ring Memory or `AGENTS.md` contract +- closing out meaningful work and deciding what should be remembered + +Use narrow queries with project scope when possible. Prefer source-linked, high-confidence, non-superseded results. + +## When To Remember + +Store a memory when the information is likely to help future work: + +- the user states a durable preference +- the user corrects the agent +- a decision is made and should survive the current session +- an implementation lesson is validated by tests or production behavior +- a failed approach should not be repeated +- a security, privacy, release, or data-loss warning appears +- a useful project convention is discovered +- a future idea should be revisited later + +Keep memory concise. Store the lesson, decision, or warning, not the full conversation. + +Use `tree-ring evidence` instead of plain `remember` when the lesson comes from +an evaluation, checkpoint, experiment, branch, incident, or reviewed run +artifact. + +Use source adapters when project artifacts already contain structured guidance +or evaluated outcomes: + +```bash +tree-ring dox sync --source-root . --dry-run +tree-ring revolve sync --source-root revolve --dry-run +tree-ring integrations scan --source-root . +``` + +Run adapter commands with `--dry-run` first. Sync only concise, source-linked +summaries; never treat imported memory as more authoritative than the source +`AGENTS.md`, Revolve record, evaluation, PR, issue, or test artifact. +In a Coordinated store, persisting an adapter result requires the coordinator +capability; dry-run discovery does not. + +Use the exact CLI commands exposed by the local install: + +```bash +tree-ring --help +tree-ring dox sync --help +tree-ring revolve sync --help +tree-ring evidence --help +``` + +If the project was initialized with a project-local binary, prefer the generated +`.tree-ring/CLI.md` reference and include `--root .tree-ring` when needed. + +If this skill was loaded through a harness-native bridge file, treat that bridge +as a pointer only. Read the project-local `.tree-ring/SKILL.md` and +`.tree-ring/CLI.md` when present so commands match the installed project root. +Do not assume a global Tree Ring setup applies to the current repo unless the +user explicitly configured it. + +## DOX Contract Flow + +When a project uses DOX-style `AGENTS.md` contracts: + +1. Read the applicable contract chain from the project root down to the working + directory before editing files. More specific child contracts may refine the + parent contract. +2. Treat those current source files as authoritative. A recalled DOX summary is + only a navigation and continuity aid; it never overrides the live contract. +3. Preview the adapter output first with + `tree-ring dox sync --source-root --dry-run` and inspect every summary + and source reference. +4. Persist only concise, useful summaries. In a Coordinated store, persistence + requires coordinator authority; dry-run discovery does not. +5. Never use the adapter to rewrite a root or child `AGENTS.md`, copy whole + contract trees into memory, or weaken child instructions. Re-run the dry run + after a source contract changes and re-read the chain before the next edit. + +## Harness Activation + +For a new project, begin with the safe, project-local default: + +```bash +tree-ring init +tree-ring integrations status +``` + +Do not ask the user to copy a bridge or run `integrations link` for ordinary +setup. `init` configures only safe project-local adapter material by creating +absent final bridge and manifest paths. It never replaces or removes an existing +entry, including during deactivation; contested entries stay untouched and +report `needs-user-review`. A bridge, marker, generated skill, or successful +`init` is not activation proof: `active` requires a fresh, matching receipt from +a new session's scoped recall and safe context injection. +Treat `configured-awaiting-proof`, `active-isolated`, `needs-trust`, +`needs-project-mount`, `needs-plugin`, `needs-user-review`, `unsupported`, +and `failed` as their exact non-active outcomes. Never say Hermes or another +unverified runtime is active. + +If publication durability becomes indeterminate, do not delete or rewrite the +published path. Preserve disk material, keep changed harnesses marked +`needs-user-review` in the returned in-memory manifest, and leave any activation +manifest already published on disk intact for explicit reconciliation. + +Pi trust is the user's decision: report `needs-trust` rather than changing +global trust. Agent Zero is separate: `tree-ring init` writes only Tree Ring's +passive Agent Zero binding with `needs-plugin`. The user installs/enables the +compatible `tree_ring_memory` plugin and selects the mounted project; the plugin +then owns its absolute, non-project `activation-capability.json` descriptor and +passes it internally. Only descriptor-scoped plugin status can derive +`configured-awaiting-proof`, and only its new-session preflight receipt can +make the runtime `active`. + +Never create a generic marker, copy or hand-author that descriptor, set its +internal transport, modify Agent Zero core, or call a different plugin store +shared. A missing, invalid, disabled, or release-incompatible descriptor stays +`needs-plugin`; a different reachable store is `active-isolated`; an +unavailable root is `needs-project-mount`. A passive binding, source checkout, +or stale bundled CLI is not installed capability. + +Receipts prove a privacy-safe preflight check, not durable memory creation or a +security boundary. They exclude raw prompts, recalled content, secrets, +sensitive values, paths, and coordinator capabilities. Shared-store claims are +limited to same-host local-filesystem processes whose receipts match the +canonical project `store_id`; they do not apply across hosts or network +filesystems. For diagnostics use `tree-ring integrations status --verbose`; +for advanced controlled work use `integrations activate --harness +--dry-run`, `integrations certify`, or `integrations deactivate --harness +`. + +## Certification Boundary + +For an installed Tree Ring runtime, use the self-contained CLI evidence paths: + +```bash +tree-ring integrations certify --source-root . +tree-ring recall-quality --source-root . +``` + +Harness certification is non-mutating and writes JSON/Markdown evidence under +`target/tree-ring-certification/`; it does not activate a harness or prove that +an agent used recalled context. Keep receipt-backed status as a separate gate. + +`sh scripts/certify-tree-ring.sh` is the full framework release suite. Run it +only from a canonical Tree Ring Memory source checkout where that file, the Rust +workspace, `install.sh`, fixtures, and build tooling are all present. Do not +copy it into another project, download it automatically, or claim full release +certification from the smaller installed-CLI checks. In the TUI, `/evidence +refresh` only displays this external source-checkout command; it does not run +certification. If the script is absent, report that boundary and use the +self-contained CLI commands above when they fit the user's request. + +Evidence outcome mapping: + +- `promoted`: durable heartwood from supported evidence +- `rejected`: scar for reusable failed or rolled-back approaches +- `deferred`: seed for promising unresolved options +- `observed`: outer-ring evaluation result + +## Memory Quality Gates + +Use these gates before relying on or writing memory. + +Recall gates: + +- Before substantial project work, recall project constraints, scars, user preferences, and unresolved seeds. +- Before risky changes, recall warnings and evidence-linked prior failures. +- Before repeating a workflow, recall prior errors and accepted procedures. +- Before closeout, recall recent decisions so memory updates do not contradict already-stored lessons. + +Trust gates: + +- Prefer source-linked, non-superseded, high-confidence memories. +- Treat heartwood as durable only when source evidence or user confirmation supports it. +- Re-read source files, tests, explicit user instructions, DOX contracts, or Revolve evidence when memory conflicts with current sources. +- Do not treat sensitive or hidden-by-default memory as ordinary recall context. + +Write gates: + +- Remember only durable decisions, validated lessons, reusable warnings, corrections, future seeds, and evidence-backed outcomes. +- Reject transient planning chatter, duplicate wording, tool noise, and unsupported claims. +- Require evidence refs for promoted or rejected evaluated outcomes. +- Require user confirmation before creating or promoting broad cross-project heartwood. + +## Ring Selection + +Use these rings: + +- `cambium`: active or recent task context +- `outer`: recent decisions and task lessons +- `inner`: older compressed project knowledge +- `heartwood`: durable, high-confidence truths and user preferences +- `scar`: important negative memory, failures, regressions, rejected approaches, and warnings +- `seed`: unresolved ideas, hypotheses, follow-ups, and future work + +Do not promote to `heartwood` from weak evidence. Prefer `outer` or `seed` unless the user confirms durability or the evidence is strong. + +## Event Types + +Prefer specific event types: + +- `user_preference` +- `decision` +- `lesson` +- `warning` +- `correction` +- `file_change` +- `tool_result` +- `summary` +- `hypothesis` + +If a host integration has stricter event type names, use the closest local equivalent. + +## What Not To Store + +Do not store: + +- secrets +- credentials +- tokens +- private keys +- raw chain-of-thought +- temporary scratchpad notes +- unverified claims as durable truth +- private health, financial, legal, or personal identifier details without explicit user instruction +- copyrighted source text beyond short allowed snippets + +If a useful memory contains sensitive material, store a redacted summary with enough context to be useful. + +## Source And Scope + +Set project and scope deliberately: + +- use project scope for repo-specific rules, decisions, warnings, and lessons +- use agent scope for agent-partitioned behavior and always set `agent_profile` +- use workflow scope for one coordinated fan-out/fan-in and always set `workflow_id` +- use session scope for one execution attempt and always set `session_id` +- use global scope only for durable user preferences or cross-project guidance +- include source references such as file paths, issue ids, PR ids, run ids, or docs paths +- use `tree-ring evidence ... --evidence-ref ` for evaluated outcomes +- use `tree-ring dox sync` for concise `AGENTS.md` summaries +- use `tree-ring revolve sync` for promoted, rejected, deferred, or observed evaluation records +- use `tree-ring integrations scan` before configuring a new agent harness + +Memory does not replace source documents. If a repo has `AGENTS.md`, project docs, tests, architectural records, or host-specific instruction files, read those sources directly and treat them as authoritative. + +When DOX or Revolve source records change, re-run the matching sync adapter with +`--dry-run`, inspect the generated memories, then run the write command only +when the summaries are useful and source-linked. + +## Multi-Agent Coordination + +For workers sharing one local Tree Ring root, give every write explicit +coordination metadata: + +```bash +tree-ring --root .tree-ring remember "Worker validated the storage boundary." \ + --event-type lesson \ + --scope agent \ + --project example-service \ + --agent-profile worker-storage \ + --workflow-id release-readiness \ + --session-id attempt-1 \ + --operation-id validate-storage-v1 \ + --source-ref runs/release-readiness/worker-storage.json +``` + +Use a unique `agent_profile` per worker, one shared `workflow_id` for the +fan-out/fan-in, one `session_id` for each genuine execution attempt, and a stable +unique `operation_id` for each logical write. An exact retry reuses both the +original session ID and operation ID; changing only the session is a conflicting +reuse. Start a new session and use new operation IDs only for a genuinely new +attempt. Exact retries with the same operation metadata and payload return the +original memory. Reusing that operation key for a different payload fails +closed. Replacing a stored memory keeps its old operation namespace claimed. +Redaction also tombstones the memory ID; only an explicit hard delete releases +those claims. + +At fan-in, recall the shared workflow and session without an agent-profile +filter, inspect the source refs, then write a source-linked workflow or project +summary: + +```bash +tree-ring --root .tree-ring recall "release readiness" \ + --project example-service \ + --workflow-id release-readiness \ + --session-id attempt-1 \ + --scope agent +``` + +`TREE_RING_AGENT_PROFILE`, `TREE_RING_WORKFLOW_ID`, and +`TREE_RING_SESSION_ID` provide the same defaults as their CLI flags. Do not +leave an agent-profile environment filter set when the coordinator intends to +recall every worker. + +This shared-root pattern is for concurrent processes on one host using a local +filesystem. It is not a distributed lock service and does not claim safe +cross-host or NFS operation. Scope and identity fields remain routing metadata, +not a read ACL; a same-user coordinator can recall across profiles. Use +per-host stores plus an explicit, evidence-preserving fan-in process when work +spans hosts. + +## Coordinated Write Policy + +Stores default to backward-compatible Open mode. For a shared root where only a +designated coordinator should publish or mutate shared memory, enable the +optional Coordinated policy: + +```bash +tree-ring --root .tree-ring policy enable --coordinator release-coordinator +export TREE_RING_COORDINATOR_TOKEN='' +tree-ring --root .tree-ring policy status +tree-ring --root .tree-ring policy audit --limit 100 +``` + +Enable prints the capability once. Put it only in +`TREE_RING_COORDINATOR_TOKEN`; never pass it as a CLI flag or place it in a +memory, log, source ref, transcript, or committed file. Tree Ring stores only a +hash. `policy status` and `policy audit` are read-only and do not reveal the +capability. Inject it only into coordinator processes, and launch every ordinary +worker with `TREE_RING_COORDINATOR_TOKEN` unset so fan-out does not inherit +coordinator authority. + +In Coordinated mode, an ordinary worker may only create non-heartwood +`scope=agent` memory whose `agent_profile` matches its write context. Supply the +same identity with `--agent-profile ` or +`TREE_RING_AGENT_PROFILE=`. A coordinator capability is required for: + +- project, global, workflow, session, or other shared/non-agent writes +- heartwood creation or promotion +- JSONL import and persisted DOX/Revolve sync +- persisted consolidation +- ring changes and supersede/delete/redact lifecycle operations +- maintenance with apply or repair flags + +Recall, export, policy status/audit, adapter dry-runs, consolidation dry-runs, +and report-only maintenance remain read-only. In the TUI, start with +`--agent-profile ` (or `TREE_RING_AGENT_PROFILE`) so `/remember` +defaults to agent scope. TUI promote/scar/seed, supersede, forget/redact, and +persisted consolidation actions require `TREE_RING_COORDINATOR_TOKEN`. + +Rotate the capability while the current one is exported, then immediately +replace the environment value with the newly printed capability: + +```bash +tree-ring --root .tree-ring policy rotate --coordinator release-coordinator-next +export TREE_RING_COORDINATOR_TOKEN='' +tree-ring --root .tree-ring policy disable +unset TREE_RING_COORDINATOR_TOKEN +``` + +Rotation invalidates the old capability. Disabling returns the store to Open +mode and also requires the current capability. + +This is operational write authorization enforced by official Rust/CLI store +paths. It is not a read ACL, an operating-system security boundary, or +protection from an adversary who controls the local database files or process +environment. + +Before opening an existing store with v0.13/schema v3, stop every Tree Ring +process, checkpoint and back up the database, and upgrade every CLI, plugin, and +bundled worker. Do not reopen the upgraded root with v0.12: schema v3 fences +memory inserts, updates, and deletes from old writers, and all mixed-version +operation is unsupported. Roll back only by stopping all processes and +restoring the pre-upgrade backup. + +## Agent-Mediated Updates + +Tree Ring Memory does not autonomously scrape chats or write durable memory in +the background. The active agent is responsible for deciding when a Tree Ring +command is warranted, then calling the CLI deliberately. + +Use bridge files only to discover Tree Ring and its command reference: + +- project-level bridges should point to `.tree-ring/SKILL.md` and + `.tree-ring/CLI.md` +- global bridges should be treated as opt-in user configuration +- TUI event-stream pulses are display signals, not durable memories + +Before writing memory, verify the lesson is durable, useful, privacy-safe, and +grounded in user instruction or source evidence. + +## Forgetting And Correction + +If memory is wrong, private, stale, or superseded: + +- redact it when the durable shape is useful but details are unsafe +- delete it when it should not be retained +- supersede it when a newer decision replaces it +- prefer explicit reasons for every forget operation + +In Coordinated mode these lifecycle writes require the coordinator capability. + +Treat redaction as monotonic. Do not try to restore a redacted ID through +replacement import; create a new reviewed memory only if the user deliberately +reintroduces safe content. + +Never keep known-wrong memory merely because it was previously recalled. + +## Closeout Habit + +At the end of meaningful work, ask: + +- What did we decide? +- What did we learn? +- What should future agents avoid repeating? +- Did the user state a durable preference? +- Is there a future seed worth revisiting? +- Is any memory sensitive and better left unstored? + +Only remember the answers that will materially improve future work. diff --git a/scripts/validate-plugin-packages.py b/scripts/validate-plugin-packages.py new file mode 100644 index 0000000..ae49c04 --- /dev/null +++ b/scripts/validate-plugin-packages.py @@ -0,0 +1,149 @@ +#!/usr/bin/env python3 +"""Validate the repo-scoped Codex and Claude Code plugin packages.""" + +from __future__ import annotations + +import json +from pathlib import Path +from typing import Any + + +ROOT = Path(__file__).resolve().parents[1] +PLUGIN = ROOT / "plugins" / "tree-ring-memory" + + +def load_json(path: Path) -> dict[str, Any]: + value = json.loads(path.read_text(encoding="utf-8")) + if not isinstance(value, dict): + raise SystemExit(f"{path.relative_to(ROOT)} must contain a JSON object") + return value + + +def require(condition: bool, message: str) -> None: + if not condition: + raise SystemExit(message) + + +def require_markers(path: Path, markers: list[str]) -> None: + text = " ".join(path.read_text(encoding="utf-8").split()) + missing = [marker for marker in markers if " ".join(marker.split()) not in text] + require(not missing, f"{path.relative_to(ROOT)} is missing: {', '.join(missing)}") + + +def validate_marketplace_source(source: str, expected: str) -> Path: + require(source == expected, f"marketplace source must be {expected}") + require(source.startswith("./") and ".." not in Path(source).parts, "unsafe marketplace source") + resolved = (ROOT / source).resolve() + require(resolved == PLUGIN.resolve(), "marketplace source does not resolve to the plugin") + return resolved + + +def validate_codex() -> None: + marketplace = load_json(ROOT / ".agents" / "plugins" / "marketplace.json") + require(marketplace.get("name") == "tree-ring-memory", "Codex marketplace name is stale") + require( + marketplace.get("interface", {}).get("displayName") == "Tree Ring Memory", + "Codex marketplace display name is stale", + ) + entries = marketplace.get("plugins") + require(isinstance(entries, list) and len(entries) == 1, "Codex marketplace must contain one plugin") + entry = entries[0] + require(entry.get("name") == "tree-ring-memory", "Codex marketplace plugin name is stale") + source = entry.get("source") + require(isinstance(source, dict) and source.get("source") == "local", "Codex source must be local") + validate_marketplace_source(source.get("path", ""), "./plugins/tree-ring-memory") + require(entry.get("policy") == {"installation": "AVAILABLE", "authentication": "ON_INSTALL"}, "Codex policy is incomplete") + require(entry.get("category") == "Developer Tools", "Codex category is stale") + + manifest = load_json(PLUGIN / ".codex-plugin" / "plugin.json") + require(manifest.get("name") == "tree-ring-memory", "Codex manifest name is stale") + require(manifest.get("version") == "0.3.1", "Codex manifest version is stale") + require(manifest.get("skills") == "./skills/", "Codex skills path is stale") + for unsupported in ("mcpServers", "apps", "hooks"): + require(unsupported not in manifest, f"skills-only Codex plugin must not declare {unsupported}") + interface = manifest.get("interface") + require(isinstance(interface, dict), "Codex interface metadata is required") + require("screenshots" not in interface, "skills-only Codex ZIP must not declare screenshots") + for asset_key in ("composerIcon", "logo"): + asset = interface.get(asset_key) + require(isinstance(asset, str) and asset.startswith("./assets/"), f"Codex {asset_key} path is invalid") + require((PLUGIN / asset).is_file(), f"Codex {asset_key} asset is missing") + + +def validate_claude() -> None: + marketplace = load_json(ROOT / ".claude-plugin" / "marketplace.json") + require(marketplace.get("name") == "tree-ring-memory", "Claude marketplace name is stale") + require(marketplace.get("version") == "0.3.0", "Claude marketplace version is stale") + require(isinstance(marketplace.get("owner"), dict), "Claude marketplace owner is required") + entries = marketplace.get("plugins") + require(isinstance(entries, list) and len(entries) == 1, "Claude marketplace must contain one plugin") + entry = entries[0] + require(entry.get("name") == "tree-ring-memory", "Claude marketplace plugin name is stale") + validate_marketplace_source(entry.get("source", ""), "./plugins/tree-ring-memory") + require("version" not in entry, "Claude marketplace entry must defer to plugin.json version") + + manifest = load_json(PLUGIN / ".claude-plugin" / "plugin.json") + require(manifest.get("name") == "tree-ring-memory", "Claude manifest name is stale") + require(manifest.get("version") == marketplace.get("version"), "Claude versions are not synchronized") + require(manifest.get("skills") == "./skills/", "Claude skills path is stale") + + expected_commands = { + "tree-ring-audit.md", + "tree-ring-capture.md", + "tree-ring-certify.md", + "tree-ring-dox-sync.md", + "tree-ring-recall.md", + "tree-ring-status.md", + } + actual_commands = {path.name for path in (PLUGIN / "commands").glob("*.md")} + require(actual_commands == expected_commands, "Claude command package is incomplete") + + +def validate_shared_contract() -> None: + skill = PLUGIN / "skills" / "tree-ring-memory" / "SKILL.md" + require_markers( + skill, + [ + "Runtime Preflight", + "0.14.0 or newer", + "DOX Contract Flow", + "tree-ring dox sync --source-root --dry-run", + "Certification Boundary", + "tree-ring integrations certify --source-root .", + "tree-ring recall-quality --source-root .", + "scripts/certify-tree-ring.sh", + "does not run certification", + "TREE_RING_COORDINATOR_TOKEN", + "configured-awaiting-proof", + "needs-plugin", + "same-host local-filesystem processes", + "schema v3", + ], + ) + require_markers( + PLUGIN / "commands" / "tree-ring-dox-sync.md", + ["--dry-run", "Current source contracts are authoritative", "must not rewrite root or child `AGENTS.md` files"], + ) + require_markers( + PLUGIN / "commands" / "tree-ring-certify.md", + ["tree-ring integrations certify", "tree-ring recall-quality", "repository-only", "does not execute the suite"], + ) + require((ROOT / "scripts" / "certify-tree-ring.sh").is_file(), "source certification script is missing") + require(not (PLUGIN / "scripts" / "certify-tree-ring.sh").exists(), "source certification suite must not be bundled") + for filename in ("LICENSE", "PRIVACY.md", "SECURITY.md", "TERMS.md", "README.md"): + require((PLUGIN / filename).is_file(), f"plugin {filename} is missing") + for path in PLUGIN.rglob("*"): + if path.is_file() and path.suffix in {".md", ".json"}: + text = path.read_text(encoding="utf-8") + require("[TODO:" not in text and "Local developer" not in text, f"placeholder remains in {path.relative_to(ROOT)}") + + +def main() -> None: + validate_codex() + validate_claude() + validate_shared_contract() + print("Tree Ring Memory Codex and Claude plugin packages validated") + + +if __name__ == "__main__": + main()