Skip to content

Dedup log-entry logic between HTTP and STDIO transports - #94

Merged
Lyellr88 merged 2 commits into
MARM-mainfrom
refactor/log-entry-dedup
Jul 17, 2026
Merged

Dedup log-entry logic between HTTP and STDIO transports#94
Lyellr88 merged 2 commits into
MARM-mainfrom
refactor/log-entry-dedup

Conversation

@Lyellr88

@Lyellr88 Lyellr88 commented Jul 17, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • Bug Fixes
    • HTTP and STDIO log/notebook operations are now consistent, including session switching and deletion behavior.
    • STDIO no longer returns raw exception text; failures use safe, generic messages while server details are logged.
    • Full-session deletion is more resilient (including when summary-cache data is missing) and avoids active-session inconsistencies on commit failure.
    • Invalid deletion types are rejected with clear 422 errors (and STDIO returns safe error dictionaries instead of raising).
  • Documentation
    • Added unreleased v2.21.3 “Log-Entry Cross-Transport Dedup” changelog notes.
  • Tests
    • Added regression and end-to-end coverage for the above behaviors.

endpoints/logging.py and services/stdio_entry_tools.py each carried
their own near-identical copy of marm_log_entry/marm_log_show/marm_delete's
session-switch detection, SQL, and dual-write-to-semantic-memory logic.
Extracted into a shared services/log_entry.py; both transports now call
the same functions through thin, transport-specific wrappers with
injectable log_info/log_warning callbacks so each keeps its existing
logging destination (HTTP: print, STDIO: _stdio_log to stderr + file).

Two behavioral divergences found during the merge, fixed rather than
carried forward:
- STDIO's error responses leaked raw exception text to the client
  (same CWE-209 class as the earlier marm_concept_recall fix); now
  returns the same fixed generic messages HTTP already used.
- HTTP's whole-session marm_delete deleted from session_summary_cache
  without a try/except guard, unlike every other cache-invalidation
  touch in both files; unified on the guarded behavior for both.

Independent Opus review found no correctness bugs in the extraction;
closed one flagged test-coverage gap (invalid marm_delete type on both
transports).

Full suite: 623 passed, 20 skipped, zero regressions. Both fixes
mutation-tested (reverted, confirmed exact expected failure, restored).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011s8tBNnQTmb1q5nRAKwhvv
@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 955adedb-e75a-447f-bfb8-abe54ee31c1d

📥 Commits

Reviewing files that changed from the base of the PR and between e907d78 and e702f82.

📒 Files selected for processing (2)
  • marm-mcp-server/marm_mcp_server/services/log_entry.py
  • marm-mcp-server/tests/test_stdio_transport.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • marm-mcp-server/tests/test_stdio_transport.py
  • marm-mcp-server/marm_mcp_server/services/log_entry.py

📝 Walkthrough

Walkthrough

HTTP and STDIO log/notebook operations now share a service module for creation, listing, and deletion. Transport wrappers retain local validation and logging, while tests cover generic errors, invalid types, isolated state, commit failures, and missing cache-table handling.

Changes

Cross-Transport Log Entry Deduplication

Layer / File(s) Summary
Shared log-entry service implementation
marm-mcp-server/marm_mcp_server/services/log_entry.py
Centralizes session handling, persistence, listing, deletion, semantic-memory cleanup, event emission, generic error responses, and guarded summary-cache updates.
HTTP and STDIO transport delegation
marm-mcp-server/marm_mcp_server/endpoints/logging.py, marm-mcp-server/marm_mcp_server/services/stdio_entry_tools.py
Replaces duplicated transport logic with shared service calls while preserving transport-specific invalid-type handling and logging.
Transport validation and regression coverage
marm-mcp-server/tests/test_http_tools.py, marm-mcp-server/tests/test_stdio_transport.py, marm-mcp-server/tests/test_summary_cache.py, CHANGELOG.md
Adds coverage for invalid types, generic STDIO errors, commit-failure state handling, shared isolated state, missing cache tables, and documents the release changes.

Estimated code review effort: 4 (Complex) | ~45 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: 3

