Skip to content

Release/v2.38.0 - #138

Merged
Lyellr88 merged 4 commits into
MARM-mainfrom
release/v2.38.0
Aug 10, 2026
Merged

Release/v2.38.0#138
Lyellr88 merged 4 commits into
MARM-mainfrom
release/v2.38.0

Conversation

@Lyellr88

@Lyellr88 Lyellr88 commented Aug 10, 2026

Copy link
Copy Markdown
Owner

v2.38.0 strengthens MARM’s internal reliability without changing its MCP tools, parameters, stored data, or HTTP/STDIO behavior.

  • Mypy now checks all 110 server modules, with a strict baseline that prevents new type errors from landing unnoticed.

  • Core contracts were tightened across memory storage, recall, embeddings, compaction, queues, graph coordination, FastAPI paths, and CLI services.

  • The encoder now accurately distinguishes single-text and batch embedding results, while migration and rechunking continue to support injected test encoders.

  • Ruff is now the single formatter/linter used locally and in CI; conflicting Black, isort, and Flake8 dependencies were removed.

  • Full validation passed: 1,078 tests, server.json validation, Mypy gate, and v2.38.0 wheel/sdist build.

Two known graph-shutdown race findings remain deliberately visible in the Mypy baseline and are documented for a dedicated lifecycle fix rather than suppressed in this type-safety release.

Summary by CodeRabbit

  • New Features

    • Added an engine pre-flight step to setup instructions, including detection or installation before protocol loading.
    • Improved notebook synchronization handling for pending or failed updates, including reuse of existing memory links.
  • Documentation

    • Updated installation, setup, and changelog documentation for version 2.38.0.
    • Clarified transport selection, runtime configuration, linking, handoff, and edge-case procedures.
  • Chores

    • Expanded type checking across the server package and reduced the tracked error baseline.
    • Standardized formatting and linting around Ruff.

Lyellr88 and others added 3 commits August 9, 2026 06:50
The typecheck gate covered marm_mcp_server/core/ only, so two thirds of the
package could accumulate type errors unnoticed, and it had already gone red at
115 against a baseline of 113. Widening the scope to the whole package found 93
more errors and, more usefully, both ends of the same defects: an implicit
Optional parameter counted once inside core/ while every caller honestly passing
None to it went unreported.

208 errors at the new scope, now 155.

Scope and reporting:
- TARGET is the whole package. Two reporting bugs had to be fixed first or the
  wider scope would have misreported: per-file counts keyed on basename merged
  the nine names that repeat across subpackages (memory.py, concepts.py,
  models.py, cli.py, ...), and the clean-file count used a non-recursive glob.

Cleared:
- types-psutil for real stubs, plus per-library ignore_missing_imports for the
  three packages that ship no py.typed and have no stubs. Named one library at a
  time so a mistyped MARM import still errors, verified with a probe.
- 19 implicit Optional signatures and the 10 caller-side arg-type errors they
  caused. No new errors surfaced inside those bodies, so the signatures were
  wrong and the code was already correct.
- _classify_chunk declared Optional[str] but cannot return None on either path,
  which its own docstring and tests already asserted.
- Three separate errors traced to one variable name serving two unrelated
  purposes, where the first assignment fixed a type the second use inherited.

Left visible:
- endpoints/graph.py:179, a narrow check-then-use race on get_client() during
  shutdown. It is a 500 instead of the usual unavailable payload, with no stuck
  lease and no effect on core memory. All 13 call sites share it; the other 12
  are invisible only because CbmClient resolves to Any. Suppressing it here would
  claim a safety it does not have. See docs/current/graph-client-none-guard.md.

No behavior change and no version bump. 1077 tests pass, unchanged before and
after. Latest tag v2.37.0 is released, so the unreleased minor gap is 0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Continues the typing pass from a89fe95: 155 errors down to 78. Everything here
was already implied by the code or already unused by the toolchain, so no
behavior changes and no design decisions.

Connection plumbing, which cascaded further than expected:
- memory_db.py's pool and ConnectionContext are typed end to end, including
  __enter__ -> sqlite3.Connection. That only works with the pool's own
  get_connection typed too, otherwise a no-untyped-def just becomes a
  no-any-return. self.conn needed sqlite3.Connection | None for __enter__ to
  narrow. That file went 11 errors to 3.
- 14 conn parameters and the 3 get_connection methods. Annotating the boundary
  cleared several no-any-return errors on its own, since a typed conn makes
  cursor.rowcount an int rather than Any.

Signatures:
- 21 functions given -> None, and the 4 middleware given
  call_next: RequestResponseEndpoint with -> Response.
- The 3 lifespan functions are AsyncIterator[None], not None. A first pass
  looked for "no return with a value" and would have mislabeled all three,
  since a generator has no return statement at all.
- 24 return types that were mechanically determinable from their own return
  expressions, applied by function name so a shifted line could not mis-target.

One real finding, from a body mypy had been skipping: protocol_injection reads
response.body_iterator, which starlette's declared Response type does not carry.
BaseHTTPMiddleware actually returns a private _StreamingResponse. The code is
correct and starlette's hint is too narrow, so this is an ignore with the reason
rather than a cast that would misstate the object's identity.

Toolchain:
- Removed black, isort, and flake8 from dev deps, their pyproject config, and
  the publish workflow's install line. None were invoked by any workflow. black
  wanted to reformat 13 files against ruff format, producing worse output on
  comprehensions containing triple-quoted strings, and flake8's 1,136 findings
  were E501 against its own 79-char default plus E203, which is knowingly
  incompatible with black-style slices. Satisfying either would have moved code
  away from what CI enforces.
- Import order was checked and left alone: 108 I001 findings are cosmetic, and
  ruff correctly leaves server_stdio.py alone, where imports sit after a
  builtins.print patch that must run first so stdout stays a clean JSON-RPC
  channel.

1078 tests pass. ruff check, ruff format, and the typecheck gate are clean at
baseline 78. Latest tag v2.37.0 is released, so the unreleased minor gap is 0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Expand Mypy coverage across the server package, strengthen internal contracts, and standardize Ruff validation in CI.\n\nDocument the release, align v2.38.0 metadata, and preserve the two graph lifecycle findings as an explicit follow-up rather than suppressing them.
@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Changes

The release updates version references to 2.38.0, replaces legacy formatting tools with Ruff, expands Mypy coverage, strengthens type annotations across the server, core, services, and utilities, and improves document-to-memory mirror retry behavior.

Release, tooling, and typecheck coverage

