All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Mastra is now a first-class Hermes memory provider. Memory reads, writes, recall, observation, telemetry, and runtime status route through the plugin while preserving local fallback behavior. Adds live integration, parity, latency, profile-isolation, redaction, observability, and end-to-end regression coverage.
- Nested skill layout (
skills/mastra/) mirroring the design-craft layout, plus rootpackage.jsonmetadata for skills.sh discovery, with docs/tests updated for the nested path and Google embedding credentials mapped to the env vars current Mastra source expects.
- Discovery-loader namespace import.
hermes doctor/memory status/hermes pluginsno longer report the provider as "not found" / "activate via config" whenmemory.provider: mastrais set. The plugin now prepends its own directory tosys.pathso absolute-import fallbacks resolve under the loader's synthetic_hermes_user_memory.<name>namespace — no host package edits. Hardens the end-to-end smoke test to pinHERMES_HOME. - Context-engine compression threshold. The Mastra
ContextEnginewrapper now honors the host'scompression.thresholdinstead of falling back to the 0.50 default, so a 272K-window model compacts at the configured fraction (e.g. 0.90 → 244,800 tokens) rather than 136,000. Failure-isolated: any config read error leaves the delegate default untouched.
0.2.2 - 2026-05-06
- Thorough
./README.mdrefresh. Reconciles every section with the shipped code (provider hooks, tools, CLI, config surface, mise tasks); adds an explicit "Resilience guarantees" section enumerating every promise; documents every new resilience config knob and the newmise run chaos/mise run bench:resiliencetasks; refreshes the install block to matchplugin.yamlv0.2.2; embeds the latest measured benchmark numbers. - Resilience layer. Added fail-closed
CircuitBreaker, stdlib response guards, bounded observation deduplication, profile/thread LRU recall cache, server-supervisor restart policy, filesystem-safe write helpers, and cron/partial-init no-op paths. - Fault-injection gates. Added the resilience RED suite plus
tests/test_chaos_resilience.py,mise run chaos, andmise run bench:resilience. - Server hard-fail boundary. Bun now declares
idleTimeout, a structurederrorhandler, and/api/memory/healthzprobe data.
MastraClientnow validates response payloads before use, rotates auth on 401 fromauth_token_env, deduplicates repeated observations, and runs HTTP calls through the circuit breaker.- Capacity hints now recommend
mastra_observeonly when built-in memory is >=50% and observations are below the action floor; explicit recall phrasing with an empty cache recommendsmastra_search. references/last-benchmark.{json,md}now includes fault-injected resilience numbers.plugin.yamlbumped to0.2.2;/healthroute inserver/src/routes-memory.tsreports the same version.
mise run test:pypasses (648 tests).mise run chaospasses.mise run bench:resiliencepasses with fault-injected hot-path p99 0.03 ms and 0 escaped hook failures.mise run compat:hermesandmise run compat:mastrapass against cached upstream sources.
0.2.1 - 2026-05-05
- Import context bug under the real Hermes loader.
server_manager.pyandserver_process.pyused bare absolute imports (from server_config import …) that worked under pytest (becauseconftest.pyadds the plugin root tosys.path) but raisedModuleNotFoundErrorunder Hermes' actual loader, which loads the plugin asplugins.memory.mastra.<module>. The downstream effect was silent:is_available()swallowed theImportErrorand returnedFalse, so the plugin appeared healthy in tests yet refused to activate at runtime. Fixed by wrapping the sibling imports in thetry: from .X import …; except ImportError: from X import …pattern already used by every other module in this codebase. Caught by manual smoke testing v0.2.0 on a clean install — seescripts/manual-smoke.sh.
tests/test_hermes_loader_imports.py(5 tests) — RED-then-GREEN regression guard for the import-context bug. Every assertion runs in a fresh subprocess that simulates the Hermes loader (syntheticplugins.memory.mastrapackage via symlink, plugin root NOT onsys.path) so in-process state can never leak into the rest of the suite. Includes a smoke test that callsplugins.memory.load_memory_provider('mastra')through Hermes' actual venv.scripts/manual-smoke.sh— one-shot 9-phase manual smoke test: pre-flight → sync → activate → server bring-up → tool surface → round-trip → tenant isolation → in-process hook roundtrip with 100 ms budget enforcement → tear-down. Distinct exit codes per phase (2=preflight, 3=server, 4=load, 5=tenant-leak, 6=budget) for CI integration.
- All 9 smoke phases pass against a freshly-installed plugin: every hot-path hook returns in < 0.1 ms (
system_prompt_block0.03 ms ·prefetch0.07 ms ·sync_turn/on_session_switch/on_pre_compress/on_memory_writeall 0.01 ms). - Tenant isolation verified end-to-end on a live Bun server: writes to
hermes:smoke-defaultandhermes:smoke-otherstayed in their own resourceIds; cross-profile keyword search returned 0 hits; working-memory values per profile remained distinct. No leakage at any boundary. mise run qualitypasses (560 tests, format · lint · typecheck · security:audit · validate).
0.2.0 - 2026-05-05
tests/test_plugin_clash.py(18 tests) — locks namespace ownership for every plugin-owned resource: plugin id, provider name, tool prefix (mastra_*), env vars (MASTRA_*), LibSQL store id (hermes-mastra), resource id format (hermes:<profile>), recall-cache instance scoping, async-runner thread names, logger names, and a no-monkey-patch guard.tests/test_plugin_non_interference.py(8 tests) — proves coexistence with arbitrary contract-valid Hermes plugins: hook callbacks never mutate kwargs, lifecycle events propagate to other plugins, foreign storage namespaces are untouched, no command/tool collisions.tests/test_plugin_load_order_permutations.py(54 parametrized cases) — proves load-order invariance across every permutation of{mastra, observer, command, lifecycle}registrars.tests/test_plugin_failure_isolation.py(7 tests) — proves failures are contained in both directions: our hooks never propagate exceptions; foreign plugin failures don't block our callbacks.tests/test_retrieval_relevance.py(8 tests) — proves prefetch returns empty when cache is empty, announces the active profile, clears stale cache on session-id mismatch, on profile flip, and onreset=True, and writes lineage observations on session continuation.tests/helpers/fake_plugins.py— in-test fakes (install_observer_plugin,install_command_plugin,install_failing_plugin,install_storage_writer,install_lifecycle_plugin) emulate real Hermes plugin behaviours without shipping production-mock code.
source-analysis.md— Hermes + Mastra primitives, lifecycle diagrams, performance-sensitive paths, risks/unknowns/disconfirming evidence.local-ci.md— canonical local CI/CD command surface (mise run quality).plugin-contract.md— 17-section operational plugin contract derived from Hermes source.plugin-clash-analysis.md— 24-resource collision matrix with per-resource owner, namespace, risk, prevention strategy, and test coverage.plugin-compatibility-matrix.yaml— 8 compatible plugins, 6 mutually-exclusive memory peers, explicitunknown_plugins_policy.memory-performance-plan.md— read/write paths, ranking, compaction, isolation, caching, instrumentation, rollout, risks, acceptance criteria.tdd-task-list.yaml— dynamic BOOTSTRAP/RED/GREEN/REFACTOR task ledger.research/firecrawl-url-map.yaml— relevance-classified URL inventory across 5 documentation roots (Hermes docs + Mastra docs/reference/models/guides), each mapped atlimit=5000.research/{hermes,mastra}-docs-knowledge.yaml— extracted findings tagged by source-classification (primary_source_claim/secondary_source_claim/source_inference/implementation_inference/common_knowledge).research/memory-integration-findings.md— where Hermes and Mastra contracts agree, disagree, and how the boundary is reconciled.final-report.md— summary, evidence, tests added, CI commands run, performance measurements, behaviour validated, files changed, risks/unknowns, counter-arguments, per-conclusion confidence, and the 30-row acceptance-criteria checklist.
references/mastra-reference-map.json(323 links),references/mastra-models-map.json(128),references/mastra-guides-map.json(63) — Firecrawl/v1/mapsnapshots atlimit=5000, complementing the existingmastra-docs-map.jsonandhermes-docs-map.json.
references/last-benchmark.{json,md}— refreshed; every hot-path hook returns under 0.2 ms p99 even with 500 ms simulated HTTP latency. Background queue throughput 16,376 jobs/sec sustained; 93 % cache hit rate over a 200-turn loop.
mise run qualitypasses (format · lint · typecheck · 552 tests · security:audit · validate).mise run compatconfirms all 16 HermesMemoryProviderhooks and all 8 used@mastra/memoryAPIs are present in upstream HEAD.- Every new test file respects the 200 LOC / 30 LOC-per-construct / depth-3 code-size policy (200/200 policy checks pass).
- Zero changes to production Python or TypeScript source — the plugin's existing
0.1.0implementation already met every contract; the upgrade is delivered as enforceable regression-guard tests.
0.1.0 - 2025-05-03
- mastra_recall — Retrieve stored memories for the active profile using Mastra's memory provider.
- mastra_search — Keyword-based search across profile-isolated memory entries.
- mastra_semantic_search — Vector / semantic search over embedded memory content via Mastra.
- mastra_observe — Trigger an observation cycle that feeds into the Observer/Reflector pipeline.
- mastra_working_memory — Read and write short-lived working-memory slots scoped to the current session.
- mastra_artifact_get — Fetch a named artifact (identity file, prompt block, etc.) by ID.
- mastra_artifact_history — Retrieve the full version history of a stored artifact.
- mastra_artifact_revert — Revert an artifact to a prior version from its history.
- All memory, artifact, and working-memory data is isolated per profile using libSQL as the backing store.
- Each profile receives its own namespace, preventing cross-profile data leakage.
- Observer role watches agent interactions and extracts salient facts, decisions, and context into memory.
- Reflector role periodically reviews accumulated observations, consolidating and pruning memory to maintain relevance.
- Hooks execute under a strict 5-second deadline.
- Hook results are returned asynchronously so the host agent loop is never blocked by a slow provider.
- When stored memory or artifact volume exceeds 50% of the configured capacity, the system automatically injects hints into the agent's system prompt encouraging consolidation or archival.
- Identity files are stored as versioned Mastra prompt-blocks, enabling deterministic retrieval of any prior version and safe atomic updates.
- A drop-in
ContextEnginewrapper is provided that transparently routes memory operations through Mastra when the plugin is installed, while falling back to the built-in engine otherwise.
- Production-ready Bun server exposing 17 routes for tool invocations, health checks, profile management, artifact CRUD, and memory queries.
- Automated policy checks reject PRs or builds that exceed the configured code-size budget, keeping the plugin lightweight.
- 425+ tests covering tool contracts, isolation boundaries, hook deadlines, capacity hints, artifact versioning, server routes, and the ContextEngine wrapper.