🤖 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/services/log_entry.py`:
- Line 86: Update the session/log creation flow around
events.emit("session_created", ...) and the additionally affected event
publication sites so event-delivery failures cannot propagate as handler
failures after durable writes commit. Catch and handle publication errors as
best-effort while preserving the successful response for the already-created
session and log data; do not alter the write semantics or create duplicate
durable records on client retry.
- Around line 48-84: Refactor the session-prefix and ordinary marm_log_entry
mutation paths to submit all SQLite writes through the serialized asynchronous
write queue instead of calling memory.get_connection directly. Ensure each
marm_log_entry operation queues both the durable log_entries insert and semantic
memories write together, including session-start entries, while preserving the
behavior that semantic-store failures do not fail the durable log write. Route
session updates, cache invalidation, and commits through the same queued
operation.
- Around line 338-340: Move the active_log_session assignment in the deletion
flow so it occurs only after conn.commit() completes successfully. Keep the
existing target check and "main" fallback, ensuring a commit failure leaves the
runtime session unchanged.
🪄 Autofix (Beta)

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

Run ID: 150a75b9-0690-41a5-a2ac-146e6eca43e8

📥 Commits

Reviewing files that changed from the base of the PR and between 2b439e9 and e907d78.

📒 Files selected for processing (7)
  • CHANGELOG.md
  • marm-mcp-server/marm_mcp_server/endpoints/logging.py
  • marm-mcp-server/marm_mcp_server/services/log_entry.py
  • marm-mcp-server/marm_mcp_server/services/stdio_entry_tools.py
  • marm-mcp-server/tests/test_http_tools.py
  • marm-mcp-server/tests/test_stdio_transport.py
  • marm-mcp-server/tests/test_summary_cache.py
📜 Review details
🧰 Additional context used
📓 Path-based instructions (7)
**/*

📄 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_http_tools.py
  • marm-mcp-server/tests/test_summary_cache.py
  • marm-mcp-server/tests/test_stdio_transport.py
  • marm-mcp-server/marm_mcp_server/services/stdio_entry_tools.py
  • CHANGELOG.md
  • marm-mcp-server/marm_mcp_server/endpoints/logging.py
  • marm-mcp-server/marm_mcp_server/services/log_entry.py
**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

**/*.py: Prefer the smallest change that solves the problem; do not add speculative abstractions or unrequested configuration flags.
Keep comments minimal, explain only non-obvious reasons, and never narrate what the next line does.

Files:

  • marm-mcp-server/tests/test_http_tools.py
  • marm-mcp-server/tests/test_summary_cache.py
  • marm-mcp-server/tests/test_stdio_transport.py
  • marm-mcp-server/marm_mcp_server/services/stdio_entry_tools.py
  • marm-mcp-server/marm_mcp_server/endpoints/logging.py
  • marm-mcp-server/marm_mcp_server/services/log_entry.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_http_tools.py
  • marm-mcp-server/tests/test_summary_cache.py
  • marm-mcp-server/tests/test_stdio_transport.py
  • marm-mcp-server/marm_mcp_server/services/stdio_entry_tools.py
  • marm-mcp-server/marm_mcp_server/endpoints/logging.py
  • marm-mcp-server/marm_mcp_server/services/log_entry.py
marm-mcp-server/tests/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

marm-mcp-server/tests/**/*.py: Run tests with pytest from marm-mcp-server/; tests should hit real FastAPI endpoints and real SQLite, mocking only when it meaningfully speeds tests and matches real 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 tests exercising real paths over broad shallow coverage.
Use pytest.mark.skip only for genuinely unavailable dependencies, such as the embedding model or spaCy [concepts] extra, never for lack of effort.

Files:

  • marm-mcp-server/tests/test_http_tools.py
  • marm-mcp-server/tests/test_summary_cache.py
  • marm-mcp-server/tests/test_stdio_transport.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_http_tools.py
  • marm-mcp-server/tests/test_summary_cache.py
  • marm-mcp-server/tests/test_stdio_transport.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 and must not bypass it.
marm_log_entry must dual-write a log_entries row and a semantic memories entry through the queue; semantic-store failure must never fail the log write.
Keep the memory database and concept-graph database isolated; never share connections between them.
Use one lazy-loaded all-MiniLM-L6-v2 fastembed encoder serialized behind a lock; writes must succeed when the encoder is unavailable.
Keep orchestration in its current owner file; extract modules only at real boundaries consistent with the existing endpoint split.

Files:

  • marm-mcp-server/marm_mcp_server/services/stdio_entry_tools.py
  • marm-mcp-server/marm_mcp_server/endpoints/logging.py
  • marm-mcp-server/marm_mcp_server/services/log_entry.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:

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

📄 CodeRabbit inference engine (AGENTS.md)

marm-mcp-server/marm_mcp_server/endpoints/**/*.py: Endpoint logic belongs in endpoints/, split by surface; shared helpers belong in core/.
When adding a tool, implement it in the appropriate endpoints/ surface before registering its transports and documentation.

Files:

  • marm-mcp-server/marm_mcp_server/endpoints/logging.py
🪛 ast-grep (0.44.1)
marm-mcp-server/marm_mcp_server/services/log_entry.py

[warning] 134-134: Regex pattern passed to re is built from a non-literal (variable, call, concatenation, or f-string) value. If that value is attacker-controlled it can introduce a malicious pattern with catastrophic backtracking (ReDoS). Use a hardcoded literal pattern, or validate/escape untrusted input with re.escape() and bound the regex complexity before compiling.
Context: re.match(entry_pattern, formatted_entry)
Note: [CWE-1333] Inefficient Regular Expression Complexity.

(redos-non-literal-regex-python)

🔇 Additional comments (7)
marm-mcp-server/marm_mcp_server/services/log_entry.py (1)

1-32: LGTM!

Also applies to: 116-143, 199-283, 341-367

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

7-11: LGTM!

Also applies to: 26-26, 40-40, 52-59

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

1-35: LGTM!

marm-mcp-server/tests/test_stdio_transport.py (1)

17-30: LGTM!

Also applies to: 278-293, 397-428

marm-mcp-server/tests/test_http_tools.py (1)

700-715: LGTM!

marm-mcp-server/tests/test_summary_cache.py (1)

166-193: LGTM!

CHANGELOG.md (1)

5-15: LGTM!

Comment thread marm-mcp-server/marm_mcp_server/services/log_entry.py
Comment thread marm-mcp-server/marm_mcp_server/services/log_entry.py Outdated
Comment thread marm-mcp-server/marm_mcp_server/services/log_entry.py Outdated
- active_log_session was flipped to "main" before conn.commit() in
  marm_delete's whole-session branch. If commit ever failed, the delete
  would roll back but the runtime pointer would already say "main"
  while the target session's rows were still in the DB. Moved the flip
  to after commit succeeds. Pre-existing in both original files, carried
  forward verbatim by the dedup refactor.

- Wrapped both events.emit() calls in try/except so an event-publish
  failure can't turn an already-committed write into a client-facing
  error (a retry on a false error response would create a duplicate
  entry). MARMEvents.emit() already isolates callback failures
  internally, so this is defense-in-depth for consistency with the
  file's existing semantic-store try/except, not a fix for a live bug.

Deferred the 3rd finding (route all SQLite writes through the
serialized write queue): checked core/write_queue.py -- it exists to
serialize semantic-memory/embedding writes specifically, not as a
general SQLite-write wrapper. The direct-connection pattern this
finding flags is used identically across endpoints/compaction.py,
concepts.py, memory.py, session.py, system.py, and
services/documentation.py, notebook.py, recall.py, summary.py --
pre-existing codebase-wide, not introduced by this PR, and CodeRabbit
itself tags it a heavy lift. Out of scope for a log-entry dedup PR.

Both fixes mutation-tested (reverted, confirmed the exact expected
failure, restored). Full suite: 624 passed, 20 skipped, zero
regressions.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011s8tBNnQTmb1q5nRAKwhvv
@Lyellr88
Lyellr88 merged commit 46c438c into MARM-main Jul 17, 2026
7 checks passed
@Lyellr88
Lyellr88 deleted the refactor/log-entry-dedup branch July 17, 2026 06:37
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.

2 participants