Layer / File(s) Summary
Release metadata and tooling
.github/workflows/*, AGENTS.md, CHANGELOG.md, docs/*, marm-mcp-server/pyproject.toml, marm-mcp-server/server.json, scripts/typecheck.py
Version references move to 2.38.0. Black, isort, and flake8 are removed. Ruff is pinned. Mypy checks the full package with a baseline of two errors.
Application and core type contracts
marm-mcp-server/marm_mcp_server/{cli.py,console,core,endpoints,middleware,server*.py}
Functions, middleware, database access, memory recall, queues, lifecycle handlers, and endpoint results receive explicit types, overloads, protocols, and sentinel handling.
Utility and notebook synchronization
marm-mcp-server/marm_mcp_server/{services,utils}/*, marm-mcp-server/tests/test_notebook_service.py
Encoder contracts and utility values are typed. Document mirroring reports pending link failures and reuses orphaned mirrors on retry.
Installer documentation
skills/marm-init/SKILL.md, marm-mcp-server/marm_mcp_server/resources/skills/marm-init/SKILL.md
The installer instructions add runtime pre-flight steps and reformat setup, transport, handoff, and edge-case guidance.

Estimated code review effort: 3 (Moderate) | ~30 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 7

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/publish-mcp.yml:
- Line 59: Update the release workflow’s dependency installation and typecheck
gate around scripts/typecheck.py to pin mypy to the baseline’s exact version and
include the exact validation scripts, configuration, and versioned inputs used
to establish BASELINE = 2. Ensure the release check runs against those pinned
inputs rather than unversioned or drifting tooling.

In `@marm-mcp-server/marm_mcp_server/core/consolidation.py`:
- Around line 45-46: Reorder the union members in the affected annotations of
the consolidation function so None is the final member, including project and
platform at both declaration sites. Preserve the existing types and _Unset
defaults; only adjust the union ordering to satisfy Ruff RUF036.

In `@marm-mcp-server/marm_mcp_server/services/notebook.py`:
- Around line 277-279: Update _save so a failure from docs_db.set_memory_id
after memory.store_doc_mirror does not leave synchronization unreconciled: catch
the update failure, persist a durable idempotent reconciliation record keyed by
doc_id, and report mirror_status as "pending". Ensure reconciliation retries
safely under concurrent saves and SQLite transactions, and only mark the mirror
synchronized after the docs row update succeeds.

In `@marm-mcp-server/pyproject.toml`:
- Line 7: Align all release metadata with the chosen version and add the
corresponding changelog entry: update marm-mcp-server/pyproject.toml:7, both
version references in marm-mcp-server/server.json:6 and 20-25, and
marm-mcp-server/marm_mcp_server/server.py:8-9 consistently, then add a
CHANGELOG.md release entry for that same version before release.

In `@scripts/typecheck.py`:
- Line 28: Align the type-error baseline behavior with its documentation: update
the gate around BASELINE in scripts/typecheck.py to compare against a snapshot
or per-file baseline so replacements are rejected, or remove the claim that
every new type error fails from CHANGELOG.md lines 8-9. Apply the chosen
correction at the corresponding site; no other changes are required.

In `@skills/marm-init/SKILL.md`:
- Around line 46-47: Pin both installer artifacts to immutable releases in
skills/marm-init/SKILL.md lines 46-47 and
marm-mcp-server/marm_mcp_server/resources/skills/marm-init/SKILL.md lines 46-47:
replace the unversioned pip package with a fixed marm-mcp-server version and
replace the Docker image’s latest tag with a fixed release tag or digest,
keeping both copies consistent.
- Around line 57-60: The protocol fetch path in skills/marm-init/SKILL.md lines
57-60 and marm-mcp-server/marm_mcp_server/resources/skills/marm-init/SKILL.md
lines 57-60 must validate the remote source before using its content or
fallbacks. Add a checksum or pinned-commit verification for the PROTOCOL.md
source, and only execute or continue with fetched content when validation
succeeds; apply the same change to both copies.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 5cc9cdd6-2a9d-4704-bdee-5c769c70da93

📥 Commits

Reviewing files that changed from the base of the PR and between 6b24b55 and 69c74ba.

📒 Files selected for processing (67)
  • .github/workflows/publish-mcp.yml
  • AGENTS.md
  • CHANGELOG.md
  • docs/INSTALL-LINUX.md
  • docs/INSTALL-WINDOWS.md
  • marm-mcp-server/Dockerfile
  • marm-mcp-server/docker-compose.yml
  • marm-mcp-server/marm_mcp_server/__init__.py
  • marm-mcp-server/marm_mcp_server/cli.py
  • marm-mcp-server/marm_mcp_server/config/settings.py
  • marm-mcp-server/marm_mcp_server/console/app.py
  • marm-mcp-server/marm_mcp_server/console/cli.py
  • marm-mcp-server/marm_mcp_server/console/endpoints/concepts.py
  • marm-mcp-server/marm_mcp_server/core/compaction.py
  • marm-mcp-server/marm_mcp_server/core/compaction_scheduler.py
  • marm-mcp-server/marm_mcp_server/core/concept_db.py
  • marm-mcp-server/marm_mcp_server/core/concept_extraction.py
  • marm-mcp-server/marm_mcp_server/core/consolidation.py
  • marm-mcp-server/marm_mcp_server/core/docs_db.py
  • marm-mcp-server/marm_mcp_server/core/events.py
  • marm-mcp-server/marm_mcp_server/core/graph_index_lock.py
  • marm-mcp-server/marm_mcp_server/core/graph_index_worker.py
  • marm-mcp-server/marm_mcp_server/core/memory.py
  • marm-mcp-server/marm_mcp_server/core/memory_db.py
  • marm-mcp-server/marm_mcp_server/core/memory_delete.py
  • marm-mcp-server/marm_mcp_server/core/memory_ops.py
  • marm-mcp-server/marm_mcp_server/core/memory_recall.py
  • marm-mcp-server/marm_mcp_server/core/memory_scoring.py
  • marm-mcp-server/marm_mcp_server/core/memory_utils.py
  • marm-mcp-server/marm_mcp_server/core/models.py
  • marm-mcp-server/marm_mcp_server/core/rate_limiter.py
  • marm-mcp-server/marm_mcp_server/core/response_limiter.py
  • marm-mcp-server/marm_mcp_server/core/runtime_manager.py
  • marm-mcp-server/marm_mcp_server/core/shutdown_manager.py
  • marm-mcp-server/marm_mcp_server/core/stdio_tool_lifecycle.py
  • marm-mcp-server/marm_mcp_server/core/write_queue.py
  • marm-mcp-server/marm_mcp_server/endpoints/compaction.py
  • marm-mcp-server/marm_mcp_server/endpoints/concepts.py
  • marm-mcp-server/marm_mcp_server/endpoints/logging.py
  • marm-mcp-server/marm_mcp_server/endpoints/memory.py
  • marm-mcp-server/marm_mcp_server/endpoints/notebook.py
  • marm-mcp-server/marm_mcp_server/endpoints/reasoning.py
  • marm-mcp-server/marm_mcp_server/endpoints/session.py
  • marm-mcp-server/marm_mcp_server/endpoints/system.py
  • marm-mcp-server/marm_mcp_server/middleware/auth.py
  • marm-mcp-server/marm_mcp_server/middleware/protocol_injection.py
  • marm-mcp-server/marm_mcp_server/middleware/rate_limiting.py
  • marm-mcp-server/marm_mcp_server/resources/skills/marm-init/SKILL.md
  • marm-mcp-server/marm_mcp_server/server.py
  • marm-mcp-server/marm_mcp_server/server_stdio.py
  • marm-mcp-server/marm_mcp_server/services/analytics.py
  • marm-mcp-server/marm_mcp_server/services/automation.py
  • marm-mcp-server/marm_mcp_server/services/compaction_apply.py
  • marm-mcp-server/marm_mcp_server/services/compaction_summarize.py
  • marm-mcp-server/marm_mcp_server/services/documentation.py
  • marm-mcp-server/marm_mcp_server/services/notebook.py
  • marm-mcp-server/marm_mcp_server/services/product_workflows.py
  • marm-mcp-server/marm_mcp_server/services/recall.py
  • marm-mcp-server/marm_mcp_server/services/stdio_graph_tools.py
  • marm-mcp-server/marm_mcp_server/utils/chunk_backfill.py
  • marm-mcp-server/marm_mcp_server/utils/embedding_migration.py
  • marm-mcp-server/marm_mcp_server/utils/helpers.py
  • marm-mcp-server/marm_mcp_server/utils/security.py
  • marm-mcp-server/pyproject.toml
  • marm-mcp-server/server.json
  • scripts/typecheck.py
  • skills/marm-init/SKILL.md
📜 Review details
🧰 Additional context used
📓 Path-based instructions (9)
{marm-mcp-server/pyproject.toml,marm-mcp-server/server.json,marm-mcp-server/marm_mcp_server/__init__.py,marm-mcp-server/marm_mcp_server/config/settings.py,marm-mcp-server/marm_mcp_server/server.py,marm-mcp-server/Dockerfile,docker-compose.yml,README.md,marm-mcp-server/README.md,marm-mcp-server/marm_mcp_server/resources/marm-docs/README.md,docs/INSTALL-*.md}

📄 CodeRabbit inference engine (AGENTS.md)

When bumping the version, update every listed package, server, Docker, compose, README, and install-document version occurrence and audit with python scripts/find-versions.py.

Files:

  • marm-mcp-server/Dockerfile
  • docs/INSTALL-WINDOWS.md
  • docs/INSTALL-LINUX.md
  • marm-mcp-server/marm_mcp_server/__init__.py
  • marm-mcp-server/server.json
  • marm-mcp-server/pyproject.toml
  • marm-mcp-server/marm_mcp_server/server.py
  • marm-mcp-server/marm_mcp_server/config/settings.py
**/*.md

⚙️ CodeRabbit configuration file

**/*.md: Only flag documentation issues that are materially wrong, misleading for installation/release behavior, or inconsistent with live MCP behavior. Skip style, phrasing, formatting, and wording preferences.

Files:

  • AGENTS.md
  • docs/INSTALL-WINDOWS.md
  • docs/INSTALL-LINUX.md
  • CHANGELOG.md
  • marm-mcp-server/marm_mcp_server/resources/skills/marm-init/SKILL.md
  • skills/marm-init/SKILL.md
marm-mcp-server/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Keep HTTP and STDIO transports in exact parity; never fork behavior between transports.

Files:

  • marm-mcp-server/marm_mcp_server/services/analytics.py
  • marm-mcp-server/marm_mcp_server/middleware/auth.py
  • marm-mcp-server/marm_mcp_server/core/runtime_manager.py
  • marm-mcp-server/marm_mcp_server/__init__.py
  • marm-mcp-server/marm_mcp_server/services/automation.py
  • marm-mcp-server/marm_mcp_server/console/endpoints/concepts.py
  • marm-mcp-server/marm_mcp_server/core/shutdown_manager.py
  • marm-mcp-server/marm_mcp_server/console/cli.py
  • marm-mcp-server/marm_mcp_server/core/events.py
  • marm-mcp-server/marm_mcp_server/core/compaction.py
  • marm-mcp-server/marm_mcp_server/server.py
  • marm-mcp-server/marm_mcp_server/endpoints/notebook.py
  • marm-mcp-server/marm_mcp_server/services/compaction_summarize.py
  • marm-mcp-server/marm_mcp_server/endpoints/reasoning.py
  • marm-mcp-server/marm_mcp_server/endpoints/system.py
  • marm-mcp-server/marm_mcp_server/core/memory_utils.py
  • marm-mcp-server/marm_mcp_server/services/compaction_apply.py
  • marm-mcp-server/marm_mcp_server/utils/helpers.py
  • marm-mcp-server/marm_mcp_server/core/compaction_scheduler.py
  • marm-mcp-server/marm_mcp_server/config/settings.py
  • marm-mcp-server/marm_mcp_server/server_stdio.py
  • marm-mcp-server/marm_mcp_server/core/memory_ops.py
  • marm-mcp-server/marm_mcp_server/core/concept_extraction.py
  • marm-mcp-server/marm_mcp_server/services/stdio_graph_tools.py
  • marm-mcp-server/marm_mcp_server/utils/chunk_backfill.py
  • marm-mcp-server/marm_mcp_server/services/product_workflows.py
  • marm-mcp-server/marm_mcp_server/endpoints/session.py
  • marm-mcp-server/marm_mcp_server/cli.py
  • marm-mcp-server/marm_mcp_server/endpoints/memory.py
  • marm-mcp-server/marm_mcp_server/middleware/protocol_injection.py
  • marm-mcp-server/marm_mcp_server/core/graph_index_lock.py
  • marm-mcp-server/marm_mcp_server/utils/security.py
  • marm-mcp-server/marm_mcp_server/services/recall.py
  • marm-mcp-server/marm_mcp_server/core/models.py
  • marm-mcp-server/marm_mcp_server/core/stdio_tool_lifecycle.py
  • marm-mcp-server/marm_mcp_server/endpoints/compaction.py
  • marm-mcp-server/marm_mcp_server/middleware/rate_limiting.py
  • marm-mcp-server/marm_mcp_server/console/app.py
  • marm-mcp-server/marm_mcp_server/core/memory_recall.py
  • marm-mcp-server/marm_mcp_server/core/docs_db.py
  • marm-mcp-server/marm_mcp_server/endpoints/concepts.py
  • marm-mcp-server/marm_mcp_server/core/memory_delete.py
  • marm-mcp-server/marm_mcp_server/core/response_limiter.py
  • marm-mcp-server/marm_mcp_server/services/notebook.py
  • marm-mcp-server/marm_mcp_server/services/documentation.py
  • marm-mcp-server/marm_mcp_server/endpoints/logging.py
  • marm-mcp-server/marm_mcp_server/core/memory_scoring.py
  • marm-mcp-server/marm_mcp_server/core/concept_db.py
  • marm-mcp-server/marm_mcp_server/core/graph_index_worker.py
  • marm-mcp-server/marm_mcp_server/core/rate_limiter.py
  • marm-mcp-server/marm_mcp_server/core/write_queue.py
  • marm-mcp-server/marm_mcp_server/core/memory_db.py
  • marm-mcp-server/marm_mcp_server/utils/embedding_migration.py
  • marm-mcp-server/marm_mcp_server/core/consolidation.py
  • marm-mcp-server/marm_mcp_server/core/memory.py
marm-mcp-server/marm_mcp_server/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

marm-mcp-server/marm_mcp_server/**/*.py: All memory writes must use the serialized asynchronous write queue; do not add bypass paths.
A semantic-store failure during marm_log_entry must never fail the log write.
Keep the memory, concept-graph, and analytics SQLite databases isolated; never share connections or pools between them.
Graph and concept failures must never break the seven core memory tools.
Every code-index call and delete_project must acquire the graph gate, and release must be driven by engine-call completion rather than awaiting-task completion.
Runtime switches must be persisted in the database; background workers must reread their flag every cycle and continue running while disabled.
Background indexing must never block writes, recall, or startup.
Graph enrichment in marm_smart_recall must be read-only, fail-open, bounded, and trimmed before primary results when enforcing response limits.
Use one lazily loaded, lock-serialized fastembed encoder with 512 dimensions; writes must succeed when the encoder is unavailable.
Prefer the smallest change that solves the task; avoid speculative abstractions and unrequested configuration flags.
Keep comments minimal and explain only non-obvious reasons; do not narrate the next line.
Keep orchestration in its current owner file and extract modules only at real boundaries consistent with the existing endpoint split.

