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 @@ -8,7 +8,7 @@
"name": "memesh",
"source": "./",
"description": "MeMesh \u2014 agentic memory for coding agents. Captured from the agent's real work via hooks, recalled when it acts. One SQLite file, zero cloud required.",
"version": "4.8.3",
"version": "4.8.4",
"author": {
"name": "PCIRCLE AI"
},
Expand Down
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"author": {
"name": "PCIRCLE AI"
},
"version": "4.8.3",
"version": "4.8.4",
"mcpServers": "./.claude-plugin/mcp.json",
"homepage": "https://github.com/PCIRCLE-AI/memesh",
"repository": "https://github.com/PCIRCLE-AI/memesh",
Expand Down
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": "memesh",
"description": "MeMesh — agentic memory for coding agents.",
"version": "4.8.3",
"version": "4.8.4",
"mcpServers": "./.codex-plugin/mcp.json"
}
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,6 @@ docs/guides/
PRE_RELEASE_CHECKLIST.md
docs/notes/
.smoke-test*.db-*

# === qa:live-journey receipts (owner-machine evidence, never shipped) ===
.qa/
119 changes: 83 additions & 36 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,34 @@ All notable changes to MeMesh are documented here.

## [Unreleased]

## [4.8.4] — 2026-09-04

### Added

