headroom/tests/test_memory
Chester d0ecc9a556
fix(memory): track MCP retrieval access (#2065)
## Description

Track successful native MCP `memory_search` retrievals in persistent
memory metadata. Returned memories now increment `access_count` and
update `last_accessed`, so MCP usage contributes to memory budget and
retention signals.

Closes #2061

## Type of Change

- [x] Bug fix (non-breaking change that fixes an issue)
- [ ] New feature (non-breaking change that adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] Documentation update
- [ ] Performance improvement
- [ ] Code refactoring (no functional changes)

## Changes Made

- Add an atomic, deduplicated `MemoryStore.record_access` operation.
- Expose access recording through `HierarchicalMemory` and
`LocalBackend`, invalidating stale cache entries.
- Record only the final active memories actually returned by MCP search.
- Fail open if usage metadata cannot be written.
- Add SQLite and MCP regression coverage.

## Testing

- [x] Unit tests pass (`pytest`)
- [ ] Linting passes (`ruff check .`)
- [ ] Type checking passes (`mypy headroom`)
- [x] New tests added for new functionality
- [x] Manual testing performed

### Test Output

```text
pytest tests/test_memory --ignore=tests/test_memory/test_learn_flag.py -q
368 passed, 142 skipped, 158 warnings in 3.28s

pytest tests/test_memory/test_hierarchical.py tests/test_memory/test_mcp_server.py tests/test_memory/test_factory.py -q
40 passed, 53 skipped, 158 warnings in 0.75s
```

## Real Behavior Proof

- Environment: macOS, Python 3.13, SQLite memory store.
- Exact command / steps: save two memories; call `record_access` with
duplicate IDs plus a missing ID; read both rows; call it again for one
row.
- Observed result: each existing memory increments once per call,
duplicates do not double-count, missing IDs are ignored, and
`last_accessed` advances to the supplied timestamp.
- Not tested: the full repository suite and
`tests/test_memory/test_learn_flag.py`; the source checkout does not
include the compiled `headroom._core` Rust extension. Ruff and mypy were
not available in the local development environment; CI remains
authoritative for those checks.

## Review Readiness

- [x] I have performed a self-review
- [x] This PR is ready for human review

## Checklist

- [x] My code follows the project style guidelines
- [x] I have performed a self-review of my code
- [x] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [ ] I have updated the CHANGELOG.md if applicable

## Additional Notes

Documentation and changelog changes are not included because this is an
internal retrieval-metadata correction with no user-facing configuration
change. Access tracking is intentionally fail-open so a metadata write
failure cannot suppress a valid memory search result.

---------

Co-authored-by: xuyidiao <xuyidiao@bytedance.com>
Co-authored-by: JerrettDavis <mxjerrett@gmail.com>
2026-07-12 19:46:13 -04:00
..
__init__.py Add persistent memory system with zero-latency inline extraction 2026-01-14 21:32:09 -08:00
conftest.py fix(ccr): skip Anthropic marker emission when tool injection is deferred (#1273) 2026-06-23 12:48:05 -05:00
test_budget.py Fix ruff lint errors in test files 2026-03-24 15:54:12 -07:00
test_core_operations.py test(memory): skip decorators on offline model misses (#2020) 2026-07-11 10:14:05 -05:00
test_easy.py test(memory): skip decorators on offline model misses (#2020) 2026-07-11 10:14:05 -05:00
test_embedder_mps_serialization.py fix(memory): cap local embedder CPU thread oversubscription (#198) (#1559) 2026-07-01 17:12:02 -05:00
test_embedder_thread_cap.py fix(memory): cap local embedder CPU thread oversubscription (#198) (#1559) 2026-07-01 17:12:02 -05:00
test_extraction.py Add hierarchical memory system with graph + vector storage 2026-01-26 21:58:47 -08:00
test_factory.py Add centralized ML model configuration 2026-02-01 23:47:42 -08:00
test_factory_external.py chore(memory): add EXTERNAL backend extension points 2026-04-20 16:42:10 -07:00
test_hierarchical.py fix(memory): track MCP retrieval access (#2065) 2026-07-12 19:46:13 -04:00
test_learn_flag.py fix(traffic-learner): raise min-evidence default and make it configurable 2026-04-30 17:44:22 +09:00
test_mcp_server.py fix(memory): track MCP retrieval access (#2065) 2026-07-12 19:46:13 -04:00
test_qdrant_env.py feat(memory): resolve Qdrant connection from HEADROOM_QDRANT_* env vars (#31) 2026-04-24 22:16:16 -07:00
test_skip_helpers.py fix(ccr): skip Anthropic marker emission when tool injection is deferred (#1273) 2026-06-23 12:48:05 -05:00
test_traffic_learner.py feat: headroom wrap opencode / unwrap opencode CLI (#1105) 2026-06-22 11:07:12 -05:00
test_writers.py fix: harden learn path handling across platforms 2026-05-09 15:45:26 -07:00