Files:

  • marm-mcp-server/marm_mcp_server/services/analytics.py
  • marm-mcp-server/marm_mcp_server/middleware/auth.py
  • marm-mcp-server/marm_mcp_server/core/runtime_manager.py
  • marm-mcp-server/marm_mcp_server/__init__.py
  • marm-mcp-server/marm_mcp_server/services/automation.py
  • marm-mcp-server/marm_mcp_server/console/endpoints/concepts.py
  • marm-mcp-server/marm_mcp_server/core/shutdown_manager.py
  • marm-mcp-server/marm_mcp_server/console/cli.py
  • marm-mcp-server/marm_mcp_server/core/events.py
  • marm-mcp-server/marm_mcp_server/core/compaction.py
  • marm-mcp-server/marm_mcp_server/server.py
  • marm-mcp-server/marm_mcp_server/endpoints/notebook.py
  • marm-mcp-server/marm_mcp_server/services/compaction_summarize.py
  • marm-mcp-server/marm_mcp_server/endpoints/reasoning.py
  • marm-mcp-server/marm_mcp_server/endpoints/system.py
  • marm-mcp-server/marm_mcp_server/core/memory_utils.py
  • marm-mcp-server/marm_mcp_server/services/compaction_apply.py
  • marm-mcp-server/marm_mcp_server/utils/helpers.py
  • marm-mcp-server/marm_mcp_server/core/compaction_scheduler.py
  • marm-mcp-server/marm_mcp_server/config/settings.py
  • marm-mcp-server/marm_mcp_server/server_stdio.py
  • marm-mcp-server/marm_mcp_server/core/memory_ops.py
  • marm-mcp-server/marm_mcp_server/core/concept_extraction.py
  • marm-mcp-server/marm_mcp_server/services/stdio_graph_tools.py
  • marm-mcp-server/marm_mcp_server/utils/chunk_backfill.py
  • marm-mcp-server/marm_mcp_server/services/product_workflows.py
  • marm-mcp-server/marm_mcp_server/endpoints/session.py
  • marm-mcp-server/marm_mcp_server/cli.py
  • marm-mcp-server/marm_mcp_server/endpoints/memory.py
  • marm-mcp-server/marm_mcp_server/middleware/protocol_injection.py
  • marm-mcp-server/marm_mcp_server/core/graph_index_lock.py
  • marm-mcp-server/marm_mcp_server/utils/security.py
  • marm-mcp-server/marm_mcp_server/services/recall.py
  • marm-mcp-server/marm_mcp_server/core/models.py
  • marm-mcp-server/marm_mcp_server/core/stdio_tool_lifecycle.py
  • marm-mcp-server/marm_mcp_server/endpoints/compaction.py
  • marm-mcp-server/marm_mcp_server/middleware/rate_limiting.py
  • marm-mcp-server/marm_mcp_server/console/app.py
  • marm-mcp-server/marm_mcp_server/core/memory_recall.py
  • marm-mcp-server/marm_mcp_server/core/docs_db.py
  • marm-mcp-server/marm_mcp_server/endpoints/concepts.py
  • marm-mcp-server/marm_mcp_server/core/memory_delete.py
  • marm-mcp-server/marm_mcp_server/core/response_limiter.py
  • marm-mcp-server/marm_mcp_server/services/notebook.py
  • marm-mcp-server/marm_mcp_server/services/documentation.py
  • marm-mcp-server/marm_mcp_server/endpoints/logging.py
  • marm-mcp-server/marm_mcp_server/core/memory_scoring.py
  • marm-mcp-server/marm_mcp_server/core/concept_db.py
  • marm-mcp-server/marm_mcp_server/core/graph_index_worker.py
  • marm-mcp-server/marm_mcp_server/core/rate_limiter.py
  • marm-mcp-server/marm_mcp_server/core/write_queue.py
  • marm-mcp-server/marm_mcp_server/core/memory_db.py
  • marm-mcp-server/marm_mcp_server/utils/embedding_migration.py
  • marm-mcp-server/marm_mcp_server/core/consolidation.py
  • marm-mcp-server/marm_mcp_server/core/memory.py
**/*.py

⚙️ CodeRabbit configuration file

**/*.py: Prioritize runtime correctness, async/concurrency safety, SQLite transaction safety, auth/rate-limit behavior, release-breaking packaging issues, and MCP protocol compatibility.

Files:

  • marm-mcp-server/marm_mcp_server/services/analytics.py
  • marm-mcp-server/marm_mcp_server/middleware/auth.py
  • marm-mcp-server/marm_mcp_server/core/runtime_manager.py
  • marm-mcp-server/marm_mcp_server/__init__.py
  • marm-mcp-server/marm_mcp_server/services/automation.py
  • marm-mcp-server/marm_mcp_server/console/endpoints/concepts.py
  • marm-mcp-server/marm_mcp_server/core/shutdown_manager.py
  • marm-mcp-server/marm_mcp_server/console/cli.py
  • marm-mcp-server/marm_mcp_server/core/events.py
  • marm-mcp-server/marm_mcp_server/core/compaction.py
  • marm-mcp-server/marm_mcp_server/server.py
  • marm-mcp-server/marm_mcp_server/endpoints/notebook.py
  • marm-mcp-server/marm_mcp_server/services/compaction_summarize.py
  • marm-mcp-server/marm_mcp_server/endpoints/reasoning.py
  • marm-mcp-server/marm_mcp_server/endpoints/system.py
  • marm-mcp-server/marm_mcp_server/core/memory_utils.py
  • marm-mcp-server/marm_mcp_server/services/compaction_apply.py
  • marm-mcp-server/marm_mcp_server/utils/helpers.py
  • marm-mcp-server/marm_mcp_server/core/compaction_scheduler.py
  • marm-mcp-server/marm_mcp_server/config/settings.py
  • marm-mcp-server/marm_mcp_server/server_stdio.py
  • marm-mcp-server/marm_mcp_server/core/memory_ops.py
  • marm-mcp-server/marm_mcp_server/core/concept_extraction.py
  • marm-mcp-server/marm_mcp_server/services/stdio_graph_tools.py
  • marm-mcp-server/marm_mcp_server/utils/chunk_backfill.py
  • marm-mcp-server/marm_mcp_server/services/product_workflows.py
  • marm-mcp-server/marm_mcp_server/endpoints/session.py
  • marm-mcp-server/marm_mcp_server/cli.py
  • marm-mcp-server/marm_mcp_server/endpoints/memory.py
  • marm-mcp-server/marm_mcp_server/middleware/protocol_injection.py
  • marm-mcp-server/marm_mcp_server/core/graph_index_lock.py
  • marm-mcp-server/marm_mcp_server/utils/security.py
  • marm-mcp-server/marm_mcp_server/services/recall.py
  • marm-mcp-server/marm_mcp_server/core/models.py
  • marm-mcp-server/marm_mcp_server/core/stdio_tool_lifecycle.py
  • marm-mcp-server/marm_mcp_server/endpoints/compaction.py
  • marm-mcp-server/marm_mcp_server/middleware/rate_limiting.py
  • marm-mcp-server/marm_mcp_server/console/app.py
  • marm-mcp-server/marm_mcp_server/core/memory_recall.py
  • marm-mcp-server/marm_mcp_server/core/docs_db.py
  • marm-mcp-server/marm_mcp_server/endpoints/concepts.py
  • marm-mcp-server/marm_mcp_server/core/memory_delete.py
  • marm-mcp-server/marm_mcp_server/core/response_limiter.py
  • marm-mcp-server/marm_mcp_server/services/notebook.py
  • scripts/typecheck.py
  • marm-mcp-server/marm_mcp_server/services/documentation.py
  • marm-mcp-server/marm_mcp_server/endpoints/logging.py
  • marm-mcp-server/marm_mcp_server/core/memory_scoring.py
  • marm-mcp-server/marm_mcp_server/core/concept_db.py
  • marm-mcp-server/marm_mcp_server/core/graph_index_worker.py
  • marm-mcp-server/marm_mcp_server/core/rate_limiter.py
  • marm-mcp-server/marm_mcp_server/core/write_queue.py
  • marm-mcp-server/marm_mcp_server/core/memory_db.py
  • marm-mcp-server/marm_mcp_server/utils/embedding_migration.py
  • marm-mcp-server/marm_mcp_server/core/consolidation.py
  • marm-mcp-server/marm_mcp_server/core/memory.py
{marm-mcp-server/marm_mcp_server/endpoints/**/*.py,marm-mcp-server/marm_mcp_server/server.py,marm-mcp-server/marm_mcp_server/server_stdio.py,marm-mcp-server/server.json,scripts/find-tools.py,README.md,docs/PROTOCOL.md,docs/PROTOCOL-LITE.md,marm-mcp-server/marm_mcp_server/resources/marm-docs/**/*.md,marm-mcp-server/tests/**/*.py}

