Skip to content

fix(memory): honest memory_forget reporting + lesson delete path - #1132

Merged
rohitg00 merged 8 commits into
rohitg00:mainfrom
SomSamantray:fix/1120-honest-forget-lesson-delete
Aug 2, 2026
Merged

fix(memory): honest memory_forget reporting + lesson delete path#1132
rohitg00 merged 8 commits into
rohitg00:mainfrom
SomSamantray:fix/1120-honest-forget-lesson-delete

Conversation

@SomSamantray

@SomSamantray SomSamantray commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Summary

Calling memory_forget with a lesson id (lsn_*) reported {deleted: 1, success: true} while deleting nothing — the lesson survived recall. mem::forget deleted and counted unconditionally whenever a memoryId was present, without checking whether a memory actually existed in the memories keyspace. It now guards the delete, index cleanup, and counter on the kv.get result (matching mem::governance-delete), so a nonexistent or lesson id honestly returns {success: true, deleted: 0} with no audit row.

Lessons also had no delete path at all: the Lesson type carries a deleted flag honored by save/recall/list/decay-sweep, but nothing ever set it. This adds mem::lesson-delete (soft-delete by id, mirroring the lesson-strengthen guard and audit pattern), exposed as a memory_lesson_delete MCP tool and a POST /agentmemory/lessons/delete REST route (400 for a missing id, 404 for a nonexistent lesson). Re-saving the content of a deleted lesson creates a fresh lesson, giving users a repair path for malformed fingerprint-id lessons.

Fixes #1120. Also resolves the deletion half of #945 (no way to delete/cleanup lessons).

Changes

  • mem::forget memoryId branch: existence-guarded delete/count, matching mem::governance-delete
  • New mem::lesson-delete soft-delete function + lesson_delete audit operation
  • New memory_lesson_delete MCP tool (registry + server dispatch)
  • New api::lesson-delete REST route
  • Count surfaces bumped: 54 MCP tools / 129 REST endpoints across README (incl. badge SVGs), AGENTS.md, INSTALL_FOR_AGENTS.md, plugin manifests, boot log, and regenerated skill references

Testing

  • test/remember-forget-audit.test.ts: regression cases for nonexistent/lesson memoryId returning deleted: 0 with no audit row
  • test/lessons.test.ts: mem::lesson-delete soft-delete, recall/list exclusion, not-found for already-deleted/nonexistent, re-save creates fresh lesson, audit row
  • test/tool-count-consistency.test.ts: EXPECTED_TOOL_COUNT 53 → 54
  • npm test: 1,432 passing; the 8 failures are pre-existing environment-dependent tests (missing @huggingface/transformers package, git-repo-state tests) present on the clean baseline
  • npm run build: succeeds
  • npm run skills:check: passes (15 skills)

Notes

The mem::forget observation/session branches retain their unconditional shape; that keyspace family is tracked separately in #833. Soft-deleted lessons are excluded from recall/list; tombstone pruning, replay-merge resurrection, and export/import handling of the deleted flag are follow-up work.

Post-Deploy Monitoring & Validation

No additional operational monitoring required — this is internal function/tool work with unit-level coverage; the observable contract change is the honest deleted: 0 for nonexistent ids.

Summary by CodeRabbit

  • New Features
    • Added lesson deletion with soft-delete behavior through the MCP tool and REST API.
    • Deleted lessons are excluded from recall and listing results, with audit tracking.
  • Bug Fixes
    • Forgetting a nonexistent memory no longer removes data, updates indexes, or creates audit records.
  • Documentation
    • Updated tool and endpoint counts across documentation and plugin descriptions.
    • Documented the new lesson deletion capabilities.

Calling mem::forget with a lesson id (lsn_*) deleted a nonexistent key
from the memories keyspace, counted it, and reported success. Guard the
delete, index cleanup, and counter on the kv.get result, matching the
mem::governance-delete pattern, so nonexistent ids return
{ success: true, deleted: 0 } with no audit row. Closes rohitg00#1120.
Register mem::lesson-delete to set deleted: true on a lesson, mirroring
the lesson-strengthen existence guard and audit pattern. Read paths
already filter !l.deleted, and re-saving deleted content creates a fresh
lesson. Adds lesson_delete to the audit operation union.
Wire mem::lesson-delete through the MCP tool registry and dispatch
case (memory_lesson_delete) and a POST /agentmemory/lessons/delete REST
route with 400 for a missing lessonId and 404 for a nonexistent lesson.
Adds memory_lesson_delete to the registry, so update every count surface:
tool-count test, README badge and prose, AGENTS.md stats,
INSTALL_FOR_AGENTS.md, plugin manifests and docs, and the two code
comments this change makes stale. REST endpoint count goes 128 to 129
for the new /agentmemory/lessons/delete route.
Cast the lesson-delete trigger result once instead of twice inline, and
restore the lastDecayedAt incremental-delta decay test that was dropped
when the lesson-delete describe block was added.
Review fixes: the lesson-delete REST route now returns the repo-standard
{ error: 'lesson not found' } body on 404 instead of the function-shaped
{ success: false } payload, matching api::memory-by-id. Regenerated the
autogen MCP and REST skill references so memory_lesson_delete and the
lessons/delete route appear in the tables with accurate counts.
@vercel

