Commit Graph

12 Commits

Author SHA1 Message Date
Rohit Ghumare 9c82d2aa7d chore(release): v0.9.29 with project-scope parity across capture surfaces (#1141)
* chore(release): v0.9.29 with project-scope parity across surfaces

Version trio + plugin manifests + supportedVersions + ExportData union
bumped to 0.9.29; CHANGELOG entry covering everything since v0.9.28 with
upgrade notes for the four visible behavior changes.

Fixes the endpoint-count drift on main (130 registered routes vs docs
saying 129 after #1132 landed in parallel with #1136).

Project-scope parity: OpenCode plugin, Hermes plugin, Pi extension, and
JSONL replay now resolve project the same way the hooks do (env
override, git toplevel basename, cwd basename) instead of sending raw
filesystem paths, closing #903 and #1135 and pre-empting the same bug
in pi. The filesystem watcher accepts AGENTMEMORY_PROJECT_NAME with the
old AGENTMEMORY_PROJECT kept as a deprecated alias, replay handles
Windows-recorded paths, and OpenCode file enrichment matches the
agent's lowercase tool names (the capitalized set never matched).

Tests: opencode fallback expectations updated to basenames per the
canonicalization, git-toplevel resolution covered with a fixture repo,
new project-scope-parity suite for replay and fs-watcher.

* fix(release): review findings, git-toplevel parity, doc counts

- skills generator dedupes routes on method plus path, so the REST
  reference lists all 130 registered routes instead of hiding the second
  method on ten dual-method paths (header said 119)
- fs-watcher trims AGENTMEMORY_PROJECT_NAME and the deprecated alias,
  treating whitespace as unset, and derives the git toplevel basename
  when watching a subdirectory
- replay resolves the git toplevel basename when the recorded cwd still
  exists locally (memoized per cwd), keeping the basename fallback for
  historical or cross-platform paths; no env override here since a bulk
  import spans many projects
- parity tests for replay git-root resolution, watcher git-root and
  trim behavior
- stat-tests badge updated from 1428+ to 1550+ passing

* fix(cli): refuse second-instance boot over a live daemon

Closes the class behind issue 1140: agentmemory consolidate (or any
unrecognized word) fell through the command table into the full server
boot, registering a duplicate worker on the running engine; on iii
0.11.2 the second instance's shutdown tears down the daemon's HTTP
trigger routing until a full engine restart. Unknown subcommands now
error with the supported list, and main() probes livez on the resolved
port and refuses to boot over a live daemon, so multi-instance setups
on other ports are unaffected. Verified behaviorally against the built
CLI: both paths refuse with exit 1.

Also from review: the watcher stamps each event with its own root's
project via a per-root map (an explicit config.project still overrides
for every root), and replay only accepts a non-empty string cwd from
parsed JSONL so malformed entries cannot reach the filesystem probe.

* test(watcher): two-repository flush events scope to their own project

* chore(release): bump packages/mcp, guard it, refresh CONTRIBUTING

packages/mcp was still 0.9.28 after the release bump because nothing
guarded it; a consistency test now pins it to package.json. CONTRIBUTING
release list corrected to the files a bump actually touches (no tracked
lockfile, the two extra plugin manifests, the export test derives from
VERSION now), and the subsystems table gains src/cli, integrations/pi,
and the generated-manifest note.

* fix(export): refuse over-frame export instead of dropping the worker

Closes the availability bug in issue 1142: GET /agentmemory/export
assembles the full store and returns it through sdk.trigger, so a store
whose serialized export passes the engine's 16 MiB WebSocket frame
(tungstenite max_frame_size, not raisable under the 0.11.2 pin) dies on
the worker->engine hop, drops the worker, and 404s every endpoint for
~1s. The session collections page on maxSessions/offset but ~18 others
do not, so a large store hits this at any parameter combination.

A shared frame-guard measures the serialized size before returning:
mem::export returns a small oversized error instead of the giant
object, and api::mesh-export returns 413 (same dead-end as #890). Either
way the over-frame payload never crosses the boundary, so the daemon
stays up and the failure is one clean request with a hint to narrow the
range. Full pagination of the non-session collections is a follow-up.

Layer 1 of the fix; verified with a synthetic oversized export returning
the error object (tiny) rather than the payload.

* ci: collapse to a single npm install to fix Node 24/26 CI

The two-step install (npm install --package-lock-only then npm ci) failed
only on the Node 24/26 matrix rows: their stricter npm rejects rolldown's
optional platform bindings (@rolldown/binding-android-arm64) that a
--package-lock-only pass does not fully enumerate. Lockfiles are gitignored,
so npm ci re-validation buys no reproducibility here. A single lenient
npm install resolves and installs in one pass.

* fix(mesh): scope exported memories by project like actions

api::mesh-export filtered actions by ?project but returned every project's
memories. On a mesh instance federating one project to a peer, the peer
pulled other projects' memories (cross-project leak), and those extras could
push the payload past the 16 MiB transport frame into a 413 even when the
requested project's own slice fit. Memories carry the same optional project
field as actions, so filter both before the frame-size guard runs.

Adds a regression test asserting a project-scoped export excludes other
projects' memories and that an oversized memory in another project no longer
413s the scoped request.

* chore(release): credit the Antigravity native hooks adapter in 0.9.29 notes

* chore(release): sweep stale 0.9.28 refs for 0.9.29

Deploy Dockerfiles/compose/render pins, AGENTS.md stats header, opencode
plugin manifest, website meta snapshot, test-count claims (1,428 -> 1,596)
in README/AGENTS/stat SVGs, and the missing 0.9.29 CHANGELOG compare link.

* chore(release): sync stat-tests badge to 1596+ and commit bridge exec bit

* refactor: trim frame-guard comments and drop issue refs from code
2026-08-09 13:22:25 +01:00
Abdullah Alaqeel 8c90741c63 chore(deps): migrate @xenova/transformers to @huggingface/transformers v4 (#1096)
* chore(deps): migrate @xenova/transformers to @huggingface/transformers v4

@xenova/transformers@2.x is deprecated and silently broken on Node 22+
(see #479). The project was renamed to @huggingface/transformers; same
Apache-2.0 license, same code. v4 ships onnxruntime-node/web and sharp
as hard deps, so they're dropped from our optionalDependencies.

Pipeline / RawImage.fromBlob / tolist / text-classification output
shape all unchanged. Three behavior-preserving adjustments needed:

- All 4 pipeline call sites pass { dtype: "q8" }. v4's default on Node
  is fp32 (DEFAULT_DEVICE_DTYPE = "fp32"); v2 defaulted to quantized=true.
  Without explicit dtype, all 4 sites silently regress (~3.5x larger
  download, slower inference). dtype "q8" maps to model_quantized.onnx
  per v4's DEFAULT_DTYPE_SUFFIX_MAPPING; file exists in all 3 Xenova
  models. This was the regression that prompted the test additions below.
- src/providers/embedding/local.ts: split import try/catch from
  pipeline() call so model-load errors (network, missing q8 variant,
  disk) propagate with their actual message, not masked as
  "Install @huggingface/transformers...".
- src/providers/embedding/{local,clip}.ts: type module from
  typeof import("@huggingface/transformers") so PretrainedModelOptions
  flows through; drop hand-rolled aliases and @ts-ignore. Cast at
  assignment sites (pipeline return union isn't structurally assignable
  to our narrow FeatureExtractor / ClipPipeline shapes).

Tests added where coverage was zero (would have caught the dtype
regression):

- test/local-embedding-provider.test.ts (3 tests): unavailable-path
  install hint; pipeline called with dtype:q8 + extractor options +
  mapped Float32Array result; embedBatch shape.
- test/clip-embedding-provider.test.ts (5 tests): unavailable-path;
  text pipeline dtype:q8 + result; embedBatch; embedImage with data:
  URL decode; custom model ID propagation.
- test/reranker.test.ts: positive-path using vi.doMock + resetModules.

Other:
- src/huggingface.d.ts deleted (package ships its own types).
- src/xenova.d.ts removed.
- src/providers/embedding/clip.ts: inline single-use DIMENSIONS constant.
- tsdown.config.ts: trim neverBundle list and comment.
- README.md L1267: BGE-small -> Xenova/all-MiniLM-L6-v2 (was always wrong).
- 16 docs: install commands + prose mentions across main README, 11
  translations, SECURITY.md, 2 benchmark docs, benchmark script.
- Model IDs (Xenova/all-MiniLM-L6-v2, Xenova/clip-vit-base-patch32,
  Xenova/ms-marco-MiniLM-L-6-v2) kept — HF Hub repo names, still valid.

Closes #1095. Fixes #479.

Verified: 1424/1424 tests pass, build clean, tsc clean on migrated files.

* test(embedding): add v4 smoke test, harden import errors, expand CI matrix

Review follow-ups for #1096:
- env-guarded non-mocked smoke test (RUN_HF_SMOKE=1) loading real
  Xenova/all-MiniLM-L6-v2, asserts 384 finite dims; skipped by default
- selective ERR_MODULE_NOT_FOUND handling in local/clip providers so real
  init errors propagate (checks err.code and err.cause.code to handle
  vitest mock-factory wrapping)
- CLIP install hint made embedding-agnostic (loader serves text + image)
- afterEach mock cleanup in doMock-based provider/reranker tests
- CI Node matrix: [20, 22] -> [20, 22, 24, 26] across ubuntu/macos

* refactor(embedding): drop err.cause check, use manual mock for missing-module tests

The .cause branch in the ERR_MODULE_NOT_FOUND check existed only to
accommodate vitest's mock-factory wrapping, not a real Node loader
behavior. Replace it with a manual mock fixture (__mocks__/@huggingface/
transformers.ts) that throws a Node-shaped error at module top-level,
bypassing vitest's factory wrapper so the import rejects with err.code
set directly.

Production code now checks only err.code === 'ERR_MODULE_NOT_FOUND',
matching real Node behavior. Tests verify the same public contract
without coupling production code to the test framework.
2026-07-29 10:21:54 +01:00
Rohit Ghumare 45de643cd2 Detailed, self-updating skills covering the whole system (#854)
* feat(skills): detailed tiered skills covering the whole system

Restructure the 8 action skills into the tiered format (SKILL.md under 100 lines, EXAMPLES.md, shared troubleshooting, anti-patterns, cross-refs) and add 7 reference skills covering MCP tools, REST API, config, connect adapters, hooks, architecture, and skill authoring. Reference data tables are generated from source by scripts/skills/generate.ts and guarded against drift by npm run skills:check in CI, so the docs stay current as the repo changes.

* docs(skills): fix recall REST mapping and label code fences

Correct the recap/handoff REST fallback in _shared/TROUBLESHOOTING.md to POST /agentmemory/smart-search (/agentmemory/recall is not a registered route), and add language identifiers to all opening code fences across the skill docs to satisfy markdownlint MD040.
2026-06-07 18:36:59 +01:00
Rohit Ghumare e9dc710e56 ci: cross-platform matrix + paths-ignore + concurrency (#556)
* ci: cross-platform matrix + paths-ignore + concurrency

1. **OS matrix** — Linux + Windows + macOS, both Node 20 + 22. 6 cells,
   ~3min each, ~18min wall time. Direct test against the class of
   bug #487 caught: hooks crashing on Windows usernames with spaces.
   Pre-merge Linux-only CI meant that bug landed in main + a release.
   fail-fast: false so a flake on one cell doesn't mask whether the
   same failure reproduces elsewhere.

2. **paths-ignore** — skip CI runs on README / CHANGELOG / docs /
   website / assets / .md / .mdx pushes. ~half the runner minutes
   back on doc-only churn. Source / config / workflow changes
   always run.

3. **concurrency + cancel-in-progress** — PR force-pushes cancel
   in-flight runs instead of piling them up. Push to main protected
   (concurrency group still scoped to ref, no cancel for main pushes).

Plus minor hardening: persist-credentials: false on the checkout
step so the GITHUB_TOKEN doesn't land in .git/config.

What was NOT lifted (rationale per plan):
- Per-package reusable workflows (Rust/Python/Homebrew — non-TS).
- License-header check (no per-file Apache banners in agentmemory).
- CLA bot (defer until external PR volume justifies friction).
- tsc --noEmit lint job (codebase has ~10 pre-existing type errors
  tsdown skips; gating CI on those would block every PR until
  fixed; tracked as separate cleanup).
- Smoke test (`agentmemory demo + livez`) — defer to its own PR
  with its own validation cycle.
- Codecov badge — defer until baseline is set.

* ci(windows): force bash shell so build script's POSIX idioms work

Windows runners default to cmd.exe for npm run scripts; the build
script uses POSIX patterns the build script's exit codes
(`cp ... 2>/dev/null || true`, `mkdir -p`) that cmd doesn't
parse. ubuntu + macos already use bash by default so this is
Windows-only behaviour change.

Alternative: rewrite the build script in Node. Bigger lift, not
minimal.

* ci(windows): point npm script-shell at git-bash before build

`shell: bash` on the step only sets the shell for the step's own
runner; `npm run` still spawns its inner script via npm's
`script-shell` config, which defaults to cmd.exe on Windows.

Configure npm to use Git-Bash (preinstalled on GitHub-hosted
Windows runners) so `npm run build` and `npm run test` execute
the build script the same way ubuntu + macos do.

Step is gated on `runner.os == 'Windows'` so it's a no-op on the
other matrix cells.

* ci: drop windows-latest from matrix (obsidian-export hardcoded POSIX paths)

Windows runners fail on test/obsidian-export.test.ts because the
test + src hardcode `/tmp/...` POSIX paths that don't resolve on
the D:\ drive Windows uses. Fixing it cleanly requires reworking
src/functions/obsidian-export.ts to use os.tmpdir() + path.join,
which is a separate scope.

Drop windows from the matrix for now. Ship ubuntu + macos coverage
(real darwin/linux divergence catch) and file a follow-up to make
obsidian-export cross-platform so Windows can be added back.

* test(fs-watcher): bump waits to 1500ms + describe retry for macos fsevents flake
2026-05-20 11:10:46 +01:00
Rohit Ghumare 632fa3531d revert: drop GH Packages mirror, keep single canonical install path (#548)
Reverting the GH Packages publish from #545. GH Packages is a
separate registry from npmjs.com — anyone installing
`@rohitg00/agentmemory` from `npm.pkg.github.com` needs to point
their registry there and authenticate, which is friction users
don't have on the canonical `@agentmemory/agentmemory` install
from public npm.

The right-sidebar Packages widget on the repo page was the only
motivation for the mirror. Acceptable to leave it empty — the
single canonical install path is the better DX.

- Drop `publish-github-packages` job from `.github/workflows/publish.yml`
- Drop `packages: write` perm wording from the workflow comment block
- Remove "GitHub Packages mirror" badge from README

Manual follow-up (post-merge): delete the already-published
`@rohitg00/agentmemory@0.9.20` from GH Packages registry via
github.com/users/rohitg00/packages/npm/agentmemory/settings → Delete.
2026-05-19 18:58:55 +01:00
Rohit Ghumare b4259229a6 feat(repo): add Sponsor button + GH Packages mirror for sidebar surface (#545)
* feat(repo): add Sponsor button + GH Packages mirror for sidebar surface

Three additions that make the repo page surface clearer + give users
a single place to fund the project:

1. `.github/FUNDING.yml` — `github: [rohitg00]` renders the "Sponsor"
   button at the top of the repo + the Sponsor widget in the right
   sidebar. Requires GitHub Sponsors to be enabled at
   github.com/sponsors/accounts on the rohitg00 profile before the
   link resolves (currently 404s — enable before merging this PR).

2. `.github/workflows/publish.yml` — new `publish-github-packages`
   job runs after the existing public-npm publish completes.
   Republishes the main package as `@rohitg00/agentmemory` to
   `npm.pkg.github.com`. The repo's right-sidebar "Packages" widget
   only surfaces packages on GitHub Packages, not packages on the
   public npm registry, so this is what makes the sidebar widget
   non-empty. Public npm remains the canonical install source;
   GH Packages is purely a discovery surface.

   - Uses built-in GITHUB_TOKEN, no new secrets needed.
   - Rewrites package.json `name` + `publishConfig` in-runner via a
     small node one-liner, publishes, then restores the original so
     main isn't permanently scope-changed.
   - Skip-on-already-published guard mirrors the existing public
     publish steps.
   - Marked `|| echo "non-fatal"` so a GH Packages hiccup never blocks
     the canonical npm release.
   - `permissions: packages: write` added at workflow level.

3. README badge row — added `npm downloads`, `GitHub Packages mirror`,
   and `Sponsor rohitg00 on GitHub Sponsors` badges alongside the
   existing `npm version` / `CI` / `License` / `Stars` row. The
   sponsor badge is the same link the FUNDING.yml sidebar widget
   uses; surfacing it in-README means readers who don't notice the
   sidebar still see it.

Out of scope (asked, declined):
- Docker Hub / ghcr.io publish workflow. Not in this PR.

* ci(publish): scope write perms per-job + persist-credentials false

Inline review on #545 flagged that the workflow-level permissions
block granted `id-token: write` + `packages: write` to every job,
including ones that don't need them. Tightened to least-privilege:

- Workflow-level: only `contents: read`.
- `publish` job: adds `id-token: write` (required for `npm publish
  --provenance` to mint a Sigstore OIDC token). The GH Packages
  job doesn't inherit this.
- `publish-github-packages` job: adds `packages: write` (required
  to push to npm.pkg.github.com). The public-npm publish job
  doesn't inherit this.

Both `actions/checkout@v6` calls also pick up `persist-credentials:
false`. The publish steps never push back to the repo, so the
GITHUB_TOKEN doesn't need to land in `.git/config` after checkout.
Same posture both jobs.

Skipped from the same review pass:

- **Pin actions to commit SHAs.** Industry rule but introduces real
  maintenance friction — Renovate/Dependabot don't auto-bump
  SHA-pinned actions to new minors, so SHA pinning trades easy
  semver tracking for stale-action drift. We stay on `@v6` major-tag
  pins (GitHub publishes those via verified moving refs).
- **Disable setup-node cache.** `actions/setup-node@v6` defaults to
  cache-off (the `cache:` input is opt-in). `package-manager-cache`
  only auto-enables when `package.json` has a `packageManager` field
  — agentmemory's doesn't (verified via `grep`). The fix is a no-op
  on this workflow.
2026-05-19 18:28:55 +01:00
Rohit Ghumare eb5f7e6895 chore(deps): bundle 10 Dependabot bumps (claude-agent-sdk 0.3, dotenv 17, vitest 4, ts 6, types/node 25, react 19.2.6, checkout/setup-node v6) (#390)
* chore(deps): bundle 10 Dependabot bumps + README agents grid refresh

Closes the open Dependabot wave in one PR.

Root npm bumps:
- @anthropic-ai/claude-agent-sdk ^0.2.56 → ^0.3.142 (closes #389 group)
- dotenv ^16.4.7 → ^17.4.2 (closes #356)
- @types/node ^22 → ^25.7.0 (closes #357)
- typescript ^5.7 → ^6.0.3 (closes #358)
- vitest ^3 → ^4.1.6 (closes #359)

Website npm bumps:
- @types/node 22.10.2 → ^25.7.0 (closes #354)
- typescript 5.7.2 → ^6.0.3 (closes #353)
- react/react-dom ^19.2.5 → ^19.2.6 (closes #352 group)

github-actions bumps:
- actions/checkout v4 → v6 (closes #351)
- actions/setup-node v4 → v6 (closes #350)

Verified:
- npm run build clean against new TypeScript 6 + vitest 4 stack
- npm test 903 / 903 pass
- website npm run build clean (next 16.2.6 + react 19.2.6 + ts 6 stack
  generates 5 static pages, finalises optimisation)
- No source changes were needed for any breaking-version bump — the
  agent-sdk 0.3.x removal of unstable_v2_createSession etc. is not on
  any path agentmemory exercises (we use query() + the existing
  AgentSDKProvider shape).

Plus README refresh on the Works-with-every-agent grid:
- Added OpenHuman entry (tinyhumansai/openhuman) pointing at the
  recently-landed Memory trait backend (PR tinyhumansai/openhuman#1743)
- Added pi as a native-plugin entry (we already ship
  integrations/pi/security.ts and the plugin file in-tree)
- Reordered the grid so native-plugin agents sit in row 1 and
  MCP-only / REST-only agents sit in row 2
- Updated sub-text on Claude Code / Codex CLI / OpenClaw / Hermes / pi
  to consistently say "native plugin" rather than mixing "plugin",
  "skills", "hooks". Counter on assets/tags/section-agents.svg moved
  from "16 integrations" to "15 integrations" because we dropped the
  meta "Any agent" + "Claude SDK" cells that double-counted REST and
  the AgentSDKProvider path already represented by Claude Code.

* docs(readme): swap pi logo to first-party SVG

Drops the generic GitHub-org avatar for the brand-mark SVG. Lives in
assets/agents/ so the README + future grid renders reach it directly.
2026-05-15 11:03:36 +01:00
Rohit Ghumare fab246a3fd ci: two-step install so npm ci has a lockfile on this branch 2026-04-22 11:22:47 +01:00
Rohit Ghumare 3ed85ffaec ci(publish): add @agentmemory/fs-watcher to the release workflow
Ships the new filesystem connector to npm on every release.
Also adds workflow_dispatch so we can manually publish packages
without cutting a release — useful for back-filling fs-watcher
against v0.9.0 which merged before the workflow knew about it.
2026-04-18 20:04:21 +01:00
Rohit Ghumare 416fa15af4 chore: release 0.8.6 — scope the MCP shim as @agentmemory/mcp (#134)
0.8.5's publish workflow got blocked on the unscoped `agentmemory-mcp`
name by npm's name-similarity policy (there's an unrelated third-party
package called `agent-memory-mcp`). Publishing the shim under the
`@agentmemory` scope we already own sidesteps the conflict.

Changes:
- Rename packages/agentmemory-mcp → packages/mcp
- Package name: agentmemory-mcp → @agentmemory/mcp (0.8.4 → 0.8.6)
- Keep bin name `agentmemory-mcp` so `npm i -g @agentmemory/mcp`
  still installs a binary at `agentmemory-mcp` for muscle memory
- Log prefix [agentmemory-mcp] → [@agentmemory/mcp] in standalone.ts
  and in-memory-kv.ts
- README / integrations/openclaw / integrations/hermes / src/cli.ts
  all point at `npx -y @agentmemory/mcp`
- .github/workflows/publish.yml working-directory and npm view queries
  target packages/mcp and @agentmemory/mcp
- Shim dependency on @agentmemory/agentmemory bumped to ~0.8.6
- Main package 0.8.5 → 0.8.6 across the 8 version files
- CHANGELOG [0.8.6] entry documenting the scope move
2026-04-14 00:31:10 +01:00
Rohit Ghumare 8a36fe7867 fix: retention scoring (#119) + npx agentmemory-mcp 404 (#120), release 0.8.3 (#123)
* fix: retention scoring (#119) + npx agentmemory-mcp 404 (#120), release 0.8.3

Issue #119 — retention score ignored agent-side reads

`mem::retention-score` previously hardcoded `accessCount=0` and
`accessTimestamps=[]` for episodic memories and used only a single-sample
`lastAccessedAt` for semantic memories, so the time-frequency decay
formula was a dead path. All read endpoints now record access events to
a new `mem:access` KV namespace via a keyed-mutex'd access tracker:

  - mem::search, mem::smart-search (compact + expand), mem::context,
    mem::timeline, mem::file-context, mem::get-related, mem::working-context
  - retention.ts pre-fetches the full access log in one kv.list call,
    normalizes every row defensively, and builds an O(1) lookup Map
  - recordAccessBatch uses Promise.allSettled so a slow keyed-lock on one
    id does not block the rest of the batch
  - Bounded ring buffer of the last 20 access timestamps per memory
  - Backwards-compat fallback: pre-0.8.3 semantic memories with only the
    legacy sem.lastAccessedAt still score correctly
  - Corrupt lastAccessedAt values are NaN-safe via Date.parse + isFinite
  - reinforcementBoost is reported as the raw formula output, not the
    clamped residual

Memory deletion sites (retention-evict, evict, auto-forget,
governance-delete, governance-bulk, forget, import replace) now call
deleteAccessLog to prevent mem:access from accumulating zombie entries.
mem::export / mem::import and mem::snapshot-create / mem::snapshot-restore
round-trip the new namespace so backup/restore cycles no longer zero out
reinforcement signals.

Issue #120 — npx agentmemory-mcp returned npm registry 404

The README instructed users to run `npx agentmemory-mcp`, but
`agentmemory-mcp` only existed as a `bin` entry inside
`@agentmemory/agentmemory`, not a real registry package. Two-part fix:

  - New sibling package `packages/agentmemory-mcp/` — a thin shim that
    depends on `@agentmemory/agentmemory` (~0.8.3, tilde to block 0.9.x
    supply-chain drift) and forwards to dist/standalone.mjs via the new
    `exports` field on the main package
  - Canonical `npx @agentmemory/agentmemory mcp` subcommand on the CLI
    for users who already have the main package installed
  - Removed the dead `agentmemory-mcp` bin from the main package so the
    shim owns the name unambiguously
  - publish.yml publishes both packages in order with idempotent
    guards and npm-view registry polling (no more fixed sleep)
  - All MCP install snippets in README + integrations/openclaw + hermes
    + shim README use `npx -y agentmemory-mcp` to skip install prompts

Release 0.8.3

  - 670 tests passing (665 + 11 new: access tracker, retention,
    smart-search integration, corrupt-input, kv.list failure path,
    Promise.allSettled resilience)
  - Version bumped across package.json, src/version.ts, types.ts,
    export-import supportedVersions, plugin.json
  - package-lock.json regenerated

* fix: address CodeRabbit review feedback on #123

Real issues caught and fixed:

- access-tracker: deleteAccessLog now takes the same mem:access:<id>
  keyed mutex used by recordAccess, eliminating the race where a
  concurrent delete could drop an in-flight RMW update and leave a
  stale access log for an evicted memory
- access-tracker: normalizeAccessLog now coerces count to a
  non-negative integer, drops non-finite recent[] entries, truncates
  recent[] to the last 20 on read (enforcing the ring-buffer invariant),
  and guarantees count >= recent.length so a malformed row can't produce
  NaN downstream. count is NOT capped at 20 — it is the lifetime access
  counter, while recent[] is the 20-entry window
- export-import: import path now rejects accessLogs arrays above
  MAX_ACCESS_LOGS (50_000), normalizes each entry via
  normalizeAccessLog, and drops entries whose memoryId is not in the
  imported memories set, so a crafted export can't blow up memory or
  resurrect zombie access rows for memories that don't exist
- publish.yml: added a post-publish npm view polling loop for
  agentmemory-mcp mirroring the one that already guards the main
  package, so the workflow only succeeds when `npx agentmemory-mcp` is
  actually visible on the registry
- CHANGELOG.md: added the missing [0.8.3] reference-style link target
  at the bottom to match the [0.8.2]/[0.8.1]/[0.8.0] pattern
- README.md: standalone MCP inline examples now use `npx -y` to match
  the MCP config snippets and skip the install confirmation prompt

Tests: 680/680 (+10 new — deleteAccessLog behavior, normalizeAccessLog
invariants, malformed mem:access row handling in retention scoring).

Findings deliberately not applied:

- auto-forget.ts / remember.ts / evict.ts recordAudit calls: existing
  pattern in the codebase only audits governance deletes (user-initiated
  admin actions), not automatic eviction. Adding audit everywhere is a
  policy change, out of scope for this PR
- evict.ts gating deleteAccessLog on memory delete success: current
  order is defensible, deleteAccessLog is already best-effort with its
  own try/catch, and calling it after a failed memory delete is harmless
- snapshot.ts fail-fast on kv.list failure: inconsistent with the
  existing .catch(() => []) pattern used for observations in the same
  function
- retention.ts semantic evict only deletes KV.memories rows: real bug
  but pre-existing on main (RetentionScore has no source/type field).
  Tracked separately — out of scope for this PR
- bin.mjs fallback command: already present in the existing catch
  handler
- Promise.all parallelization of delete+deleteAccessLog: micro
  optimization not worth the readability cost
2026-04-13 12:05:18 +01:00
Rohit Ghumare e8f410b537 feat: v0.7.0 — lessons, tool visibility, auto-consolidation, obsidian export, npx bootstrap (#82)
* feat: v0.7.0 — lessons, tool visibility, auto-consolidation, obsidian export, npx bootstrap

Five DX improvements based on competitive research against Mem0, Engram, CodeMem:

1. `npx agentmemory` zero-config startup
   - New CLI bootstrap (src/cli.ts) auto-detects and starts iii-engine
   - Tries `iii` binary first, falls back to `docker compose up -d`
   - Bundles iii-config.yaml and docker-compose.yml in dist/

2. Simplified MCP tool surface (7 core tools by default)
   - AGENTMEMORY_TOOLS=all unlocks all 49 tools
   - Default: save, recall, consolidate, forget, sessions, diagnose, lesson_save
   - Call handler remains unfiltered — any tool callable by name

3. Auto-consolidation on session end
   - CONSOLIDATION_ENABLED defaults to true (was false)
   - Session-end hook: session/end → crystallize → consolidate → bridge sync
   - Consolidation pipeline always registered (timer gated by config)

4. First-class lesson memory type with confidence decay
   - Lesson interface: confidence (0-1), reinforcements, decayRate, source
   - 5 functions: lesson-save, lesson-recall, lesson-list, lesson-strengthen, lesson-decay-sweep
   - Dedup via SHA-256 fingerprint — duplicate saves strengthen existing
   - Crystal lessons auto-flow into lesson system at confidence 0.6
   - Daily decay sweep with parallel KV writes

5. Obsidian-compatible Markdown export
   - Export to ~/.agentmemory/vault/ with YAML frontmatter + wikilinks
   - MOC.md (Map of Content) index file
   - Parallel KV reads, auto-export via OBSIDIAN_AUTO_EXPORT=true

Stats: 49 MCP tools, 99 REST endpoints, 573 tests passing

* docs: add AGENTS.md, fix tool/endpoint counts across README, plugin, cli

- Create AGENTS.md with strict consistency rules for MCP tools, REST
  endpoints, versions, KV scopes, and audit operations
- Fix MCP tool count: 38 → 41 across README.md (4 occurrences)
- Fix REST endpoint count: 93/95 → 99 across README.md and index.ts
- Fix plugin.json: version 0.6.1 → 0.7.0, tool count 5 → 41
- Fix cli.ts help text: 48+ → 41 MCP tools
- Fix README api.ts path reference → triggers/api.ts

* fix: address code review findings — consolidation guard, decay bug, async fs, export-import lessons

Inline fixes:
- Revert CONSOLIDATION_ENABLED to opt-in (=== "true"), matching original behavior
- Add early-exit guard in consolidation-pipeline handler when disabled
- Gate session-end crystallize+consolidation calls on CONSOLIDATION_ENABLED
- Fix lesson decay over-decay bug: add lastDecayedAt to Lesson, compute
  incremental delta instead of reapplying full age every sweep run
- Add LESSON_DECAY_ENABLED flag (default true) to gate the sweep timer

Outside diff fixes:
- Add lessons to export-import (export + import + replace cleanup)
- Log warning instead of swallowing obsidian auto-export errors

Nitpick fixes:
- Switch obsidian-export to async fs/promises (mkdir, writeFile)
- Add per-item try/catch in obsidian-export, return errors array
- Replace governance_delete with smart_search in ESSENTIAL_TOOLS (non-destructive default)
- Fix CLI whichBinary for Windows (uses "where" on win32)
- Use dynamic port in CLI error message instead of hardcoded 3111
- Return 201 for newly created lessons, 200 for strengthened
- Wrap lesson audit calls in try/catch so audit failure doesn't surface
- Fix build script to not swallow tsdown failure
- Remove exact tool count from test, use >=41 + uniqueness + required names
- Add test/consistency.test.ts: validates version, tool count, README consistency
- Add isConsolidationEnabled mock to consolidation-pipeline test

579 tests passing (573 original + 6 new consistency checks)

* fix: guard remaining audit calls, correct endpoint count, add CI + npm publish

Review fixes:
- Wrap lesson_recall and lesson_strengthen audit calls in try/catch
- Fix REST endpoint count: 99 → 100 (verified via grep) across index.ts,
  README.md, and AGENTS.md
- Use regex in consistency test for README assertions (flexible phrasing)
- Add consolidation gate tests: disabled returns early, force=true bypasses

CI/CD:
- Add .github/workflows/ci.yml — test on Node 18/20/22
- Add .github/workflows/publish.yml — auto-publish to npm on GitHub release
  (uses NPM_TOKEN secret + provenance)

Nitpick:
- Single-char term filter (t.length > 1) kept intentionally — prevents noise
  from single-letter matches; documented in AGENTS.md if needed

581 tests passing

* fix(ci): add --legacy-peer-deps for zod v3/v4 peer conflict

@anthropic-ai/claude-agent-sdk@0.2.56 requires zod@^4.0.0 as a peer
dependency but the project uses zod@^3.23.0. The lock file resolves
this locally but npm ci is strict about peer deps in CI.

* fix(ci): drop Node 18 from matrix — tsdown requires Node 20+

tsdown/rolldown uses node:util.styleText which is only available in
Node 20.12+. Updated engines field to >=20.0.0 to match.

* fix(ci): add inlineOnly: false to tsdown config, target node20

tsdown errors on CI with "Consider adding inlineOnly option" when
dependencies are bundled. Setting inlineOnly: false suppresses this.
Also updated target from node18 to node20 to match engines field.
2026-04-04 17:57:01 +01:00