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 .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"name": "memware",
"source": "./integrations/claude-code",
"description": "Session transcripts indexed for recall; a belief ledger that only remembers the latest truth. Hooks: SessionEnd/PreCompact sync, prompt-time belief context.",
"version": "0.1.1",
"version": "0.2.4",
"author": {
"name": "ericwalisko"
}
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@ htmlcov/
*.db-wal
*.db-shm
.memware/

# uv lockfile (library, not committed)
uv.lock
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ All notable changes to this project are documented here. The format follows

## [Unreleased]

### Fixed
- The Claude Code plugin manifest version was stuck at 0.1.1 across every release, so
`claude plugin update` compared 0.1.1 to 0.1.1 and never reinstalled — no plugin or hook
change (e.g. the 0.2.x automatic session-end backup hook) could reach an installed
machine. Both manifests now track the package version, enforced by
`tests/test_plugin_manifest.py` so it cannot silently drift again.

## [0.2.4] - 2026-09-03

### Fixed
Expand Down
14 changes: 12 additions & 2 deletions RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,23 @@ Troubleshooting below.

## Cutting a release

1. **Bump the version.** It lives in exactly one place:
1. **Bump the version.** The package version lives in:

```
src/memware/__init__.py → __version__ = "0.1.1"
```

`pyproject.toml` reads it via `[tool.hatch.version]`, so nothing else needs editing.
`pyproject.toml` reads it via `[tool.hatch.version]`. The Claude Code plugin also carries
its own copy of the version in two manifests, and `tests/test_plugin_manifest.py` fails CI
unless both equal the package version — so bump all three together:

```
integrations/claude-code/.claude-plugin/plugin.json → "version"
.claude-plugin/marketplace.json → plugins[memware].version
```

`claude plugin update` only reinstalls when the manifest version rises, so a plugin or hook
change that skips this bump never reaches an installed machine.

2. **Cut the CHANGELOG.** Move the `## [Unreleased]` entries under a new
`## [X.Y.Z] - YYYY-MM-DD` heading and leave `## [Unreleased]` empty above it.
Expand Down
2 changes: 1 addition & 1 deletion integrations/claude-code/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "memware",
"description": "Session transcripts indexed for recall; a belief ledger that only remembers the latest truth.",
"version": "0.1.1",
"version": "0.2.4",
"author": {
"name": "ericwalisko"
}
Expand Down
24 changes: 24 additions & 0 deletions tests/test_plugin_manifest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"""The Claude Code plugin carries its own version string, and `claude plugin update` only
reinstalls when it rises. Nothing in the release path enforced it, so it silently sat at 0.1.1
across many releases and no hook change ever reached an installed machine. These tests keep both
manifests equal to the package version, so cutting a release always moves the plugin too."""

import json
from pathlib import Path

import memware

ROOT = Path(__file__).resolve().parents[1]
PLUGIN = ROOT / "integrations" / "claude-code" / ".claude-plugin" / "plugin.json"
MARKETPLACE = ROOT / ".claude-plugin" / "marketplace.json"


def test_plugin_manifest_version_matches_package():
plugin = json.loads(PLUGIN.read_text())
assert plugin["version"] == memware.__version__, (plugin["version"], memware.__version__)


def test_marketplace_plugin_version_matches_package():
market = json.loads(MARKETPLACE.read_text())
entry = next(p for p in market["plugins"] if p["name"] == "memware")
assert entry["version"] == memware.__version__, (entry["version"], memware.__version__)
Loading