📄 CodeRabbit inference engine (AGENTS.md)

When adding or removing an MCP tool, update its endpoint, HTTP route and whitelist, STDIO registration, server.json, canonical tool list, all full tool-list documentation and counts, and tests for both transports; then run python scripts/find-tools.py.

Files:

  • marm-mcp-server/server.json
  • marm-mcp-server/marm_mcp_server/server.py
  • marm-mcp-server/marm_mcp_server/endpoints/notebook.py
  • marm-mcp-server/marm_mcp_server/endpoints/reasoning.py
  • marm-mcp-server/marm_mcp_server/endpoints/system.py
  • marm-mcp-server/marm_mcp_server/server_stdio.py
  • marm-mcp-server/marm_mcp_server/endpoints/session.py
  • marm-mcp-server/marm_mcp_server/endpoints/memory.py
  • marm-mcp-server/marm_mcp_server/endpoints/compaction.py
  • marm-mcp-server/marm_mcp_server/endpoints/concepts.py
  • marm-mcp-server/marm_mcp_server/endpoints/logging.py
marm-mcp-server/marm_mcp_server/server.py

📄 CodeRabbit inference engine (AGENTS.md)

HTTP tools must be registered in both the route definitions and the MCP_TOOL_OPERATIONS whitelist.

Files:

  • marm-mcp-server/marm_mcp_server/server.py
marm-mcp-server/marm_mcp_server/endpoints/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Endpoint logic belongs under endpoints/, split by surface; shared helpers belong in core/.

Files:

  • marm-mcp-server/marm_mcp_server/endpoints/notebook.py
  • marm-mcp-server/marm_mcp_server/endpoints/reasoning.py
  • marm-mcp-server/marm_mcp_server/endpoints/system.py
  • marm-mcp-server/marm_mcp_server/endpoints/session.py
  • marm-mcp-server/marm_mcp_server/endpoints/memory.py
  • marm-mcp-server/marm_mcp_server/endpoints/compaction.py
  • marm-mcp-server/marm_mcp_server/endpoints/concepts.py
  • marm-mcp-server/marm_mcp_server/endpoints/logging.py
marm-mcp-server/marm_mcp_server/server_stdio.py

📄 CodeRabbit inference engine (AGENTS.md)

STDIO owns the FastMCP app and core wrappers; graph and concept services must be registered after core tools so tools/list order remains stable.

Files:

  • marm-mcp-server/marm_mcp_server/server_stdio.py
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
Repo: Lyellr88/marm-memory

Timestamp: 2026-08-10T10:59:10.458Z
Learning: Never commit changes without an explicit user request.
Learnt from: CR
Repo: Lyellr88/marm-memory

Timestamp: 2026-08-10T10:59:10.458Z
Learning: Use SemVer: MAJOR for breaking changes, MINOR for new tools, parameters, or features, and PATCH for fixes and documentation updates.
📚 Learning: 2026-07-31T08:30:32.056Z
Learnt from: Lyellr88
Repo: Lyellr88/marm-memory PR: 125
File: docs/INSTALL-LINUX.md:323-323
Timestamp: 2026-07-31T08:30:32.056Z
Learning: In the Linux and Windows installation documentation, treat http://localhost:8001 as the primary MARM MCP Server endpoint. Do not validate its response contract against the standalone marm-mcp-server/marm_graph/server.py health route, because marm-graph is embedded in the primary marm_mcp_server service.

Applied to files:

  • docs/INSTALL-WINDOWS.md
  • docs/INSTALL-LINUX.md
🪛 GitHub Actions: Ruff CI / 0_ruff.txt
marm-mcp-server/marm_mcp_server/core/consolidation.py

[error] 45-45: Ruff check failed: RUF036 — None is not at the end of the type union. Command: ruff check --output-format=github.

🪛 GitHub Actions: Ruff CI / ruff
marm-mcp-server/marm_mcp_server/core/consolidation.py

[error] 45-45: Ruff RUF036: None is not at the end of the type union. Fix the type annotation ordering.

🪛 GitHub Check: ruff
marm-mcp-server/marm_mcp_server/core/consolidation.py

[failure] 74-74: ruff (RUF036)
marm_mcp_server/core/consolidation.py:74:15: RUF036 None not at the end of the type union.
help: Move None to the end of the type union


[failure] 73-73: ruff (RUF036)
marm_mcp_server/core/consolidation.py:73:14: RUF036 None not at the end of the type union.
help: Move None to the end of the type union


[failure] 46-46: ruff (RUF036)
marm_mcp_server/core/consolidation.py:46:15: RUF036 None not at the end of the type union.
help: Move None to the end of the type union


[failure] 45-45: ruff (RUF036)
marm_mcp_server/core/consolidation.py:45:14: RUF036 None not at the end of the type union.
help: Move None to the end of the type union

🪛 SkillSpector (2.5.1)
marm-mcp-server/marm_mcp_server/resources/skills/marm-init/SKILL.md

[info] 46: [RP1] null: pip install without ==version installs the latest release, which could include malicious changes.

Remediation: Pin the version: pip install package==1.2.3

(MCP Rug Pull (RP1))


[warning] 47: [RP1] null: Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.

Remediation: Pin the image: image:tag or image@sha256:abc123

(MCP Rug Pull (RP1))


[warning] 137: [RP1] null: Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.

Remediation: Pin the image: image:tag or image@sha256:abc123

(MCP Rug Pull (RP1))


[warning] 7: [AS3] Skill Enumeration: Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Remediation: Remove all code or instructions that list or read other skills' files or directories. Skills should operate independently; cross-skill access is a privilege escalation.

(Agent Snooping (AS3))


[info] 46: [RP1] null: pip install without ==version installs the latest release, which could include malicious changes.

Remediation: Pin the version: pip install package==1.2.3

(MCP Rug Pull (RP1))


[warning] 47: [RP1] null: Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.

Remediation: Pin the image: image:tag or image@sha256:abc123

(MCP Rug Pull (RP1))


[warning] 137: [RP1] null: Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.

Remediation: Pin the image: image:tag or image@sha256:abc123

(MCP Rug Pull (RP1))


[warning] 7: [AS3] Skill Enumeration: Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Remediation: Remove all code or instructions that list or read other skills' files or directories. Skills should operate independently; cross-skill access is a privilege escalation.

(Agent Snooping (AS3))


[info] 46: [RP1] null: pip install without ==version installs the latest release, which could include malicious changes.

Remediation: Pin the version: pip install package==1.2.3

(MCP Rug Pull (RP1))


[warning] 47: [RP1] null: Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.

Remediation: Pin the image: image:tag or image@sha256:abc123

(MCP Rug Pull (RP1))


[warning] 137: [RP1] null: Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.

Remediation: Pin the image: image:tag or image@sha256:abc123

(MCP Rug Pull (RP1))


[warning] 7: [AS3] Skill Enumeration: Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Remediation: Remove all code or instructions that list or read other skills' files or directories. Skills should operate independently; cross-skill access is a privilege escalation.

(Agent Snooping (AS3))


[info] 46: [RP1] null: pip install without ==version installs the latest release, which could include malicious changes.

Remediation: Pin the version: pip install package==1.2.3

(MCP Rug Pull (RP1))


[warning] 47: [RP1] null: Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.

Remediation: Pin the image: image:tag or image@sha256:abc123

(MCP Rug Pull (RP1))


[warning] 137: [RP1] null: Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.

Remediation: Pin the image: image:tag or image@sha256:abc123

(MCP Rug Pull (RP1))


[warning] 7: [AS3] Skill Enumeration: Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Remediation: Remove all code or instructions that list or read other skills' files or directories. Skills should operate independently; cross-skill access is a privilege escalation.

(Agent Snooping (AS3))

skills/marm-init/SKILL.md

[info] 46: [RP1] null: pip install without ==version installs the latest release, which could include malicious changes.

Remediation: Pin the version: pip install package==1.2.3

(MCP Rug Pull (RP1))


[warning] 47: [RP1] null: Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.

Remediation: Pin the image: image:tag or image@sha256:abc123

(MCP Rug Pull (RP1))


[warning] 137: [RP1] null: Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.

Remediation: Pin the image: image:tag or image@sha256:abc123

(MCP Rug Pull (RP1))


[warning] 7: [AS3] Skill Enumeration: Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Remediation: Remove all code or instructions that list or read other skills' files or directories. Skills should operate independently; cross-skill access is a privilege escalation.

(Agent Snooping (AS3))


[info] 46: [RP1] null: pip install without ==version installs the latest release, which could include malicious changes.

Remediation: Pin the version: pip install package==1.2.3

(MCP Rug Pull (RP1))


[warning] 47: [RP1] null: Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.

Remediation: Pin the image: image:tag or image@sha256:abc123

(MCP Rug Pull (RP1))


[warning] 137: [RP1] null: Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.

Remediation: Pin the image: image:tag or image@sha256:abc123

(MCP Rug Pull (RP1))


[warning] 7: [AS3] Skill Enumeration: Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Remediation: Remove all code or instructions that list or read other skills' files or directories. Skills should operate independently; cross-skill access is a privilege escalation.

(Agent Snooping (AS3))


[info] 46: [RP1] null: pip install without ==version installs the latest release, which could include malicious changes.

Remediation: Pin the version: pip install package==1.2.3

(MCP Rug Pull (RP1))


[warning] 47: [RP1] null: Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.

Remediation: Pin the image: image:tag or image@sha256:abc123

(MCP Rug Pull (RP1))


[warning] 137: [RP1] null: Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.

Remediation: Pin the image: image:tag or image@sha256:abc123

(MCP Rug Pull (RP1))


[warning] 7: [AS3] Skill Enumeration: Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Remediation: Remove all code or instructions that list or read other skills' files or directories. Skills should operate independently; cross-skill access is a privilege escalation.

