Skip to content

feat(mcp): save reminder on inactivity + session activity score#178

Merged
Alan-TheGentleman merged 1 commit into
mainfrom
feat/save-reminder-activity-score
Apr 12, 2026
Merged

feat(mcp): save reminder on inactivity + session activity score#178
Alan-TheGentleman merged 1 commit into
mainfrom
feat/save-reminder-activity-score

Conversation

@Alan-TheGentleman

Copy link
Copy Markdown
Collaborator

Summary

  • When no mem_save has been called for 10+ minutes in a session, a nudge is appended to mem_search and mem_context responses
  • On mem_session_summary, an activity score (tool calls vs saves) is appended so agents can identify sessions with potential context loss
  • Per-project tracking via SessionActivity (mutex-protected, cleaned up on session end)

Why

AI agents have instructions to save memories proactively, but saving is an opt-in action that competes with the main task flow. When the agent is in an intense execution loop, it forgets to call mem_save. The server now nudges the agent instead of relying on the agent to remember.

Implementation

  • internal/mcp/activity.goSessionActivity tracker with RecordToolCall, RecordSave, NudgeIfNeeded, ActivityScore, ClearSession
  • Unified session ID resolution via defaultSessionID(project) across all handlers
  • Wired into handleSearch, handleContext, handleSave, handleSessionStart, handleSessionEnd, handleSessionSummary, handleCapturePassive
  • Injectable now function for deterministic testing
  • ~30 tokens per nudge, zero extra tokens for activity score (piggybacks on existing responses)

Test plan

  • Unit tests: nudge timing, save resets timer, activity score formatting, pluralization, clear session, idle suppression, concurrent access (7 tests)
  • Integration tests: nudge in search output, score in summary output, clear on session end, passive capture tracking, session start ID mapping (5 tests)
  • Race detection: go test -race passes
  • Full suite: go test ./... — 10/10 packages pass
  • Judgment Day: 2 rounds, both judges pass clean

Closes #177

When no mem_save has been called for 10+ minutes in a session, append
a nudge to mem_search and mem_context responses reminding the agent to
persist decisions and discoveries.

On mem_session_summary, append an activity score showing tool calls vs
saves so agents and users can identify sessions with potential context
loss.

Implementation:
- SessionActivity tracker with per-project state (mutex-protected)
- Unified session ID resolution via defaultSessionID(project)
- ClearSession on session end to prevent unbounded map growth
- handleCapturePassive participates in activity tracking
- Conditional pluralization in score output

Closes #177
@Alan-TheGentleman Alan-TheGentleman added type:feature New feature status:approved Approved for implementation labels Apr 12, 2026
Copilot AI review requested due to automatic review settings April 12, 2026 13:49
@Alan-TheGentleman
Alan-TheGentleman merged commit 9f87509 into main Apr 12, 2026
12 checks passed

Copilot AI 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.

Pull request overview

Adds server-side session activity tracking to nudge agents to call mem_save after inactivity and to surface a session activity score in mem_session_summary.

Changes:

  • Introduces SessionActivity to track tool calls/saves per (project-scoped) session and generate inactivity nudges + activity scores.
  • Wires activity tracking into MCP handlers (mem_search, mem_context, mem_save, session start/end/summary, passive capture).
  • Adds unit + integration tests validating nudges, activity score formatting, session clearing, and concurrency behavior.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
internal/mcp/mcp.go Wires SessionActivity into MCP server/tool handlers; appends nudges and activity score; clears tracking on session end.
internal/mcp/activity.go New mutex-protected activity tracker providing RecordToolCall, RecordSave, NudgeIfNeeded, ActivityScore, ClearSession.
internal/mcp/mcp_test.go Updates handler tests for new dependency and adds integration tests for nudge/score/clear behavior.
internal/mcp/activity_test.go Adds focused unit tests for timing, pluralization, idle suppression, clearing, and concurrent access.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread internal/mcp/mcp.go
Comment on lines +1123 to +1129
// Determine the project for this session to clean up activity tracking
project := cfg.DefaultProject
if p, _ := req.GetArguments()["project"].(string); p != "" {
project = p
}
project, _ = store.NormalizeProject(project)
activity.ClearSession(defaultSessionID(project))

Copilot AI Apr 12, 2026

Copy link

Choose a reason for hiding this comment

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

Activity cleanup in handleSessionEnd derives project from the request (or cfg.DefaultProject) rather than the session being ended. Existing clients may not send project, and store.EndSession is a no-op for missing IDs, so this can clear the wrong project's activity (or clear activity even when no session existed). Consider looking up the session's project via s.GetSession(id) (before/after ending) and only calling activity.ClearSession(defaultSessionID(sess.Project)) when the session exists.

Copilot uses AI. Check for mistakes.
Comment thread internal/mcp/mcp_test.go
s := newMCPTestStore(t)

// Seed a memory to search for
s.CreateSession("s1", "myproject", "")

Copilot AI Apr 12, 2026

Copy link

Choose a reason for hiding this comment

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

This test calls s.CreateSession(...) without checking the returned error. If setup fails, the test may pass/fail for the wrong reason; please assert err == nil.

Suggested change
s.CreateSession("s1", "myproject", "")
if err := s.CreateSession("s1", "myproject", ""); err != nil {
t.Fatalf("CreateSession: %v", err)
}

Copilot uses AI. Check for mistakes.
Comment thread internal/mcp/mcp_test.go
Comment on lines +1837 to +1843
s.AddObservation(store.AddObservationParams{
SessionID: "s1",
Type: "manual",
Title: "test memory",
Content: "some content",
Project: "myproject",
})

Copilot AI Apr 12, 2026

Copy link

Choose a reason for hiding this comment

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

This test ignores the return values from s.AddObservation(...) (it returns an ID and error). Please capture and assert the error to avoid false positives if seeding fails.

Suggested change
s.AddObservation(store.AddObservationParams{
SessionID: "s1",
Type: "manual",
Title: "test memory",
Content: "some content",
Project: "myproject",
})
_, err := s.AddObservation(store.AddObservationParams{
SessionID: "s1",
Type: "manual",
Title: "test memory",
Content: "some content",
Project: "myproject",
})
if err != nil {
t.Fatalf("AddObservation: %v", err)
}

Copilot uses AI. Check for mistakes.
Comment thread internal/mcp/mcp_test.go
}

// Create session in store so EndSession works
s.CreateSession("real-session-id", project, "")

Copilot AI Apr 12, 2026

Copy link

Choose a reason for hiding this comment

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

This test calls s.CreateSession(...) without checking the returned error. Please assert the error so the test can't silently proceed with invalid setup.

Suggested change
s.CreateSession("real-session-id", project, "")
if _, err := s.CreateSession("real-session-id", project, ""); err != nil {
t.Fatalf("CreateSession setup failed: %v", err)
}

Copilot uses AI. Check for mistakes.
rubenqc pushed a commit to cloudopstudio/engram that referenced this pull request Apr 14, 2026
…Gentleman-Programming#178)

When no mem_save has been called for 10+ minutes in a session, append
a nudge to mem_search and mem_context responses reminding the agent to
persist decisions and discoveries.

On mem_session_summary, append an activity score showing tool calls vs
saves so agents and users can identify sessions with potential context
loss.

Implementation:
- SessionActivity tracker with per-project state (mutex-protected)
- Unified session ID resolution via defaultSessionID(project)
- ClearSession on session end to prevent unbounded map growth
- handleCapturePassive participates in activity tracking
- Conditional pluralization in score output

Closes Gentleman-Programming#177
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status:approved Approved for implementation type:feature New feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(mcp): save reminder on inactivity + session activity score

2 participants