vercel Bot commented Jul 31, 2026

Copy link
Copy Markdown

@SomSamantray is attempting to deploy a commit to the rohitg00's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Jul 31, 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: a8d4b3d0-23e0-499f-a082-23f5235c9e1d

📥 Commits

Reviewing files that changed from the base of the PR and between 4d95321 and 03c9af3.

📒 Files selected for processing (4)
  • README.md
  • plugin/skills/agentmemory-rest-api/REFERENCE.md
  • src/functions/remember.ts
  • src/triggers/api.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/triggers/api.ts
  • src/functions/remember.ts
  • plugin/skills/agentmemory-rest-api/REFERENCE.md
  • README.md

📝 Walkthrough

Walkthrough

The change adds soft deletion for lessons through internal, MCP, and REST interfaces. It adds audit support and regression coverage. It also corrects nonexistent-memory deletion accounting and updates MCP and REST surface documentation.

Changes

Lesson deletion

Layer / File(s) Summary
Soft-delete handler and accounting
src/types.ts, src/functions/lessons.ts, src/functions/remember.ts, test/lessons.test.ts, test/remember-forget-audit.test.ts
Adds mem::lesson-delete, audit support, soft-delete behavior, validation, and tests. Missing memory IDs no longer produce deletion side effects or audit rows.
MCP and REST deletion interfaces
src/mcp/tools-registry.ts, src/mcp/server.ts, src/triggers/api.ts, plugin/skills/agentmemory-mcp-tools/REFERENCE.md, plugin/skills/agentmemory-rest-api/REFERENCE.md
Adds the memory_lesson_delete MCP tool and authenticated POST /agentmemory/lessons/delete endpoint.
Tool and endpoint count synchronization
AGENTS.md, INSTALL_FOR_AGENTS.md, README.md, plugin/**/*.json, plugin/opencode/README.md, src/mcp/standalone.ts, test/tool-count-consistency.test.ts
Updates documented MCP and REST totals and the expected MCP tool count.

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

Sequence Diagram(s)

sequenceDiagram
  participant MCPClient
  participant RESTClient
  participant memory_lesson_delete
  participant api_lesson_delete
  participant mem_lesson_delete
  MCPClient->>memory_lesson_delete: submit lessonId
  memory_lesson_delete->>mem_lesson_delete: invoke deletion
  RESTClient->>api_lesson_delete: POST lessonId
  api_lesson_delete->>mem_lesson_delete: invoke deletion
  mem_lesson_delete-->>memory_lesson_delete: return serialized result
  mem_lesson_delete-->>api_lesson_delete: return result or not found
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.11% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the two primary changes: accurate memory_forget reporting and the lesson deletion path.
Linked Issues check ✅ Passed The changes address issue #1120 by making memory_forget counts accurate and adding the requested soft-delete path for lessons.
Out of Scope Changes check ✅ Passed The documentation, manifests, API, MCP tool, implementation, and tests directly support the linked issue objectives.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 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.

@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

🧹 Nitpick comments (1)
test/remember-forget-audit.test.ts (1)

125-154: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Assert that the no-op path has no cleanup side effects.

The tests verify deleted: 0 and no audit row. They do not verify that kv.delete or search-index cleanup is skipped. A future regression could perform those side effects and still pass these tests. Add collaborator assertions for the nonexistent memoryId path.