(Agent Snooping (AS3))


[info] 46: [RP1] null: pip install without ==version installs the latest release, which could include malicious changes.

Remediation: Pin the version: pip install package==1.2.3

(MCP Rug Pull (RP1))


[warning] 47: [RP1] null: Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.

Remediation: Pin the image: image:tag or image@sha256:abc123

(MCP Rug Pull (RP1))


[warning] 137: [RP1] null: Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.

Remediation: Pin the image: image:tag or image@sha256:abc123

(MCP Rug Pull (RP1))


[warning] 7: [AS3] Skill Enumeration: Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Remediation: Remove all code or instructions that list or read other skills' files or directories. Skills should operate independently; cross-skill access is a privilege escalation.

(Agent Snooping (AS3))

🔇 Additional comments (66)
marm-mcp-server/marm_mcp_server/utils/chunk_backfill.py (1)

25-25: LGTM!

Also applies to: 137-137, 180-182

marm-mcp-server/marm_mcp_server/utils/embedding_migration.py (1)

6-11: LGTM!

Also applies to: 31-42, 56-56, 97-105, 123-123, 190-190

marm-mcp-server/marm_mcp_server/utils/helpers.py (1)

19-19: LGTM!

Also applies to: 32-32

marm-mcp-server/marm_mcp_server/utils/security.py (1)

140-153: LGTM!

marm-mcp-server/marm_mcp_server/core/compaction.py (1)

6-6: LGTM!

Also applies to: 186-186

marm-mcp-server/marm_mcp_server/core/concept_db.py (1)

314-338: LGTM!

Also applies to: 362-362, 428-428, 504-504, 529-529

marm-mcp-server/marm_mcp_server/core/concept_extraction.py (1)

9-9: LGTM!

Also applies to: 69-69, 91-91, 101-101, 113-113, 127-127

marm-mcp-server/marm_mcp_server/core/docs_db.py (1)

88-93: LGTM!

Also applies to: 164-166

marm-mcp-server/marm_mcp_server/core/memory.py (1)

6-8: LGTM!

Also applies to: 40-40, 79-85, 102-102, 201-209, 281-281, 290-290, 416-458, 475-478

marm-mcp-server/marm_mcp_server/core/memory_db.py (1)

7-11: LGTM!

Also applies to: 20-33, 49-49, 62-69, 86-99, 468-468, 479-479, 496-496

marm-mcp-server/marm_mcp_server/core/memory_delete.py (1)

4-19: LGTM!

Also applies to: 52-52, 81-81, 104-104, 141-146

marm-mcp-server/marm_mcp_server/core/compaction_scheduler.py (1)

3-4: LGTM!

Also applies to: 15-21, 36-41

marm-mcp-server/marm_mcp_server/core/events.py (1)

11-22: LGTM!

Also applies to: 60-62

marm-mcp-server/marm_mcp_server/core/rate_limiter.py (1)

17-17: LGTM!

Also applies to: 86-86

marm-mcp-server/marm_mcp_server/core/runtime_manager.py (1)

373-375: LGTM!

marm-mcp-server/marm_mcp_server/core/stdio_tool_lifecycle.py (1)

7-7: LGTM!

Also applies to: 22-28

marm-mcp-server/marm_mcp_server/core/consolidation.py (1)

5-24: LGTM!

Also applies to: 88-93, 109-109

marm-mcp-server/marm_mcp_server/core/memory_ops.py (1)

7-7: LGTM!

Also applies to: 36-40, 151-155, 302-302, 380-380

marm-mcp-server/marm_mcp_server/core/memory_recall.py (1)

6-8: LGTM!

Also applies to: 34-38, 42-47, 103-103, 145-156, 180-180, 362-367

marm-mcp-server/marm_mcp_server/core/memory_scoring.py (1)

4-18: LGTM!

Also applies to: 38-40, 87-90, 152-156, 300-300

marm-mcp-server/marm_mcp_server/core/memory_utils.py (1)

11-19: LGTM!

Also applies to: 197-197, 288-288

marm-mcp-server/marm_mcp_server/core/models.py (1)

156-156: LGTM!

Also applies to: 182-182

marm-mcp-server/marm_mcp_server/core/response_limiter.py (1)

88-88: LGTM!

Also applies to: 117-120

marm-mcp-server/marm_mcp_server/core/graph_index_lock.py (1)

39-39: LGTM!

Also applies to: 48-49, 131-145, 168-172

marm-mcp-server/marm_mcp_server/core/graph_index_worker.py (1)

25-28: LGTM!

Also applies to: 123-123

marm-mcp-server/marm_mcp_server/core/shutdown_manager.py (1)

16-21: LGTM!

Also applies to: 35-35, 49-53

marm-mcp-server/marm_mcp_server/core/write_queue.py (1)

6-11: LGTM!

Also applies to: 36-36, 69-94

CHANGELOG.md (1)

3-3: LGTM!

Also applies to: 5-7, 10-23

scripts/typecheck.py (1)

30-37: LGTM!

Also applies to: 55-64, 74-74, 125-130

marm-mcp-server/marm_mcp_server/resources/skills/marm-init/SKILL.md (1)

16-45: LGTM!

Also applies to: 48-56, 61-70, 79-80, 89-163, 173-192

skills/marm-init/SKILL.md (1)

16-45: LGTM!

Also applies to: 48-56, 61-70, 79-80, 89-163, 173-192

marm-mcp-server/marm_mcp_server/__init__.py (3)

20-21: LGTM!

Also applies to: 23-29


17-22: 🎯 Functional Correctness

Align the release number with the published change type. If this release does not add public MCP tools/parameters/features or change behavior, do not use 2.38.0; use 2.37.1 from the previous 2.37.0 release. Apply the chosen version consistently across release metadata, including marm-mcp-server/pyproject.toml, marm-mcp-server/server.json, marm-mcp-server/docker-compose.yml, CHANGELOG.md, and AGENTS.md, then audit with python scripts/find-versions.py.


17-18: 🎯 Functional Correctness

Keep the release version consistent with CHANGELOG.md.

The changelog titles this release as v2.38.0, and all release-critical metadata currently uses 2.38.0. Changing 2.38.0 to 2.37.1 would create the very version drift this review is meant to avoid.

			> Likely an incorrect or invalid review comment.
marm-mcp-server/marm_mcp_server/cli.py (1)

13-20: LGTM!

Also applies to: 89-89

marm-mcp-server/marm_mcp_server/console/cli.py (1)

15-15: LGTM!

Also applies to: 45-45, 98-98

marm-mcp-server/marm_mcp_server/services/product_workflows.py (1)

10-10: LGTM!

Also applies to: 119-119

docs/INSTALL-LINUX.md (1)

316-316: LGTM!

docs/INSTALL-WINDOWS.md (1)

290-290: LGTM!

marm-mcp-server/Dockerfile (1)

76-76: LGTM!

marm-mcp-server/docker-compose.yml (1)

8-8: LGTM!

Also applies to: 21-21

marm-mcp-server/marm_mcp_server/config/settings.py (1)

162-162: LGTM!

Also applies to: 181-181, 209-209

marm-mcp-server/marm_mcp_server/endpoints/concepts.py (1)

13-13: LGTM!

Also applies to: 327-339, 399-399, 426-430, 515-534

marm-mcp-server/marm_mcp_server/endpoints/system.py (1)

24-24: LGTM!

Also applies to: 54-54, 115-115

marm-mcp-server/marm_mcp_server/middleware/auth.py (1)

4-5: LGTM!

Also applies to: 13-15

marm-mcp-server/marm_mcp_server/services/compaction_summarize.py (1)

10-10: LGTM!

Also applies to: 78-78, 101-101

marm-mcp-server/marm_mcp_server/services/notebook.py (1)

5-5: LGTM!

Also applies to: 46-46, 89-89, 127-127, 155-155, 167-167, 182-182, 240-240, 261-272, 281-294

marm-mcp-server/pyproject.toml (2)

101-112: LGTM!


74-77: 📐 Maintainability & Code Quality

No issue found.

The CI lint/format workflow installs and runs Ruff only, and the remaining black, isort, and flake8 references in scripts/find-versions.py are only documentation-version-search exclusions.

marm-mcp-server/marm_mcp_server/endpoints/notebook.py (1)

12-12: 🎯 Functional Correctness

Verify the FastAPI response contract for all newly annotated endpoints.

The three -> dict annotations can change inferred response-model validation, serialization, filtering, and documentation. The supplied snippets do not show the route decorators or the complete delegated return contract. Confirm that the intended routes use response_model=None where required and that all success paths return plain dictionaries. (fastapi.tiangolo.com)

  • marm-mcp-server/marm_mcp_server/endpoints/notebook.py#L12-L12: verify every notebook_dispatch path returns a dictionary.
  • marm-mcp-server/marm_mcp_server/endpoints/session.py#L17-L17: verify the marm_start route preserves its existing response contract.
  • marm-mcp-server/marm_mcp_server/endpoints/session.py#L68-L68: verify the marm_refresh route preserves its existing response contract.
marm-mcp-server/marm_mcp_server/middleware/protocol_injection.py (1)

8-9: LGTM!

Also applies to: 32-34, 125-127

marm-mcp-server/marm_mcp_server/middleware/rate_limiting.py (1)

4-5: LGTM!

Also applies to: 44-46

marm-mcp-server/marm_mcp_server/server.py (1)

11-12: LGTM!

Also applies to: 52-52, 111-111

marm-mcp-server/marm_mcp_server/services/analytics.py (1)

13-15: LGTM!

marm-mcp-server/marm_mcp_server/services/automation.py (1)

7-19: LGTM!

marm-mcp-server/marm_mcp_server/services/documentation.py (1)

15-15: LGTM!

Also applies to: 59-59, 262-262, 278-278

marm-mcp-server/marm_mcp_server/console/app.py (1)

14-24: LGTM!

Also applies to: 75-75, 97-99, 153-153, 181-181, 192-192

marm-mcp-server/marm_mcp_server/console/endpoints/concepts.py (1)

126-126: LGTM!

marm-mcp-server/marm_mcp_server/endpoints/compaction.py (1)