- **`npm run qa:pre-release` — one door before a release, that says what it did
not check.** It runs `npm run build`, `verify:artifact` (lint, typecheck,
version coherence, doc claims, the isolated suite, the packed artifact and
every derived upgrade path — the same sequence `prepublishOnly` runs, now
named once instead of copied) and `audit:memory`, reports each step's real
exit code, and prints the checks it cannot run: the interactive live journey,
the post-release check, and the entry-point start gate.
version coherence, doc claims, the isolated suite, the packed artifact,
every derived upgrade path, and now the entry-point start gate below — the
same sequence `prepublishOnly` runs, now named once instead of copied) and
`audit:memory`, reports each step's real exit code, and prints the checks it
still cannot run here: the interactive live journey (gated separately by
`release:finish`, below) and the post-release check.
- **A release gate that actually starts every shipped entry point.** Eight
binaries and nine hooks ship; every existing check only asked whether a
file existed, whether JSON parsed, or whether a referenced path resolved —
none of them ran the code. `scripts/check-entry-points-start.mjs`
(`npm run check:entry-points-start`, folded into `verify:release`) spawns
each of the 17 for real against a throwaway `MEMESH_DIR`: a CLI must accept
`--version`, an MCP server must exit 0 on stdin EOF, a long-lived daemon
must reach its "running" signal (a log line, or its socket file appearing),
and a host runtime with no config must fail closed with a named message,
never a raw stack trace. It also fails on any unresolved `${...}` left in
`.mcp.json` or `hooks/hooks.json`, evaluated against each manifest's own
real substitution environment — `CLAUDE_PLUGIN_ROOT` is always defined for
the plugin-loader-only `hooks/hooks.json`, but not for `.mcp.json`, which
Claude Code also auto-discovers with no plugin loader involved at all. The
Windows skip list is pinned to exactly one entry (`memesh-router`, no
`AF_UNIX` there) so it cannot grow silently.
- **`npm run qa:post-release` — the check that runs on the machine, not on a
fresh clone.** Every gate here runs on a fresh checkout or a fresh install,
and all three release incidents lived in state that already existed: v4.7.0
Expand All @@ -26,9 +45,55 @@ All notable changes to MeMesh are documented here.
resolve, not the first one: two installs on one PATH, four releases apart,
is the shape of the incident, and a check that stops at the first hit cannot
see it.
- **Repeatable owner-run live delivery checks.** `npm run qa:live-journey -- --host codex|claude`
(`scripts/qa/live-journey.mjs`) starts this checkout's router in a throwaway
`MEMESH_DIR`, registers one real host session, sends one exact-session
envelope, and passes only on model-visible proof: the Codex path requires the
model to quote the envelope's `message_id` and `delivery_id` back on its next
turn; the Claude path requires an `intake` receipt written by the interactive
session the operator launched with the printed command. Both then stop the
session and require `recipient_unavailable` while the durable row stays
fetchable and the router still answers `discover`. It refuses to run against
`$HOME/.memesh`, reads no auth files, never runs in CI, and records its
limitations in the JSON report — including that the Codex registration is
harness-driven because `codex exec --ignore-user-config` bypasses the plugin
`SessionStart` hook, and that print-mode Claude is unsupported (#275).
Closes the "repeatable check in the repository" box on #270 and #272.
- **A write-side reminder hook.** The read side of MeMesh was already automatic
(SessionStart and PreToolUse inject memories) but nothing prompted an agent
to *store* anything, so decisions made mid-session were routinely lost until
the user said "remember this" (#277). A ninth hook,
`scripts/hooks/decision-nudge.js`, runs on `PostToolUse` for `ExitPlanMode`
and `AskUserQuestion` — the two calls where a decision has most likely just
been made — and adds one line of context asking the model to `remember` it
if it is worth keeping. At most once per tool per session, enforced by an
`O_EXCL` flag file under `MEMESH_DIR/decision-nudge-flags/`; the hook never
opens the database, exits 0 on any malformed input, and writes nothing to
the graph itself. Hook inventories in the READMEs (three languages),
`docs/ARCHITECTURE.md`, `AGENTS.md`, `CODEMAP.md` and the skill now list nine
hooks, and `check-codemap-parity` no longer hard-codes the count.

### Changed

- **`npm run release:finish` now runs the real-credential checks instead of
merely documenting that they exist.** `qa:pre-release` and `qa:live-journey`
were both available since the previous release but neither was in the one
command that actually cuts a release — a check nobody has to run is a check
that gets skipped exactly when a release is rushed. `finish-release.mjs` now
runs `npm run qa:pre-release` itself (build + `verify:artifact` +
`audit:memory`, several minutes, streamed live) and blocks on its exit code;
a receipt cannot substitute here because it can go stale the moment the next
commit lands. `qa:live-journey` cannot run unattended — it needs a Codex
login or a person at an interactive Claude Code session — so it stays
receipt-based: `npm run qa:live-journey -- --host codex|claude --out
.qa/<host>-report.json` writes a report, and `release:finish` requires ONE
of the two hosts' reports to be readable, `verdict: "PASS"`, recorded
against a clean tree, and naming this exact commit — an older PASS proves an
earlier revision, not this one. Neither host is preferred; only Codex can be
driven unattended today, but a human-run Claude receipt satisfies the gate
exactly as well. `.qa/` is gitignored — a receipt is owner-machine evidence,
never shipped.

- **The packed-upgrade gate derives its upgrade paths instead of pinning
them.** `scripts/smoke-packed-upgrade.mjs` named both ends by hand
(`expectedPreviousVersion = '4.8.2'`, `expectedCandidateVersion = '4.8.3'`,
Expand All @@ -45,6 +110,19 @@ All notable changes to MeMesh are documented here.

### Fixed

- **The Claude Code plugin cache never cleaned up an old version after an
upgrade — only the ONE it had just replaced.** `upgrade-plugin.sh`'s atomic
swap always removed the previous cache directory, but anything left behind
by an interrupted upgrade, or one from before this swap mechanism existed,
had no path back to zero: measured on the maintainer's machine, 9 stale
version directories, 1.2 GB, with nothing ever sweeping them. A new
`sweep_stale_cache_versions` removes every OTHER directory under the cache
root whose name is exactly `<major>.<minor>.<patch>` after a successful
upgrade — never the version just installed, and never the registry's own
recorded install path even when that path is a stray non-canonical
directory the "repairing it" branch above deliberately leaves for a human,
whatever it happens to be named.

- **Three release-gate guards that could not fail, and the silent failure one
of them was hiding.** A mutation audit reintroduced the defect each guard was
written for and re-ran the suite: with all three defects present at once,
Expand Down Expand Up @@ -451,37 +529,6 @@ All notable changes to MeMesh are documented here.
independent `readUpdateCheckCache()` path formula is untouched by this —
it only reads, and the filename scheme did not change.

### Added

- **Repeatable owner-run live delivery checks.** `npm run qa:live-journey -- --host codex|claude`
(`scripts/qa/live-journey.mjs`) starts this checkout's router in a throwaway
`MEMESH_DIR`, registers one real host session, sends one exact-session
envelope, and passes only on model-visible proof: the Codex path requires the
model to quote the envelope's `message_id` and `delivery_id` back on its next
turn; the Claude path requires an `intake` receipt written by the interactive
session the operator launched with the printed command. Both then stop the
session and require `recipient_unavailable` while the durable row stays
fetchable and the router still answers `discover`. It refuses to run against
`$HOME/.memesh`, reads no auth files, never runs in CI, and records its
limitations in the JSON report — including that the Codex registration is
harness-driven because `codex exec --ignore-user-config` bypasses the plugin
`SessionStart` hook, and that print-mode Claude is unsupported (#275).
Closes the "repeatable check in the repository" box on #270 and #272.

- **A write-side reminder hook.** The read side of MeMesh was already automatic
(SessionStart and PreToolUse inject memories) but nothing prompted an agent
to *store* anything, so decisions made mid-session were routinely lost until
the user said "remember this" (#277). A ninth hook,
`scripts/hooks/decision-nudge.js`, runs on `PostToolUse` for `ExitPlanMode`
and `AskUserQuestion` — the two calls where a decision has most likely just
been made — and adds one line of context asking the model to `remember` it
if it is worth keeping. At most once per tool per session, enforced by an
`O_EXCL` flag file under `MEMESH_DIR/decision-nudge-flags/`; the hook never
opens the database, exits 0 on any malformed input, and writes nothing to
the graph itself. Hook inventories in the READMEs (three languages),
`docs/ARCHITECTURE.md`, `AGENTS.md`, `CODEMAP.md` and the skill now list nine
hooks, and `check-codemap-parity` no longer hard-codes the count.

## [4.8.3] — 2026-08-31

### Fixed
Expand Down
27 changes: 18 additions & 9 deletions CODEMAP.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# CODEMAP

**Version**: 4.8.3
**Version**: 4.8.4

A navigation map for the codebase: *"I want to change X — which file?"* For the
design rationale behind these modules see [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md);
Expand Down Expand Up @@ -146,12 +146,21 @@ The same `operations.ts` memory functions run identically from all three transpo
- Owner-run live checks (never CI): `scripts/qa/live-journey.mjs` — `npm run qa:live-journey -- --host codex|claude`
drives a real Codex thread or an interactive Claude channel session and requires model-visible proof.
Its pure half is pinned by `tests/qa/live-journey.test.ts`; the contract is in `docs/platforms/agent-messaging.md`.
- Release gates, in the order a release meets them: `npm run qa:pre-release`
(`scripts/qa/pre-release.mjs`) runs build + `verify:artifact` + `audit:memory` as one door
and prints what it could not check; `verify:artifact` is the same sequence `prepublishOnly`
runs, named once. `scripts/smoke-packed-upgrade.mjs` derives every upgrade path it proves
from `package.json` and the registry (`scripts/lib/upgrade-matrix.mjs`) instead of pinning
a version pair. After publishing, `npm run qa:post-release` (`scripts/qa/post-release.mjs`)
checks registry acceptance, a fresh install from the registry, and whether this machine is
on the release — read-only, printing fixes rather than running them.
- Release gates, in the order a release meets them: `verify:release` (called by `qa:pre-release`
below) now ends with `npm run check:entry-points-start`
(`scripts/check-entry-points-start.mjs`), which spawns every one of the 17 shipped bins and
hooks for real and fails on any unresolved `${...}` left in `.mcp.json`/`hooks/hooks.json`.
`npm run qa:pre-release` (`scripts/qa/pre-release.mjs`) runs build + `verify:artifact` +
`audit:memory` as one door and prints what it could not check; `verify:artifact` is the same
sequence `prepublishOnly` runs, named once. `scripts/smoke-packed-upgrade.mjs` derives every
upgrade path it proves from `package.json` and the registry (`scripts/lib/upgrade-matrix.mjs`)
instead of pinning a version pair. `npm run release:finish` (`scripts/finish-release.mjs`) runs
`qa:pre-release` itself and blocks on its exit code, and requires a `qa:live-journey` receipt
under `.qa/` (named `<host>-report.json` — codex or claude, either satisfies it) that is
`PASS`, clean-tree, and names the exact commit being released
(`scripts/lib/release-preconditions.mjs`'s
`findUsableLiveJourneyReceipt`) — real-credential checks CI cannot run, now required rather
than merely available. After publishing, `npm run qa:post-release`
(`scripts/qa/post-release.mjs`) checks registry acceptance, a fresh install from the registry,
and whether this machine is on the release — read-only, printing fixes rather than running them.
- Version anchors that must agree on a bump: `package.json`, both root entries in `package-lock.json`, `.claude-plugin/plugin.json`, `.claude-plugin/marketplace.json`, `herdr-plugin.toml`, `CHANGELOG.md`, `CODEMAP.md`, `docs/ARCHITECTURE.md`, and `docs/api/API_REFERENCE.md`. Run `npm run build` after to regenerate `dist/skills-manifest.json`.
4 changes: 2 additions & 2 deletions dist/skills-manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
},
{
"path": ".claude-plugin/plugin.json",
"sha256": "fe68e32aaf8cd1ec56472bd058b1149f8451938524bf945ad27c4ba9cd362136",
"sha256": "2b425a0b6ca6c6a2a549d273616ee0aa418a485960aa5f05ba44a38a6d49e9b5",
"bytes": 572
},
{
Expand All @@ -18,7 +18,7 @@
},
{
"path": ".codex-plugin/plugin.json",
"sha256": "4a31bc9ce1ef62f7203ed9b3a9d4a9aa4b9a95a19f37f60cf4cfbdffa0ca95d8",
"sha256": "1ce4c7b5a8f04cfe1dde55adb6b1af580141de3a73eca0ee5a7bbb066d39b725",
"bytes": 154
},
{
Expand Down
2 changes: 1 addition & 1 deletion docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# MeMesh Plugin Architecture

**Version**: 4.8.3
**Version**: 4.8.4

> Looking for "which file do I change for X?" — see [CODEMAP.md](../CODEMAP.md).

Expand Down
2 changes: 1 addition & 1 deletion docs/api/API_REFERENCE.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# MeMesh Plugin -- API Reference

**Protocol**: Model Context Protocol (MCP) over stdio
**Version**: 4.8.3
**Version**: 4.8.4
**Compatibility**: Works with Claude Code plugins, Claude Managed Agents (via MCP connector), and any MCP-compatible client.

**Native Integrations**: Beyond MCP, MeMesh integrates as a native memory provider for Hermes Agent (Python `MemoryProvider` plugin) and OpenClaw (TypeScript memory-capability plugin) — same tier as their built-in backends, not HTTP bridges. See [docs/platforms/](../platforms/) for platform-specific guides.
Expand Down
9 changes: 7 additions & 2 deletions docs/platforms/agent-messaging.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,10 +212,15 @@ close that gap by requiring evidence that could only have come out of a running
model.

```bash
TMPDIR=/private/tmp npm run qa:live-journey -- --host codex --out codex-report.json
TMPDIR=/private/tmp npm run qa:live-journey -- --host claude --out claude-report.json
TMPDIR=/private/tmp npm run qa:live-journey -- --host codex --out .qa/codex-report.json
TMPDIR=/private/tmp npm run qa:live-journey -- --host claude --out .qa/claude-report.json
```

`.qa/` is where `npm run release:finish` looks for these reports (any ONE
host's PASS, against the exact commit being released, is enough — see
`scripts/lib/release-preconditions.mjs`'s `findUsableLiveJourneyReceipt`). The
directory is gitignored; a report is owner-machine evidence, never shipped.

`TMPDIR` is not decoration on macOS. The router's Unix socket lives beside the
database inside the temporary directory, and `AF_UNIX` caps a socket path at
104 bytes; the platform default `os.tmpdir()` spends about half of that before
Expand Down
2 changes: 1 addition & 1 deletion herdr-plugin.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# is the honest floor rather than a copied one.
id = "memesh"
name = "MeMesh"
version = "4.8.3"
version = "4.8.4"
min_herdr_version = "0.7.0"
description = "Local SQLite memory shared across coding agents — decisions, lessons, and why the code looks the way it does."
platforms = ["linux", "macos", "windows"]
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@pcircle/memesh",
"version": "4.8.3",
"description": "MeMesh \u2014 agentic memory for coding agents. Captured from the agent's real work via hooks, recalled when it acts. One SQLite file, zero cloud required.",
"version": "4.8.4",
"description": "MeMesh agentic memory for coding agents. Captured from the agent's real work via hooks, recalled when it acts. One SQLite file, zero cloud required.",
"main": "dist/index.js",
"type": "module",
"bin": {
Expand Down Expand Up @@ -50,7 +50,8 @@
"check:surface-parity": "node scripts/check-readme-tool-parity.mjs && node scripts/check-codemap-parity.mjs",
"audit:prod": "node scripts/check-consumer-audit.mjs",
"audit:memory": "node scripts/audit/memory-invariants.mjs",
"verify:release": "npm run lint && npm run typecheck && node scripts/check-version-coherence.mjs && node scripts/check-generated-mirror.mjs && node scripts/check-agent-message-sync.mjs && npm run check:surface-parity && node scripts/check-doc-claims.mjs && node scripts/audit/verification-audit.mjs && npm run audit:prod",
"check:entry-points-start": "node scripts/check-entry-points-start.mjs",
"verify:release": "npm run lint && npm run typecheck && node scripts/check-version-coherence.mjs && node scripts/check-generated-mirror.mjs && node scripts/check-agent-message-sync.mjs && npm run check:surface-parity && node scripts/check-doc-claims.mjs && node scripts/audit/verification-audit.mjs && npm run audit:prod && npm run check:entry-points-start",
"release:finish": "node scripts/finish-release.mjs",
"verify:artifact": "npm run verify:release && npm run test:isolated && npm run test:packaged && npm run test:packaged:upgrade",
"prepublishOnly": "npm run build && npm run verify:artifact",
Expand Down
Loading
Loading