🤖 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 `@test/remember-forget-audit.test.ts` around lines 125 - 154, Extend the
nonexistent-memory tests around registerRememberFunction and mem::forget to
assert that kv.delete and search-index cleanup collaborators are not called for
the missing memoryId. Preserve the existing deleted: 0 result and empty
mem:audit assertions while covering both cleanup side effects.
🤖 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 `@src/mcp/server.ts`:
- Around line 1129-1131: Normalize lesson IDs consistently at both entry points:
in src/mcp/server.ts lines 1129-1131, trim args.lessonId once and pass the
normalized value to the mem::lesson-delete trigger; in src/triggers/api.ts lines
3156-3158, trim the request lesson ID before validating emptiness and pass only
the normalized value onward.
- Around line 1125-1127: Update the memory_lesson_delete handler’s argument
validation before accessing args.lessonId so null or otherwise invalid arguments
return status_code 400 with a validation error. Preserve the existing required,
non-blank lessonId check for valid object arguments, and ensure arguments: null
cannot reach property access or the outer 500 path.

In `@test/lessons.test.ts`:
- Around line 360-363: Remove the unmatched duplicate type assertion from each
SDK trigger result in test/lessons.test.ts at lines 360-363, 396-399, 405-408,
and 430-433, leaving one valid assertion per result so the test file parses
correctly.

---

Nitpick comments:
In `@test/remember-forget-audit.test.ts`:
- Around line 125-154: Extend the nonexistent-memory tests around
registerRememberFunction and mem::forget to assert that kv.delete and
search-index cleanup collaborators are not called for the missing memoryId.
Preserve the existing deleted: 0 result and empty mem:audit assertions while
covering both cleanup side effects.
🪄 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: c981df68-116f-4788-99af-2c13e66e2d44

📥 Commits

Reviewing files that changed from the base of the PR and between 8c90741 and bc4f3c7.

⛔ Files ignored due to path filters (2)
  • assets/tags/light/stat-tools.svg is excluded by !**/*.svg
  • assets/tags/stat-tools.svg is excluded by !**/*.svg
📒 Files selected for processing (20)
  • AGENTS.md
  • INSTALL_FOR_AGENTS.md
  • README.md
  • plugin/.claude-plugin/plugin.json
  • plugin/.codex-plugin/plugin.json
  • plugin/opencode/README.md
  • plugin/plugin.json
  • plugin/skills/agentmemory-mcp-tools/REFERENCE.md
  • plugin/skills/agentmemory-rest-api/REFERENCE.md
  • src/functions/lessons.ts
  • src/functions/remember.ts
  • src/index.ts
  • src/mcp/server.ts
  • src/mcp/standalone.ts
  • src/mcp/tools-registry.ts
  • src/triggers/api.ts
  • src/types.ts
  • test/lessons.test.ts
  • test/remember-forget-audit.test.ts
  • test/tool-count-consistency.test.ts

Comment thread src/mcp/server.ts
Comment thread src/mcp/server.ts
Comment thread test/lessons.test.ts
SomSamantray and others added 2 commits July 31, 2026 23:41
Address CodeRabbit review: trim lessonId once at both the MCP dispatch
and REST route before triggering mem::lesson-delete (whitespace-padded
ids previously 404'd or looked up raw), and extend the nonexistent-
memoryId regression test to assert the no-op path performs no kv.delete
and no search-index cleanup.
@rohitg00
rohitg00 merged commit 5023cf3 into rohitg00:main Aug 2, 2026
1 of 2 checks passed
rohitg00 added a commit that referenced this pull request Aug 2, 2026
Version trio + plugin manifests + supportedVersions + ExportData union
bumped to 0.9.29; CHANGELOG entry covering everything since v0.9.28 with
upgrade notes for the four visible behavior changes.

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

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

Tests: opencode fallback expectations updated to basenames per the
canonicalization, git-toplevel resolution covered with a fixture repo,
new project-scope-parity suite for replay and fs-watcher.
berthojoris added a commit to berthojoris/agentmemory that referenced this pull request Aug 3, 2026
`npm run skills:check` is a separate CI gate from the consistency test
and fails on main for the same root cause: 5023cf3 (rohitg00#1132) registered a
new endpoint without running `npm run skills:gen`, leaving the
AUTOGEN:rest block in plugin/skills/agentmemory-rest-api/REFERENCE.md at
118 registered endpoints.

Only the rest-api reference has a content change; the other four
REFERENCE.md files regenerate byte-identical.

Signed-off-by: Bertho Joris <bertho_joris@yahoo.co.id>
rohitg00 added a commit that referenced this pull request Aug 9, 2026
…aces (#1141)

* chore(release): v0.9.29 with project-scope parity across surfaces

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

* refactor: trim frame-guard comments and drop issue refs from code
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.

memory_forget reports {deleted: 1, success: true} for lesson IDs it never touches

2 participants