36-36: LGTM!

Also applies to: 93-95, 257-257, 310-310, 535-535

marm-mcp-server/marm_mcp_server/endpoints/logging.py (1)

17-17: LGTM!

Also applies to: 34-34, 44-44

marm-mcp-server/marm_mcp_server/endpoints/memory.py (1)

22-24: LGTM!

Also applies to: 215-215

marm-mcp-server/marm_mcp_server/endpoints/reasoning.py (1)

13-13: LGTM!

marm-mcp-server/marm_mcp_server/server_stdio.py (1)

22-22: LGTM!

Also applies to: 59-59

marm-mcp-server/marm_mcp_server/services/compaction_apply.py (1)

9-13: LGTM!

marm-mcp-server/marm_mcp_server/services/recall.py (1)

29-30: LGTM!

marm-mcp-server/marm_mcp_server/services/stdio_graph_tools.py (1)

17-20: LGTM!

Also applies to: 368-368

pip install -r marm-mcp-server/requirements.txt
pip install -e './marm-mcp-server' --no-deps
pip install pytest pytest-asyncio pytest-cov jsonschema requests black isort flake8 mypy ruff
pip install pytest pytest-asyncio pytest-cov jsonschema requests mypy ruff

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== workflow lines around install =="
sed -n '45,70p' .github/workflows/publish-mcp.yml 2>/dev/null || true

echo
echo "== typecheck file outline/content =="
if [ -f scripts/typecheck.py ]; then
  wc -l scripts/typecheck.py
  sed -n '1,120p' scripts/typecheck.py
else
  fd -a 'typecheck.py' .
fi

echo
echo "== files mentioning mypy/ruff/pytest-asyncio validation baseline =="
rg -n "mypy|ruff|BASELINE|typecheck|pytest-cov|jsonschema|requests|pip install" .github scripts -S || true

echo
echo "== other tool pins in repo =="
rg -n "mypy=.*|ruff=.*|python_requires|twine|pytest-cov|jsonschema|requests|mypy|mypy-strict|ruff check" pyproject.toml setup.cfg setup.py tox.ini .github -S 2>/dev/null | head -n 200

Repository: Lyellr88/marm-memory

Length of output: 10960


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== scripts/find-versions.py relevant section =="
sed -n '55,90p' scripts/find-versions.py 2>/dev/null || true

echo
echo "== requirements files mentioning validation packages =="
for f in $(git ls-files | rg '(^|/)requirements.*\.txt$|pyproject\.toml$|tox\.ini$|setup\.cfg$'); do
  if rg -n "mypy|ruff|pytest|pytest-asyncio|pytest-cov|jsonschema|requests|strict" "$f" >/tmp/matches.$$; then
    echo "--- $f"
    cat /tmp/matches.$$
  fi
done

echo
echo "== workflow exact validation steps =="
sed -n '48,66p' .github/workflows/publish-mcp.yml
sed -n '128,138p' .github/workflows/publish-mcp.yml

Repository: Lyellr88/marm-memory

Length of output: 2854


Pin scripts/typecheck.py inputs before enabling it as a release gate.

scripts/typecheck.py fails if reported errors go above BASELINE = 2 and explicitly says a pinned Mypy is not optional because the baseline is version-specific. Add an exact mypy pin and the exact validation scripts/config/versioned inputs used when creating the baseline before gating releases on this check.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/publish-mcp.yml at line 59, Update the release workflow’s
dependency installation and typecheck gate around scripts/typecheck.py to pin
mypy to the baseline’s exact version and include the exact validation scripts,
configuration, and versioned inputs used to establish BASELINE = 2. Ensure the
release check runs against those pinned inputs rather than unversioned or
drifting tooling.

Comment thread marm-mcp-server/marm_mcp_server/core/consolidation.py Outdated
Comment on lines +277 to +279
if mirror_memory_id is not None:
with docs_db.get_connection() as conn:
docs_db.set_memory_id(conn, doc_row.id, memory_id)
docs_db.set_memory_id(conn, doc_row.id, mirror_memory_id)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Keep mirror synchronization pending when the document-ID update fails.

If docs_db.set_memory_id raises after memory.store_doc_mirror succeeds, _save propagates the exception. The docs row still contains the old or null memory_id, while the memory mirror already exists. A later save can create a duplicate mirror or clean the wrong record. Catch this failure and use a durable, idempotent reconciliation keyed by doc_id; report mirror_status as "pending" until the docs update succeeds.

As per path instructions, prioritize runtime correctness, async/concurrency safety, and SQLite transaction safety.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@marm-mcp-server/marm_mcp_server/services/notebook.py` around lines 277 - 279,
Update _save so a failure from docs_db.set_memory_id after
memory.store_doc_mirror does not leave synchronization unreconciled: catch the
update failure, persist a durable idempotent reconciliation record keyed by
doc_id, and report mirror_status as "pending". Ensure reconciliation retries
safely under concurrent saves and SQLite transactions, and only mark the mirror
synchronized after the docs row update succeeds.

Source: Path instructions

[project]
name = "marm-mcp-server"
version = "2.37.0"
version = "2.38.0"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== files =="
git ls-files | rg '(^|/)pyproject\.toml$|(^|/)server\.json$|(^|/)README\.md$|(^|/)INSTALL-.*\.md$|scripts/find-versions\.py|marm-mcp-server/marm_mcp_server/server\.py'

echo
echo "== version occurrences =="
rg -n '"?version"?|2\.38|2\.37|2\.3[0-9]|Dockerfile|marm-mcp-server|lyellr88/marm-mcp-server|python scripts/find-versions' \
  -g '!**/.git/**' \
  -g '!**/*.pyc' \
  -g '!**/__pycache__/**' .

echo
echo "== pyproject excerpt =="
cat -n marm-mcp-server/pyproject.toml | sed -n '1,40p'

echo
echo "== server.json excerpt =="
cat -n marm-mcp-server/server.json | sed -n '1,45p'

echo
echo "== server.py header =="
cat -n marm-mcp-server/marm_mcp_server/server.py | sed -n '1,35p'

echo
echo "== scripts/find-versions.py =="
cat -n scripts/find-versions.py | sed -n '1,220p' || true

Repository: Lyellr88/marm-memory

Length of output: 50377


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== targeted files status =="
git diff --stat -- marm-mcp-server/pyproject.toml marm-mcp-server/server.json marm-mcp-server/marm_mcp_server/server.py README.md marm-mcp-server/README.md docker-compose.yml marm-mcp-server/Dockerfile scripts/find-versions.py docs/INSTALL-*.md 2>/dev/null || true

echo
echo "== targeted versions with line numbers =="
rg -n -C 2 '("version"|version|2\.38\.0|2\.37\.0|2\.37\.1|lyellr88/marm-mcp-server|marm-mcp-server|python scripts/find-versions)' \
  marm-mcp-server/pyproject.toml \
  marm-mcp-server/server.json \
  marm-mcp-server/marm_mcp_server/server.py \
  README.md \
  marm-mcp-server/README.md \
  docker-compose.yml \
  marm-mcp-server/Dockerfile \
  scripts/find-versions.py \
  docs/INSTALL-*.md \
  2>/dev/null || true

echo
echo "== find-versions.py =="
cat -n scripts/find-versions.py | sed -n '1,220p' || true

echo
echo "== semver mentions =="
rg -n -i -C 2 'semver|breaking|minor|patch|feature|fix|mcp|transport' README.md docs marm-mcp-server/pyproject.toml 2>/dev/null || true

echo
echo "== inspect static asset length issue if present =="
wc -l ./marm-mcp-server/marm_mcp_server/console/static/assets/index-D10wAXCq.js 2>/dev/null || true

Repository: Lyellr88/marm-memory

Length of output: 50379


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== first changelog entry =="
python3 - <<'PY'
from pathlib import Path
text = Path("CHANGELOG.md").read_text()
lines = text.splitlines()
for i, line in enumerate(lines, 1):
    if line.startswith("# ") or line.startswith("## "):
        print(f"{i}: {line}")
        break
PY

echo
echo "== release/type mentions in changelog head =="
sed -n '1,80p' CHANGELOG.md

echo
echo "== docker-compose version refs =="
test -f docker-compose.yml && sed -n '1,80p' docker-compose.yml || true

echo
echo "== all exact 2.38.0 refs in tracked text =="
git grep -n '"version": "2\.38\.0"\|version = "2\.38\.0"\|Version: 2\.38\.0\|2\.38\.0' -- '*.toml' '*.json' '*.py' '*.yml' '*.yaml' Dockerfile README.md docs/INSTALL-*.md scripts/find-versions.py marm-mcp-server 2>/dev/null || true

echo
echo "== git tree refs for version files =="
git ls-tree HEAD -- marm-mcp-server/pyproject.toml marm-mcp-server/server.json marm-mcp-server/marm_mcp_server/server.py README.md marm-mcp-server/README.md docker-compose.yml marm-mcp-server/Dockerfile scripts/read-versions.py docs/INSTALL-*.md | sed -n '1,120p'

Repository: Lyellr88/marm-memory

Length of output: 11603


Align the release version metadata with the changelog.

CHANGELOG.md has no release entry for 2.38.0, but the tracked package, manifest, OCI, Docker, and module metadata all use 2.38.0. Use the chosen release version consistently, and ensure the changelog contains a release entry for it before release.

📍 Affects 3 files
  • marm-mcp-server/pyproject.toml#L7-L7 (this comment)
  • marm-mcp-server/server.json#L6-L6
  • marm-mcp-server/server.json#L20-L25
  • marm-mcp-server/marm_mcp_server/server.py#L8-L9
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@marm-mcp-server/pyproject.toml` at line 7, Align all release metadata with
the chosen version and add the corresponding changelog entry: update
marm-mcp-server/pyproject.toml:7, both version references in
marm-mcp-server/server.json:6 and 20-25, and
marm-mcp-server/marm_mcp_server/server.py:8-9 consistently, then add a
CHANGELOG.md release entry for that same version before release.

Sources: Coding guidelines, Learnings

Comment thread scripts/typecheck.py
from collections import Counter

BASELINE = 113
BASELINE = 2

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== files =="
git ls-files | rg '(^|/)(scripts/typecheck.py|CHANGELOG.md)$' || true

