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
2 changes: 1 addition & 1 deletion .codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "tree-ring-memory",
"version": "0.3.6",
"version": "0.3.7",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

1. Users see the wrong release version 🐞 Bug ≡ Correctness

The manifest version is bumped to 0.3.7, while the release introduction in README.md still
identifies the plugin as 0.3.6. Anyone using the README to verify the installed or submitted
release receives metadata that conflicts with both packaged manifests and the submission dossier.
Agent Prompt
## Issue description
The release manifests and submission dossier declare version `0.3.7`, but the README still presents the plugin as version `0.3.6`.

## Issue Context
This release updates both packaged manifests to `0.3.7`; user-facing release documentation should identify the same version. Add validation if practical so future release bumps cannot leave this copy stale.

## Fix Focus Areas
- README.md[9-12]
- scripts/validate-plugin.sh[69-70]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

"description": "Local-first memory lifecycle, project bootstrap, and receipt-backed harness guidance for coding agents using Tree Ring Memory v0.15+.",
"author": {
"name": "TerminallyLazy",
Expand Down
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ used by this guidance.
The repository plugin includes native lifecycle hooks and requires CLI `0.15.6`
or newer for automatic recall. Build the separate public-directory ZIP with
`python3 packaging/build-codex-skills-only.py tree-ring-memory-codex-skills-only.zip`.
That generated ZIP is a skills-only package. It intentionally omits
`interface.screenshots`, which OpenAI's ZIP ingestion does not accept for this
package type; the logo and composer icon remain available.
That generated ZIP includes skills and native Codex lifecycle hooks. The portal
calls the route "Skills only" because this plugin has no MCP server. The upload
preserves executable hook scripts and excludes Claude metadata and commands.
Hooks require Codex or ChatGPT Work, an available CLI, and host trust; ordinary
Chat remains guidance-only. See [OpenAI's current compatibility guidance](https://developers.openai.com/plugins/guides/submit-claude-plugin).

It does not run a background service, scrape chats, or capture transcripts.
The active agent chooses when a memory action is useful, source-linked, and
Expand Down Expand Up @@ -261,9 +263,8 @@ project and plugin hooks.

`integrations status --verbose` reports the last validated recall's result
count and query class. A zero-result receipt proves the check ran; it does not
prove that useful context was found. A skills-only plugin installation has no
automatic lifecycle hooks; enable the repository plugin or configure the
project with the CLI to obtain them. A newly configured Codex hook still needs
prove that useful context was found. Older skills-only packages omitted
automatic lifecycle hooks. Current Git and public upload packages include them. A newly configured Codex hook still needs
the host's trust flow and a new session before automatic execution can be
verified.

Expand Down
32 changes: 19 additions & 13 deletions SUBMISSION.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ Long description:

## Release Notes

Version 0.3.6 of the v0.15-compatible skills-only package adds verified
Version 0.3.7 retains native lifecycle hooks in the public upload and verified
project-local bootstrap, project-root-safe initialization, and scope-preserving
CLI update guidance. It retains the ZIP-ingestion fix that omits unsupported
`interface.screenshots`, plus receipt-backed harness readiness, same-host
Expand All @@ -91,15 +91,21 @@ requirement.
The core workflow invokes a separately installed local CLI and reads project
files when the host supports those capabilities. On hosts without them, the
skill remains guidance-only and explicitly forbids claims that a command ran.
OpenAI's Claude-plugin migration guide asks local-execution plugins to contact
their OpenAI partner; disclose this boundary in the submission rather than
representing the package as a hosted integration.

## Repository Lifecycle Distribution

The Git marketplace package now includes SessionStart, SubagentStart, Stop, and
SubagentStop hooks backed by CLI 0.15.6. The public-directory upload must use
`packaging/build-codex-skills-only.py`; it excludes hooks and does not promise
automatic invocation. Updating the Git repository does not update a previously
reviewed directory snapshot. Submit the versioned ZIP through the directory
review channel separately.
Native command hooks require the Codex runtime (including ChatGPT Work), an
available CLI, and host trust. Ordinary Chat does not run these hooks. Disclose
this boundary and follow [OpenAI compatibility guidance](https://developers.openai.com/plugins/guides/submit-claude-plugin).

## Native Lifecycle Distribution

Both the Git package and public-directory ZIP include SessionStart,
SubagentStart, Stop, and SubagentStop hooks. Build the public upload using
`packaging/build-codex-skills-only.py`. The portal's "Skills only" route means
there is no MCP server; it does not require stripping native command hooks.
CLI 0.15.7 or newer repairs installer bootstrap. Host trust and a fresh recall
receipt are required before claiming activation. Updating Git does not update
a reviewed directory snapshot; submit the versioned ZIP separately.

Package validation covers deterministic ZIP bytes, canonical hook definitions,
and executable permissions. Older local scaffold validators that reject all
`hooks` fields are incompatible with the current published contract. Use native
host validation and the [current manifest specification](https://developers.openai.com/plugins/build/plugins).
9 changes: 7 additions & 2 deletions packaging/build-codex-skills-only.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
"""Build the OpenAI upload artifact without repository lifecycle hooks."""
"""Build the OpenAI skills-only upload, including native Codex lifecycle hooks."""

from __future__ import annotations

Expand All @@ -17,7 +17,9 @@
def write_file(archive: ZipFile, source: Path, destination: Path) -> None:
info = ZipInfo(str(PACKAGE_ROOT / destination), FIXED_TIMESTAMP)
info.compress_type = ZIP_DEFLATED
info.external_attr = 0o100644 << 16
info.create_system = 3
mode = 0o100755 if source.stat().st_mode & 0o111 else 0o100644
info.external_attr = mode << 16
archive.writestr(info, source.read_bytes())


Expand All @@ -35,6 +37,9 @@ def build(destination: Path) -> None:
for path in sorted((PLUGIN / "assets").rglob("*")):
if path.is_file():
write_file(archive, path, path.relative_to(PLUGIN))
for name in ("codex-hooks.json", "codex-hook.sh"):
path = PLUGIN / "hooks" / name
write_file(archive, path, path.relative_to(PLUGIN))
Comment on lines +40 to +42

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. Homebrew users get unsupported hooks 🔗 Cross-repo conflict ≡ Correctness

build() now includes native lifecycle hooks that require Tree Ring Memory CLI 0.15.6 or newer,
while the live Homebrew formula still installs 0.15.3. When a Homebrew user installs this public
upload without a project-local binary, codex-hook.sh resolves the outdated executable from PATH,
reaching unsupported automatic recall and checkpoint behavior.
Agent Prompt
## Issue description
The public upload now activates lifecycle hooks requiring CLI 0.15.6+, but the live Homebrew installation path supplies CLI 0.15.3. Prevent the hook from invoking an unsupported Homebrew runtime and coordinate a formula update to at least 0.15.6, preferably the pinned 0.15.7 release.

## Issue Context
The hook prefers a project-local executable but otherwise resolves `tree-ring` from `PATH`, where Homebrew installs version 0.15.3. Add an explicit compatibility check or graceful fallback until the Homebrew formula is updated.

## Fix Focus Areas
- hooks/codex-hook.sh[21-26]
- packaging/build-codex-skills-only.py[40-42]
- /cross_repos/homebrew-tree-ring/Formula/tree-ring.rb[4-18]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

for name in ("LICENSE", "PRIVACY.md", "SECURITY.md", "TERMS.md"):
write_file(archive, PLUGIN / name, Path(name))

Expand Down
7 changes: 4 additions & 3 deletions packaging/codex-skills-only/.codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{
"name": "tree-ring-memory",
"version": "0.3.6",
"version": "0.3.7",
"description": "Local-first memory lifecycle, project bootstrap, and receipt-backed harness guidance for coding agents using Tree Ring Memory v0.15+.",
"author": {
"name": "TerminallyLazy",
"url": "https://github.com/TerminallyLazy"
},
"homepage": "https://github.com/TerminallyLazy/Tree-Ring-Memory",
"repository": "https://github.com/TerminallyLazy/Tree-Ring-Memory",
"repository": "https://github.com/TerminallyLazy/tree-ring-memory-codex-plugin",
"license": "MIT",
"keywords": [
"codex",
Expand Down Expand Up @@ -44,5 +44,6 @@
"brandColor": "#2F7D5C",
"composerIcon": "./assets/tree-ring-memory-logo.png",
"logo": "./assets/tree-ring-memory-logo.png"
}
},
"hooks": "./hooks/codex-hooks.json"
}
6 changes: 4 additions & 2 deletions scripts/validate-plugin.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ root = Path(".")
manifest = json.loads((root / ".codex-plugin/plugin.json").read_text())
if manifest.get("name") != "tree-ring-memory":
raise SystemExit("plugin name must remain tree-ring-memory")
if manifest.get("version") != "0.3.6":
raise SystemExit("wrapper version must be 0.3.6")
if manifest.get("version") != "0.3.7":
raise SystemExit("wrapper version must be 0.3.7")

interface = manifest.get("interface", {})
prompts = interface.get("defaultPrompt", [])
Expand Down Expand Up @@ -92,3 +92,5 @@ assert_contains "$SKILL" 'launch every ordinary worker with `TREE_RING_COORDINAT
printf 'Tree Ring Memory Codex wrapper contract is valid.\n'

python3 scripts/validate-lifecycle.py

python3 scripts/validate-upload.py
73 changes: 73 additions & 0 deletions scripts/validate-upload.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#!/usr/bin/env python3
"""Validate the deterministic public upload and its native lifecycle hooks."""
import json
import subprocess
import sys
import tempfile
from pathlib import Path
from zipfile import ZipFile

ROOT = Path(__file__).resolve().parents[1]
PLUGIN = ROOT
CODEX_SKILLS_ONLY = ROOT / "packaging/codex-skills-only"
CODEX_SKILLS_BUILDER = ROOT / "packaging/build-codex-skills-only.py"


def require(condition, message):
if not condition:
raise SystemExit(message)


def load_json(path):
return json.loads(path.read_text())


def validate_codex_skills_only() -> None:
repository_manifest = load_json(PLUGIN / ".codex-plugin" / "plugin.json")
skills_manifest = load_json(CODEX_SKILLS_ONLY / ".codex-plugin" / "plugin.json")
expected_manifest = dict(repository_manifest)
require(skills_manifest == expected_manifest, "skills-only Codex manifest drifted from repository metadata")
for unsupported in ("mcpServers", "apps"):
require(unsupported not in skills_manifest, f"skills-only Codex ZIP must not declare {unsupported}")
require("screenshots" not in skills_manifest.get("interface", {}), "skills-only Codex ZIP must not declare screenshots")

with tempfile.TemporaryDirectory() as temporary:
first = Path(temporary) / "first.zip"
second = Path(temporary) / "second.zip"
for destination in (first, second):
subprocess.run([sys.executable, str(CODEX_SKILLS_BUILDER), str(destination)], check=True)
require(first.read_bytes() == second.read_bytes(), "skills-only Codex ZIP must be deterministic")
with ZipFile(first) as archive:
names = set(archive.namelist())
prefix = "tree-ring-memory/"
require(names and all(name.startswith(prefix) for name in names), "skills-only Codex ZIP needs one package root")
manifest_name = prefix + ".codex-plugin/plugin.json"
require(manifest_name in names, "skills-only Codex ZIP manifest is missing")
built_manifest = json.loads(archive.read(manifest_name))
require(built_manifest == skills_manifest, "skills-only Codex ZIP manifest is stale")
require(
not any(
marker in name
for name in names
for marker in ("/commands/", "/.claude-plugin/", "/packaging/")
),
"skills-only Codex ZIP contains repository-only components",
)
for hook_name in ("codex-hooks.json", "codex-hook.sh"):
archive_path = prefix + "hooks/" + hook_name
require(archive_path in names, "public upload is missing its native lifecycle hook")
require(archive.read(archive_path) == (PLUGIN / "hooks" / hook_name).read_bytes(), "public upload hook differs from the validated runtime hook")
hook_mode = archive.getinfo(prefix + "hooks/codex-hook.sh").external_attr >> 16
require(hook_mode & 0o111 != 0, "public upload hook script must remain executable")
require(
prefix + "skills/tree-ring-memory/SKILL.md" in names,
"skills-only Codex ZIP is missing its skill",
)
require(
prefix + "assets/tree-ring-memory-logo.png" in names,
"skills-only Codex ZIP is missing its declared assets",
)


validate_codex_skills_only()
print("Public upload retains validated executable lifecycle hooks")
4 changes: 2 additions & 2 deletions skills/tree-ring-memory/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ working directory by accident.
this project. Otherwise check `command -v tree-ring` and run
`tree-ring --version`.
2. Read existing `<project-root>/.tree-ring/SKILL.md` and `CLI.md` when present.
Lifecycle hooks need CLI 0.15.6 or newer; a skills-only plugin package has no
automatic hooks. Use `integrations status --verbose` to inspect the last
Lifecycle hooks need CLI 0.15.6 or newer; older packages may omit
automatic hooks. Current Codex packages include them, including the public upload. Use `integrations status --verbose` to inspect the last
recall count and query class, and distinguish no receipt from zero results.
3. This package targets Tree Ring Memory CLI 0.15.0 or newer. If no compatible
CLI is available and the user's request already authorizes Tree Ring setup,
Expand Down