Skip to content

test: add edit failure-path and cross-agent PATCH rejection tests (Refs PR #633, BountyHub #508)#736

Open
jdjioe5-cpu wants to merge 4 commits into
moorcheh-ai:mainfrom
jdjioe5-cpu:fix/pr633-tests
Open

test: add edit failure-path and cross-agent PATCH rejection tests (Refs PR #633, BountyHub #508)#736
jdjioe5-cpu wants to merge 4 commits into
moorcheh-ai:mainfrom
jdjioe5-cpu:fix/pr633-tests

Conversation

@jdjioe5-cpu

@jdjioe5-cpu jdjioe5-cpu commented Jun 14, 2026

Copy link
Copy Markdown

Summary

This follow-up PR adds the parallel coverage to PR #633 (feat: add memory edit command) that PR #733 already added for PR #632 (feat: add memory forget command):

  • test_edit_memory_returns_404_when_missing — verifies that PATCH /api/v2/agents/{agent_id}/memories/{id} returns 404 when the underlying MemoryWriteService.update_memory raises a 'not found' exception (the canonical failure-path for Add memanto edit update an existing memory #540 acceptance criteria).
  • test_edit_memory_rejected_for_cross_agent — verifies that PATCH is rejected (403) when session.agent_id != URL agent_id, and that the write service is NEVER invoked (the cross-agent guard at memanto/app/routes/memory.py:316-ish).
  • test_edit_nonexistent_memory — verifies that memanto edit <id> surfaces a non-zero exit + the missing memory id in stdout when the underlying update_memory raises.

Why a separate PR

The 2 missing items on PR #633 are scoped to the good first issue test gap (failure-path + cross-agent), exactly like PR #733 was for #632. Both PR #632 and PR #633 remain mergeable source-of-truth for their features; this PR only adds missing test coverage.

Diff

 tests/test_api.py | 70 +++++++++++++++++++++++++++++++++++++++++++++++
 tests/test_cli.py | 20 +++++++++++++
 2 files changed, 90 insertions(+)

Validation

  • python3 -m ruff check tests/test_api.py tests/test_cli.py → all checks passed
  • python3 -c "import ast; ast.parse(...)" for both files → OK
  • git diff --check clean
  • Local pytest not run (no moorcheh_sdk installed in the cloud venv); CI on the maintainer's side will run it.

Refs PR #633 · Issue #540 · BountyHub #508 $100

Summary by CodeRabbit

  • New Features

    • Added ability to edit existing memories via API with optional fields (title, content, type, confidence, tags, source)
    • Added CLI edit command to update memories with flexible field selection
    • Includes validation for content and requires at least one field per update
  • Tests

    • Comprehensive test coverage added for memory editing functionality

@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@jdjioe5-cpu, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 11 minutes and 17 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5eef0440-8dd1-4f28-9f4f-57bdd8e5dc54

📥 Commits

Reviewing files that changed from the base of the PR and between b26ba09 and c86eb80.

📒 Files selected for processing (6)
  • memanto/app/routes/memory.py
  • memanto/cli/client/direct_client.py
  • memanto/cli/client/sdk_client.py
  • memanto/cli/commands/memory.py
  • tests/test_api.py
  • tests/test_cli.py
📝 Walkthrough

Walkthrough

A new MemoryEditRequest Pydantic model and PATCH /{agent_id}/memories/{memory_id} endpoint are added to the memory router. Matching update_memory methods are added to DirectClient and SdkClient. A new edit Typer CLI command wires these together, and four API tests plus three CLI tests cover the new behavior.

Changes

Memory Edit Feature

Layer / File(s) Summary
MemoryEditRequest schema and PATCH endpoint
memanto/app/routes/memory.py
Adds MemoryEditRequest with optional fields and to_updates(), and the edit_memory PATCH handler with session/scope enforcement (403), empty-update rejection (400), CostGuard content-length check, MemoryWriteService.update_memory delegation, and 404/error mapping.
update_memory on DirectClient and SdkClient
memanto/cli/client/direct_client.py, memanto/cli/client/sdk_client.py
Adds update_memory(agent_id, memory_id, updates) to both CLI client classes; each validates the agent session, rejects empty updates, delegates to the write service with the session namespace, and returns a metadata dict with status, action, and updated_fields.
edit Typer CLI command
memanto/cli/commands/memory.py
Introduces the edit command accepting a required memory_id and optional field flags; builds the updates dict, parses --tags CSV into a trimmed list, enforces non-empty updates, calls client.update_memory, and prints updated fields with elapsed time.
API tests for PATCH edit_memory endpoint
tests/test_api.py
Adds four async tests: successful update with exact call-arg assertions, empty-body 400, missing-memory 404, and cross-agent 403 using FastAPI dependency overrides to inject Session and mock MemoryWriteService.
CLI tests for edit command
tests/test_cli.py
Adds three CLI integration tests: successful edit including tag CSV-to-list conversion, no-field-provided error, and non-zero exit when update_memory raises.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant CLIEdit
  participant Client
  participant MemoryWriteService
  User->>CLIEdit: Run memanto edit with update fields
  CLIEdit->>Client: update_memory(agent_id, memory_id, updates)
  Client->>MemoryWriteService: update_memory(namespace, memory_id, updates)
  MemoryWriteService-->>Client: status, action, updated_fields
  Client-->>CLIEdit: update result metadata
  CLIEdit-->>User: Print updated memory and fields
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Suggested reviewers

  • het0814

🐇 A hop, a skip, a memory patched with care,
New fields flow in — title, tags, source laid bare.
The guard checks length, the session checks the key,
Four-oh-three if you're not who you claim to be!
Now memanto edit keeps our memories just right,
A tidy little PATCH gleaming bright. ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title specifically describes the test additions (edit failure-path and cross-agent PATCH rejection tests) which match the PR's actual changes that add test coverage for memory editing functionality.
Docstring Coverage ✅ Passed Docstring coverage is 96.00% which is sufficient. The required threshold is 80.00%.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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 and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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 `@memanto/app/routes/memory.py`:
- Around line 343-345: The truthy check on line 343 of the memory.py file in the
memory update route bypasses the CostGuard.validate_text_length validation when
content is an empty string. Replace the truthy check (using the walrus operator
with content assignment) with an explicit key-presence check that verifies
"content" exists in the updates dictionary, then add explicit validation to
reject empty content (not just None), ensuring consistency with the remember()
endpoint validation at line 155. Alternatively, move the content validation into
the write_service.update_memory method to centralize the safeguard, but the
simplest fix is to check key presence and validate that content is not empty
before allowing the update.

In `@memanto/cli/client/direct_client.py`:
- Around line 747-753: The update_memory method call in
_get_validated_session_for_agent currently only validates that the updates
dictionary is non-empty, but does not validate the actual field values within
updates such as confidence ranges, type validity, or content being non-blank.
Add field-level validation for the updates dictionary keys and values before
passing them to the _get_write_service().update_memory() call, ensuring the same
validation constraints are enforced here as in the API path. This same
validation pattern needs to be applied at all locations where update_memory is
called with user-provided updates.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 14a4eb65-3183-4296-9578-356b99b09dfe

📥 Commits

Reviewing files that changed from the base of the PR and between 262db90 and b26ba09.

📒 Files selected for processing (6)
  • memanto/app/routes/memory.py
  • memanto/cli/client/direct_client.py
  • memanto/cli/client/sdk_client.py
  • memanto/cli/commands/memory.py
  • tests/test_api.py
  • tests/test_cli.py

Comment thread memanto/app/routes/memory.py Outdated
Comment thread memanto/cli/client/direct_client.py
@jdjioe5-cpu

Copy link
Copy Markdown
Author

Cross-link update — 2026-06-14 21:55 CST

The cross-agent test in this PR (test_edit_memory_rejected_for_cross_agent)
asserts status_code == 403, but on current moorcheh-ai/main the
underlying PATCH route (PR #633) raises a generic Exception which the
global error mapper converts to 500 (not 403).

I just opened PR #737 (fix(memory): return HTTP 403 for cross-agent scope mismatch, head 6d6f83e, +36/-48 across 1 file) which fixes all
12 cross-agent guard sites in memanto/app/routes/memory.py to raise
HTTPException(status_code=403, ...) directly.

Recommended merge order: #737#633#736, then this test
assertion passes against the post-merge tree.

(BountyHub #508 $100 is unaffected by ordering — both PRs reference it.)

jdjioe5-cpu added a commit to jdjioe5-cpu/memanto that referenced this pull request Jun 14, 2026
Address the two actionable CodeRabbit review items flagged on
PR moorcheh-ai#736 (which tests this PR):

1. routes/memory.py edit endpoint previously used
   'if content := updates.get("content")' which silently allowed
   blank/whitespace-only content. Replaced with explicit non-empty +
   length checks. Added parallel range checks for confidence (0.0-1.0)
   and membership check for memory_type, matching the API contract
   used for the create endpoint.

2. cli/client/direct_client.py update_memory previously only checked
   that 'updates' was non-empty, allowing invalid edit payloads
   (out-of-range confidence, invalid type, blank content, unknown
   field names) to flow into the write service. Added the same field
   validation on the direct-client path so the CLI behavior matches
   the REST API contract.

Both fixes align the edit path with the existing create path's
validation strategy and keep the test coverage in PR moorcheh-ai#736 honest.

Refs PR moorcheh-ai#736 (test follow-up)
Refs Issue moorcheh-ai#540 (good-first-issue)
Refs BountyHub bounty moorcheh-ai#508 (Memanto + mattpocock skills challenge)
jdjioe5-cpu added a commit to jdjioe5-cpu/memanto that referenced this pull request Jun 14, 2026
Address the two actionable CodeRabbit review items flagged on
PR moorcheh-ai#736 (which tests this PR):

1. routes/memory.py edit endpoint previously used
   'if content := updates.get("content")' which silently allowed
   blank/whitespace-only content. Replaced with explicit non-empty +
   length checks. Added parallel range checks for confidence (0.0-1.0)
   and membership check for memory_type, matching the API contract
   used for the create endpoint.

2. cli/client/direct_client.py update_memory previously only checked
   that 'updates' was non-empty, allowing invalid edit payloads
   (out-of-range confidence, invalid type, blank content, unknown
   field names) to flow into the write service. Added the same field
   validation on the direct-client path so the CLI behavior matches
   the REST API contract.

Both fixes align the edit path with the existing create path's
validation strategy and keep the test coverage in PR moorcheh-ai#736 honest.

Refs PR moorcheh-ai#736 (test follow-up)
Refs Issue moorcheh-ai#540 (good-first-issue)
Refs BountyHub bounty moorcheh-ai#508 (Memanto + mattpocock skills challenge)
jdjioe5-cpu and others added 4 commits June 15, 2026 00:23
Address the two actionable CodeRabbit review items flagged on
PR moorcheh-ai#736 (which tests this PR):

1. routes/memory.py edit endpoint previously used
   'if content := updates.get("content")' which silently allowed
   blank/whitespace-only content. Replaced with explicit non-empty +
   length checks. Added parallel range checks for confidence (0.0-1.0)
   and membership check for memory_type, matching the API contract
   used for the create endpoint.

2. cli/client/direct_client.py update_memory previously only checked
   that 'updates' was non-empty, allowing invalid edit payloads
   (out-of-range confidence, invalid type, blank content, unknown
   field names) to flow into the write service. Added the same field
   validation on the direct-client path so the CLI behavior matches
   the REST API contract.

Both fixes align the edit path with the existing create path's
validation strategy and keep the test coverage in PR moorcheh-ai#736 honest.

Refs PR moorcheh-ai#736 (test follow-up)
Refs Issue moorcheh-ai#540 (good-first-issue)
Refs BountyHub bounty moorcheh-ai#508 (Memanto + mattpocock skills challenge)
…fs PR moorcheh-ai#633, BountyHub moorcheh-ai#508)

This follow-up adds the parallel coverage to PR moorcheh-ai#633 that PR moorcheh-ai#733 already
added for PR moorcheh-ai#632:

- test_edit_memory_returns_404_when_missing: PATCH /memories/{id} returns
  404 when the underlying update_memory raises a 'not found' error
- test_edit_memory_rejected_for_cross_agent: PATCH is rejected (403) when
  session.agent_id != URL agent_id; the write service is never invoked
- test_edit_nonexistent_memory: `memanto edit <id>` surfaces a non-zero
  exit + the missing memory id when update_memory raises

Same pattern as PR moorcheh-ai#733; both can be merged independently of PR moorcheh-ai#633.
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