echo "== typecheck.py =="
if [ -f scripts/typecheck.py ]; then
  nl -ba scripts/typecheck.py | sed -n '1,90p'
fi

echo "== changelog excerpt =="
if [ -f CHANGELOG.md ]; then
  nl -ba CHANGELOG.md | sed -n '1,25p'
fi

echo "== search related terms =="
rg -n "BASELINE|mypy|typecheck|new type error|type error" -S . --glob '!/.git/**' --glob '!node_modules/**' | head -100

Repository: Lyellr88/marm-memory

Length of output: 263


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== typecheck.py =="
if [ -f scripts/typecheck.py ]; then
  cat -n scripts/typecheck.py | sed -n '1,90p'
fi

echo "== changelog excerpt =="
if [ -f CHANGELOG.md ]; then
  cat -n CHANGELOG.md | sed -n '1,25p'
fi

echo "== related code searches =="
rg -n "BASELINE|mypy|typecheck|typeerr|new type error|type error|exit_code|subprocess" -S . --glob '!/.git/**' --glob '!node_modules/**' | head -200 || true

echo "== parse typecheck behavior =="
python3 - <<'PY'
from pathlib import Path
p=Path("scripts/typecheck.py")
if p.exists():
    text=p.read_text()
    print(text)
PY

Repository: Lyellr88/marm-memory

Length of output: 28811


Keep the baseline description aligned with the count-only gate. scripts/typecheck.py only rejects total > BASELINE, so a new error replacing an old one can pass unchanged. Change the gate to snapshotted or per-file baseline comparison, or update CHANGELOG.md to remove the claim that every new type error fails.

📍 Affects 2 files
  • scripts/typecheck.py#L28-L28 (this comment)
  • CHANGELOG.md#L8-L9
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/typecheck.py` at line 28, Align the type-error baseline behavior with
its documentation: update the gate around BASELINE in scripts/typecheck.py to
compare against a snapshot or per-file baseline so replacements are rejected, or
remove the claim that every new type error fails from CHANGELOG.md lines 8-9.
Apply the chosen correction at the corresponding site; no other changes are
required.

Comment thread skills/marm-init/SKILL.md
Comment on lines +46 to +47
- pip: run `pip install marm-mcp-server`. Confirm success, for example `marm-mcp-server --version` resolves. Record runtime = python.
- Docker: run `docker pull lyellr88/marm-mcp-server:latest`. Confirm the image is present with `docker images -q lyellr88/marm-mcp-server`. Record runtime = docker.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Locate SKILL.md files =="
git ls-files | grep -E '(^|/)SKILL\.md$' | sed -n '1,50p'

echo
echo "== Relevant lines =="
for f in $(git ls-files | grep -E '(^|/)SKILL\.md$'); do
  if grep -n -E 'pip install marm-mcp-server|docker pull|Docker image|lyellr88/marm-mcp-server' "$f" >/dev/null; then
    echo "--- $f"
    sed -n '36,55p' "$f" | cat -n
  fi
done

echo
echo "== Release/version references nearby =="
for f in $(git ls-files | grep -E 'README\.md$|AGENTS\.md$|CHANGELOG\.md$'); do
  echo "--- $f"
  grep -n -E 'marm-mcp-server|pip install|docker|lyellr88|version' "$f" | sed -n '1,80p' || true
done

Repository: Lyellr88/marm-memory

Length of output: 36446


🌐 Web query:

Docker latest tag mutable image digest best practice package latest pip install mutable artifact security

💡 Result:

Using the latest tag and mutable image tags in production is a significant security and operational risk; the industry best practice is to pin container images by their unique, immutable digest (e.g., image@sha256:...) [1][2][3][4]. Why latest and mutable tags are unsafe: 1. Lack of Determinism: The latest tag is a moving label that points to whatever image was most recently pushed [5][2][6]. This causes non-deterministic behavior, where two deployments of the same configuration might pull different images [7][6]. 2. Security Vulnerabilities (TOCTOU): Using mutable tags exposes your environment to Time-of-Check vs. Time-of-Use (TOCTOU) attacks [4][8]. An image can be scanned and validated as secure, but replaced in the registry by a malicious image with the same tag before it is deployed [4][9]. 3. Broken Reproducibility: If an issue occurs, you cannot reliably roll back to a known-good state because the tag no longer points to the same bytes it did during the original deployment [2][6]. 4. Operational Risks: Unexpected updates can occur during pod restarts if your orchestrator (like Kubernetes) is configured to pull images, leading to mysterious production failures that are difficult to debug [2][6]. Best Practices: - Pin by Digest: Always use the immutable SHA-256 digest in your deployment manifests or configuration files [1][3][4]. This ensures that every deployment is byte-for-byte identical to the version you tested and validated [7][9]. - Enforce Tag Immutability: If your registry supports it (e.g., AWS ECR's imageTagMutability, GCP Artifact Registry's immutable tags), enable it to prevent existing tags from being overwritten [2][3][6]. - Automate Updates: Since pinning by digest prevents automatic updates, use automation tools (such as Renovate or Dependabot) to monitor for new base images and automatically open pull requests to update the pinned digests in your manifests [7][9]. - Separate Build from Deploy: CI pipelines should build an image, generate its unique digest, and then inject that specific digest into the deployment process, rather than relying on mutable tag names [3][9]. Regarding pip install latest: The risks are similar. Installing the "latest" version of a software package without pinning a version (e.g., via a requirements.txt or lockfile with hashes) is a supply chain security risk. It makes your builds non-reproducible and potentially vulnerable to malicious code injection if an upstream package is compromised or updated unexpectedly. Always use lockfiles that include specific versions and cryptographic hashes (e.g., pip-compile with hashes) to ensure the artifact you install is the exact one you verified. Top Results: [1], [2], [7], [3], [4], [9]

Citations:


Pin both installer artifacts to immutable releases.

  • skills/marm-init/SKILL.md#L46-L55 and marm-mcp-server/marm_mcp_server/resources/skills/marm-init/SKILL.md#L46-L55 both use pip install marm-mcp-server and lyellr88/marm-mcp-server:latest. Replace these in both copies with a fixed package version and a fixed Docker tag or digest.
🧰 Tools
🪛 SkillSpector (2.5.1)

[info] 46: [RP1] null: pip install without ==version installs the latest release, which could include malicious changes.

Remediation: Pin the version: pip install package==1.2.3

(MCP Rug Pull (RP1))


[warning] 47: [RP1] null: Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.

Remediation: Pin the image: image:tag or image@sha256:abc123

(MCP Rug Pull (RP1))


[warning] 137: [RP1] null: Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.

Remediation: Pin the image: image:tag or image@sha256:abc123

(MCP Rug Pull (RP1))


[warning] 7: [AS3] Skill Enumeration: Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Remediation: Remove all code or instructions that list or read other skills' files or directories. Skills should operate independently; cross-skill access is a privilege escalation.

(Agent Snooping (AS3))

📍 Affects 2 files
  • skills/marm-init/SKILL.md#L46-L47 (this comment)
  • marm-mcp-server/marm_mcp_server/resources/skills/marm-init/SKILL.md#L46-L47
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@skills/marm-init/SKILL.md` around lines 46 - 47, Pin both installer artifacts
to immutable releases in skills/marm-init/SKILL.md lines 46-47 and
marm-mcp-server/marm_mcp_server/resources/skills/marm-init/SKILL.md lines 46-47:
replace the unversioned pip package with a fixed marm-mcp-server version and
replace the Docker image’s latest tag with a fixed release tag or digest,
keeping both copies consistent.

Source: Linters/SAST tools

Comment thread skills/marm-init/SKILL.md
Comment on lines +57 to +60
1. Read the full MARM protocol from source: `https://raw.githubusercontent.com/Lyellr88/marm-memory/MARM-main/docs/PROTOCOL.md` If the network read fails, fall back in this order:
- local repo `docs/PROTOCOL.md`
- packaged copy `marm-mcp-server/marm_mcp_server/resources/marm-docs/PROTOCOL.md`
2. Freshness check: read the `version:` field in this file's frontmatter and compare it against the `version:` in the source copy at `metadata.source`. If the source version is higher, tell the user once: "Your MARM init skill is out of date. Re-run `marm-memory init` to refresh it." Then continue with the version you have.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'Files matching marm-init SKILL.md:\n'
git ls-files | rg '(^|/)marm-init/SKILL\.md$|marm-mcp-server/.*marm-init/SKILL\.md$'

printf '\nRelevant SKILL.md snippets:\n'
for f in $(git ls-files | rg '(^|/)marm-init/SKILL\.md$|marm-mcp-server/.*marm-init/SKILL\.md$'); do
  echo "--- $f"
  cat -n "$f" | sed -n '1,90p'
done

printf '\nSearch for protocol source usages/init behavior:\n'
rg -n "marm-memory|MARM-main|PROTOCOL|metadata\.source|version:" -S . || true

printf '\nGit diff stat/name-status if available:\n'
git diff --stat || true
git diff --name-status || true

Repository: Lyellr88/marm-memory

Length of output: 50377


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'Find exact SKILL.md files:\n'
git ls-files | rg '(^skills/marm-init/SKILL\.md$|^marm-mcp-server/.*marm-init/SKILL\.md$)' || true

printf '\nSkips using fd with lowercase match (if available):\n'
fd -a 'SKILL\.md$' . 2>/dev/null | rg 'marm-init|skills/marm-init' || true

printf '\nFocused rg for URLs:\n'
rg -n "Lyellr88/marm-memory/MARM-main/docs/PROTOCOL|/docs/PROTOCOL\.md$|metadata\.source|version:" -S --glob '!**/node_modules/**' --glob '!**/.git/**' .

printf '\nInspect likely installer/workflow files if any:\n'
rg -n "init|marm-init|SKILL|metadata\.source|PROTOCOL" -S marm-mcp-server/scripts marm-mcp-server tests --glob '!**/node_modules/**' || true

Repository: Lyellr88/marm-memory

Length of output: 50377


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'Git tracked files by direct name matches:\n'
for f in 'skills/marm-init/SKILL.md' 'marm-mcp-server/marm_mcp_server/resources/skills/marm-init/SKILL.md'; do
  if git ls-files --error-unmatch "$f" >/dev/null 2>&1; then
    echo "tracked $f"
  else
    echo "missing $f"
  fi
done

printf '\nAll tracked files named SKILL.md:\n'
git ls-files '*SKILL.md' | sed -n '1,80p'

printf '\nAll tracked files in marm-init paths:\n'
git ls-files '*marm-init*' | sed -n '1,120p'

printf '\nFocused rg to tracked Python/config/test files only:\n'
git ls-files | rg '\.(py|md|yaml|yml|toml)$|/tests/' | rg 'skill|marm-init|protocol|marm|init' | while IFS= read -r f; do
  rg -n "Lyellr88/marm-memory/MARM-main/docs/PROTOCOL|marm-mcp-server/marm_mcp_server/resources/skills/marm-init|version:|metadata\.source|PROTOCOL\.md" "$f" \
    && printf '\n--- %s\n' "$f" \
    || true
done

printf '\nDiff stat and changed markdown files only:\n'
git diff --stat
git diff --name-only | rg '\.md$|marm-init|skills|marm_mcp_server' || true

Repository: Lyellr88/marm-memory

Length of output: 6189


Validate the protocol source before running the fetch path.

Both skills/marm-init/SKILL.md and the packaged marm-mcp-server/marm_mcp_server/resources/skills/marm-init/SKILL.md direct fetches from https://raw.githubusercontent.com/Lyellr88/marm-memory/MARM-main/docs/PROTOCOL.md. Add an immutability check, such as checksum or pinned commit verification, before executing that protocol content or using fetch fallbacks.

🧰 Tools
🪛 SkillSpector (2.5.1)

[info] 46: [RP1] null: pip install without ==version installs the latest release, which could include malicious changes.

Remediation: Pin the version: pip install package==1.2.3

(MCP Rug Pull (RP1))


[warning] 47: [RP1] null: Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.

Remediation: Pin the image: image:tag or image@sha256:abc123

(MCP Rug Pull (RP1))


[warning] 137: [RP1] null: Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.

Remediation: Pin the image: image:tag or image@sha256:abc123

(MCP Rug Pull (RP1))


[warning] 7: [AS3] Skill Enumeration: Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Remediation: Remove all code or instructions that list or read other skills' files or directories. Skills should operate independently; cross-skill access is a privilege escalation.

(Agent Snooping (AS3))

📍 Affects 2 files
  • skills/marm-init/SKILL.md#L57-L60 (this comment)
  • marm-mcp-server/marm_mcp_server/resources/skills/marm-init/SKILL.md#L57-L60
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@skills/marm-init/SKILL.md` around lines 57 - 60, The protocol fetch path in
skills/marm-init/SKILL.md lines 57-60 and
marm-mcp-server/marm_mcp_server/resources/skills/marm-init/SKILL.md lines 57-60
must validate the remote source before using its content or fallbacks. Add a
checksum or pinned-commit verification for the PROTOCOL.md source, and only
execute or continue with fetched content when validation succeeds; apply the
same change to both copies.

A doc save commits the docs row, then links it to a memories mirror in a
second write. A failure in that second write propagated out of _save, so a
save that had already durably succeeded reported an error and left the mirror
row unlinked. The next save then passed existing_memory_id=None and created a
second mirror, once per save.

The link failure is now reported as mirror_status="pending" on a successful
save, matching the existing behavior for a failed mirror write. _store_doc_mirror
resolves a doc's existing mirror by metadata.doc_id when it has no usable id,
inside its own transaction, so the write is idempotent per doc and the pending
status is a promise it can keep.

Two tests drive the real failure through notebook_dispatch against SQLite.
The repair test was confirmed to fail without the doc_id resolution.

Also in this commit:

- Reorder four unions in consolidation.py so None comes last. Ruff 0.16.2
  promoted RUF036 out of preview and failed CI on them; 0.15.16 reported the
  file clean, so a local pass did not predict CI.
- Pin ruff==0.16.2 in CI so a ruff release cannot fail an unchanged PR.
- Correct the changelog's typecheck claim to name the count-based mechanism
  rather than implying every new type error is caught.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@marm-mcp-server/marm_mcp_server/core/memory_ops.py`:
- Around line 426-437: Update the orphan-repair logic around existing_memory_id
to fetch all matching doc rows for metadata["doc_id"], retain one canonical row,
and remove or retire surplus rows using the existing chunk and graph cleanup
path. Ensure repair leaves recall with a single document mirror, and add a
regression test covering two orphaned rows with the same document ID.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 332ef027-5c8e-414c-b9fa-a75fef6d73ba

📥 Commits

Reviewing files that changed from the base of the PR and between 69c74ba and 0f8300b.

📒 Files selected for processing (6)
  • .github/workflows/ruff.yml
  • CHANGELOG.md
  • marm-mcp-server/marm_mcp_server/core/consolidation.py
  • marm-mcp-server/marm_mcp_server/core/memory_ops.py
  • marm-mcp-server/marm_mcp_server/services/notebook.py
  • marm-mcp-server/tests/test_notebook_service.py
🚧 Files skipped from review as they are similar to previous changes (3)
  • CHANGELOG.md
  • marm-mcp-server/marm_mcp_server/core/consolidation.py
  • marm-mcp-server/marm_mcp_server/services/notebook.py
📜 Review details
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{py,md,json,yml,yaml,toml,Dockerfile}

📄 CodeRabbit inference engine (AGENTS.md)

Keep changes surgical: modify only what the task requires, match existing style, and preserve behavior during refactors.

Files:

  • marm-mcp-server/tests/test_notebook_service.py
  • marm-mcp-server/marm_mcp_server/core/memory_ops.py
marm-mcp-server/tests/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

marm-mcp-server/tests/**/*.py: Run tests with pytest from marm-mcp-server/; exercise real FastAPI endpoints and real SQLite, mocking only when it meaningfully accelerates tests and matches behavior with at least 95% fidelity.
Every new MARM Console API route needs at least one happy-path FastAPI response-contract test with the MCP adapter stubbed.
Do not write existence-check or coded-to-pass tests; prefer deep real-path coverage, and use pytest.mark.skip only for genuinely unavailable dependencies.

Files:

  • marm-mcp-server/tests/test_notebook_service.py
**/tests/**

⚙️ CodeRabbit configuration file

**/tests/**: Focus on tests that are flaky, non-isolated, incorrectly asserting behavior, or missing coverage for a changed high-risk path. Skip minor naming, comments, and layout preferences.

Files:

  • marm-mcp-server/tests/test_notebook_service.py
**/*.py

⚙️ CodeRabbit configuration file

**/*.py: Prioritize runtime correctness, async/concurrency safety, SQLite transaction safety, auth/rate-limit behavior, release-breaking packaging issues, and MCP protocol compatibility.

Files:

  • marm-mcp-server/tests/test_notebook_service.py
  • marm-mcp-server/marm_mcp_server/core/memory_ops.py
marm-mcp-server/marm_mcp_server/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

marm-mcp-server/marm_mcp_server/**/*.py: HTTP and STDIO transports must remain in exact behavioral parity; never fork behavior between transports.
All memory writes must use the serialized asynchronous write queue; do not add bypass paths.
marm_log_entry must dual-write a log_entries row and semantic memory, while semantic-store failure must never fail the log write.
Never share database connections or pools between the memory database and the concept-graph database.
Every code-index call and delete_project must use the graph gate; release must be driven by engine-call completion rather than the awaiting task.
Background indexing must never block writes, recall, or startup; graph and concept failures must not break the seven core memory tools.
marm_smart_recall must keep primary memory ranking authoritative; graph enrichment is bounded, read-only, fail-open, and trimmed before primary results when enforcing response limits.
Use one lazy-loaded, lock-serialized fastembed jinaai/jina-embeddings-v2-small-en encoder with 512 dimensions; writes must succeed if the encoder is unavailable.
New tools must be implemented in endpoints/, routed and whitelisted for HTTP, wrapped or serviced for STDIO, and added to every consistency-list artifact.
Prefer the smallest solution; avoid speculative abstractions and unrequested configuration flags. Keep orchestration in its current owner and extract modules only at real boundaries.
Use minimal comments only for non-obvious reasons; do not add comments that narrate the next line.

Files:

  • marm-mcp-server/marm_mcp_server/core/memory_ops.py
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: Lyellr88/marm-memory

Timestamp: 2026-08-10T11:40:37.646Z
Learning: Never commit changes without an explicit user request.
Learnt from: CR
Repo: Lyellr88/marm-memory

Timestamp: 2026-08-10T11:40:37.646Z
Learning: Use semantic versioning: MAJOR for breaking changes, MINOR for new tools, parameters, or features, and PATCH for fixes and documentation updates.
🔇 Additional comments (1)
.github/workflows/ruff.yml (1)

27-32: LGTM!

Comment on lines +426 to +437
if not existing_memory_id and metadata.get("doc_id") is not None:
orphan = conn.execute(
"""
SELECT id FROM memories
WHERE context_type = 'doc'
AND json_extract(metadata, '$.doc_id') = ?
ORDER BY timestamp LIMIT 1
""",
(metadata["doc_id"],),
).fetchone()
if orphan is not None:
existing_memory_id = orphan[0]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Repair pre-existing duplicate document mirrors.

If earlier failed retries created multiple doc rows for one metadata.doc_id, this query updates only one row and leaves the other stale mirrors intact. Recall can still return duplicate document content after the link repair.

Resolve all matching rows during repair. Keep one row. Remove or retire surplus rows through the existing chunk and graph cleanup path. Add a regression test that starts with two orphaned rows for the same document.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@marm-mcp-server/marm_mcp_server/core/memory_ops.py` around lines 426 - 437,
Update the orphan-repair logic around existing_memory_id to fetch all matching
doc rows for metadata["doc_id"], retain one canonical row, and remove or retire
surplus rows using the existing chunk and graph cleanup path. Ensure repair
leaves recall with a single document mirror, and add a regression test covering
two orphaned rows with the same document ID.

@Lyellr88
Lyellr88 merged commit d419d5a into MARM-main Aug 10, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant