mirror of
https://github.com/basicmachines-co/basic-memory
synced 2026-06-21 13:47:35 +00:00
306e562281
Signed-off-by: phernandez <paul@basicmachines.co>
345 lines
16 KiB
Markdown
345 lines
16 KiB
Markdown
# Post-v0.18.0 Test Plan and Acceptance Criteria
|
||
|
||
## Goal
|
||
|
||
Define a complete validation plan for all major features merged after `v0.18.0`, combining:
|
||
|
||
- Coverage-gap-driven automated tests
|
||
- Real MCP server integration tests (no mocks for target flows)
|
||
- Manual MCP verification via LLM-driven tool calls
|
||
|
||
This plan is based on commits in `v0.18.0..HEAD` and the latest `just check` coverage output.
|
||
|
||
## Scope Window
|
||
|
||
- Start tag: `v0.18.0` (2026-01-28)
|
||
- End: current `main`
|
||
- Change volume: 12 feature commits + 14 bug-fix commits (+ release chores/hotfixes)
|
||
|
||
## Execution Strategy
|
||
|
||
1. Stabilize all feature-level acceptance criteria in automated tests first.
|
||
2. Add black-box MCP integration tests for semantic search + schema (real server startup).
|
||
3. Run manual MCP tool-call verification to confirm real UX and routing behavior.
|
||
4. Re-run full gate: `just check` + targeted integration packs.
|
||
|
||
## Global Quality Gates
|
||
|
||
- Feature criteria below must all pass.
|
||
- No regressions in existing suites.
|
||
- Coverage improves in targeted low-coverage feature modules.
|
||
- SQLite and Postgres parity for search/semantic features.
|
||
|
||
## Priority Coverage Gaps (from latest run)
|
||
|
||
These are the most important post-`v0.18.0` feature modules currently under-covered:
|
||
|
||
- `src/basic_memory/mcp/tools/schema.py` (27%)
|
||
- `src/basic_memory/mcp/clients/schema.py` (36%)
|
||
- `src/basic_memory/mcp/tools/ui_sdk.py` (43%)
|
||
- `src/basic_memory/mcp/tools/search.py` (73%)
|
||
- `src/basic_memory/repository/postgres_search_repository.py` (63%)
|
||
- `src/basic_memory/mcp/async_client.py` (82%)
|
||
- `src/basic_memory/api/v2/routers/schema_router.py` (80%)
|
||
|
||
## Feature Acceptance Criteria and Test Plan
|
||
|
||
### 1) Schema System (`c97733d`) — DONE
|
||
|
||
### Acceptance criteria
|
||
|
||
- `schema_validate`, `schema_infer`, and `schema_diff` produce consistent outcomes across CLI/API/MCP for the same fixture set.
|
||
- Strict validation fails deterministically on required-field/type violations.
|
||
- Validation warnings are stable and machine-readable in non-strict mode.
|
||
- Inference output is deterministic for unchanged input corpus.
|
||
- Drift diff output is deterministic and identifies missing/extra/type-mismatch fields correctly.
|
||
|
||
### Existing coverage anchor points
|
||
|
||
- `tests/schema/*`
|
||
- `tests/api/v2/test_schema_router.py`
|
||
- `test-int/test_schema/*`
|
||
|
||
### Gaps to close — DONE
|
||
|
||
- ~~MCP schema tool branches (`src/basic_memory/mcp/tools/schema.py`)~~ — 18 tests in `tests/mcp/test_tool_schema.py`
|
||
- ~~MCP schema client behavior (`src/basic_memory/mcp/clients/schema.py`)~~ — `tests/mcp/test_client_schema.py`
|
||
- ~~Schema router error-path branches (`src/basic_memory/api/v2/routers/schema_router.py`)~~ — `tests/api/v2/test_schema_router.py`
|
||
|
||
### Planned additions — DONE
|
||
|
||
- ~~Add MCP tool tests for `schema_validate` strict + non-strict result shapes.~~ **DONE**
|
||
- ~~Add MCP tool tests for `schema_infer` with explicit `entity_type` and inferred type fallback.~~ **DONE**
|
||
- ~~Add MCP tool tests for `schema_diff` empty-diff and non-empty-diff paths.~~ **DONE**
|
||
- ~~Add API tests for schema router invalid payload/edge error handling.~~ **DONE**
|
||
- Add integration test that starts MCP server and calls schema tools end-to-end on fixture notes. — deferred to backlog item 4.
|
||
|
||
### 2) Semantic Search (`0777879`, `1428d18`, `344e651`) — DONE
|
||
|
||
### Acceptance criteria
|
||
|
||
- `search_type=text|vector|hybrid` returns expected ranked results on canonical semantic corpus.
|
||
- Missing semantic dependencies fail fast with actionable install guidance.
|
||
- Reindex and provider/model changes produce valid vectors without dimension mismatch.
|
||
- SQLite and Postgres produce equivalent behavior for semantic modes on the same dataset.
|
||
- Generated-column migration path is valid on SQLite environments in use.
|
||
|
||
### Existing coverage anchor points
|
||
|
||
- `tests/repository/test_sqlite_vector_search_repository.py`
|
||
- `tests/repository/test_postgres_search_repository.py`
|
||
- `tests/services/test_semantic_search.py`
|
||
- `tests/mcp/test_tool_search.py`
|
||
- `test-int/test_search_performance_benchmark.py`
|
||
|
||
### Gaps to close — DONE
|
||
|
||
- ~~Uncovered Postgres vector/hybrid branches~~ — 20 tests in `tests/repository/test_postgres_search_repository_unit.py` + 5 integration tests in `test-int/semantic/test_semantic_coverage.py`
|
||
- ~~MCP search semantic/output branches~~ — expanded `tests/mcp/test_tool_search.py`
|
||
|
||
### Planned additions — DONE
|
||
|
||
- ~~Expand Postgres repository tests for vector query composition edge cases.~~ **DONE**
|
||
- ~~Expand Postgres repository tests for hybrid fusion ranking and pagination branches.~~ **DONE**
|
||
- ~~Expand Postgres repository tests for embedding/provider error handling branches.~~ **DONE**
|
||
- ~~Expand MCP search tool tests for vector/hybrid output formatting branches.~~ **DONE**
|
||
- ~~Expand MCP search tool tests for semantic-disabled and missing-dependency failures.~~ **DONE**
|
||
- Add MCP integration tests that start server and execute semantic `search_notes` tool calls. — deferred to backlog item 4.
|
||
|
||
### Semantic search quality benchmarks (NEW)
|
||
|
||
Full benchmark suite in `test-int/semantic/` covering 5 backend×provider combinations:
|
||
- `sqlite-fts`, `sqlite-fastembed`, `postgres-fts`, `postgres-fastembed`, `postgres-openai`
|
||
- Quality metrics: hit@1, recall@5, MRR@10 with per-query timing
|
||
- Realistic corpus with cross-topic vocabulary overlap (240 notes, 4 topics)
|
||
- Rich CLI viewer: `just semantic-report`
|
||
- JSON artifact output: `just test-semantic-report`
|
||
|
||
Key finding: **FastEmbed (384-d local ONNX) matches or exceeds OpenAI (1536-d) quality at 30x lower latency.** Recommending FastEmbed as default for both local and cloud deployments.
|
||
|
||
### 3) Per-Project Local/Cloud Routing + API Key Auth (`d84708c`, `ed94877`, `312662f`) — DONE
|
||
|
||
### Acceptance criteria
|
||
|
||
- Project mode (`local`/`cloud`) persists and displays correctly.
|
||
- Routing selects ASGI for local projects and HTTP+Bearer for cloud projects.
|
||
- Cloud project without key fails with explicit remediation (`cloud set-key`/`cloud create-key`).
|
||
- Resolution precedence is correct (factory > force-local > per-project cloud > global fallback > local).
|
||
- Watch/sync only run for local projects.
|
||
|
||
### Existing coverage anchor points
|
||
|
||
- `tests/mcp/test_async_client_modes.py`
|
||
- `tests/cli/test_project_set_cloud_local.py`
|
||
- `tests/mcp/test_project_context.py`
|
||
- `tests/test_project_resolver.py`
|
||
- `tests/sync/test_watch_service_reload.py`
|
||
|
||
### Gaps to close — DONE
|
||
|
||
- ~~Cloud routing branch gaps in `src/basic_memory/mcp/async_client.py`~~ — expanded `tests/mcp/test_async_client_modes.py`
|
||
|
||
### Planned additions — DONE
|
||
|
||
- ~~Add branch-focused tests for all unresolved routing branches in `get_client()`.~~ **DONE**
|
||
- Add MCP integration scenario with mixed local/cloud project config — deferred to backlog item 4.
|
||
|
||
### 4) Project-Prefixed Permalinks + Memory URL Routing (`545804f`) — DONE
|
||
|
||
### Acceptance criteria
|
||
|
||
- Project-prefixed permalinks are generated consistently on create/update/import flows.
|
||
- Memory URLs resolve to the correct project/entity even with duplicate note titles.
|
||
- `read_note`, `search`, `build_context`, write/edit/move flows preserve project identity correctly.
|
||
- Link resolution remains correct for context-aware wikilinks.
|
||
|
||
### Existing coverage anchor points
|
||
|
||
- `tests/utils/test_permalink_formatting.py`
|
||
- `tests/mcp/test_tool_read_note.py`
|
||
- `tests/mcp/test_tool_search.py`
|
||
- `tests/services/test_context_service.py`
|
||
- `test-int/mcp/test_read_note_integration.py`
|
||
|
||
### Gaps to close
|
||
|
||
- No major coverage alarm in report, but keep as regression-critical due broad impact surface.
|
||
|
||
### Planned additions — DONE
|
||
|
||
- ~~Add one integration test with colliding titles across two projects and assert URL routing invariants.~~ **DONE** — `test-int/mcp/test_permalink_collision_integration.py` (2 tests: collision across projects + memory:// URL routing with project prefix)
|
||
|
||
### 5) MCP UI Variants + TUI Output (`8bc03d1`) — DONE
|
||
|
||
### Acceptance criteria
|
||
|
||
- UI resource variant selection (`tool-ui`, `vanilla`, `mcp-ui`) follows env configuration.
|
||
- `search_notes` and `read_note` expose expected resource metadata for UI hosts.
|
||
- `ascii`/`ansi` outputs are deterministic and stable for terminal clients.
|
||
|
||
### Existing coverage anchor points
|
||
|
||
- `tests/mcp/test_tool_contracts.py`
|
||
- `test-int/mcp/test_output_format_json_integration.py`
|
||
- `test-int/mcp/test_ui_sdk_integration.py`
|
||
|
||
### Gaps to close — DONE
|
||
|
||
- ~~`src/basic_memory/mcp/tools/ui_sdk.py` branch coverage~~ — `tests/mcp/test_ui_sdk.py`
|
||
- ~~`src/basic_memory/mcp/ui/sdk.py` and `src/basic_memory/mcp/ui/templates.py` branch coverage~~ — `tests/mcp/test_ui_templates.py` + `tests/mcp/test_ui_resources.py`
|
||
|
||
### Planned additions — DONE
|
||
|
||
- ~~Add unit tests for UI SDK metadata generation and template selection branches.~~ **DONE** — 31 tests
|
||
- ~~Add integration assertion for variant-specific resource URIs and metadata payload shape.~~ **DONE**
|
||
|
||
### 6) Watch Command (`8df88e4`) — DONE
|
||
|
||
### Acceptance criteria
|
||
|
||
- `basic-memory watch` starts and processes create/update/delete events.
|
||
- Watch restart/reload path does not duplicate watchers.
|
||
- Cloud-mode projects are excluded from active watcher set.
|
||
|
||
### Existing coverage anchor points
|
||
|
||
- `tests/cli/test_watch.py`
|
||
- `tests/sync/test_coordinator.py`
|
||
- `tests/sync/test_watch_service_reload.py`
|
||
|
||
### Planned additions — DONE
|
||
|
||
- ~~Add one stress-style integration test for rapid file changes and watcher stability.~~ **DONE** — `tests/sync/test_watch_service_stress.py` (3 tests: 50-file batch, mixed add/modify/delete batch, rapid modifications to same file)
|
||
|
||
### 7) CLI JSON Output (`a47c9c0`) — DONE
|
||
|
||
### Acceptance criteria
|
||
|
||
- `--format json` returns valid JSON with stable keys for success paths.
|
||
- Error paths also return JSON-shaped output with correct non-zero exits.
|
||
- Default human output remains unchanged.
|
||
|
||
### Existing coverage anchor points
|
||
|
||
- `tests/cli/test_cli_tool_json_output.py`
|
||
- `test-int/cli/test_cli_tool_json_integration.py`
|
||
|
||
### Planned additions — DONE
|
||
|
||
- ~~Add one failure-path integration test per high-use tool command.~~ **DONE** — `test-int/cli/test_cli_tool_json_failure_integration.py` (4 tests: read-note not found, write-note missing content, write→read roundtrip, recent-activity empty project)
|
||
|
||
### 8) Search/Edit and Metadata Fixes (`530cbac`, `f1d50c2`, `8838571`, `009e849`) — DONE
|
||
|
||
### Acceptance criteria
|
||
|
||
- Metadata filters produce consistent results on SQLite and Postgres.
|
||
- `tag:` shorthand works alone and with mixed query terms.
|
||
- Fast write/edit paths preserve `external_id` and metadata integrity.
|
||
|
||
### Existing coverage anchor points
|
||
|
||
- `tests/repository/test_metadata_filters.py`
|
||
- `tests/repository/test_search_repository.py`
|
||
- `tests/services/test_search_service.py`
|
||
|
||
### Planned additions — DONE
|
||
|
||
- ~~Add Postgres-specific metadata filter edge-case tests to mirror SQLite assertions exactly.~~ **DONE** — `tests/repository/test_metadata_filters_edge_cases.py` (6 tests: missing field, AND logic, contains single-element array, nested path missing intermediate, $gte/$lte boundaries, $between inclusive — all pass on both SQLite and Postgres)
|
||
|
||
### 9) Compatibility and Hotfix Regression Pack (`c46d7a6`, `a0e754b`, `343a6e1`, `24ca5f6`, `e3ced49`, `8489a3d`, `b609c4e`, `f6e0a5b`, `7624a20`)
|
||
|
||
### Acceptance criteria
|
||
|
||
- Legacy endpoints required by older CLI versions function without `405` (`GET /projects/projects`, `POST /projects/projects`, `POST /projects/config/sync`).
|
||
- Entity creation conflicts map to conflict status (not 500).
|
||
- `recent_activity` prompt defaults are correct.
|
||
- No spurious `metadata: {}` in serialized frontmatter.
|
||
- Tigris/rclone uses global consistency headers for all transaction types.
|
||
- `bm --version` fast path avoids heavy import path and remains responsive.
|
||
- Default SQLite DB path is isolated by config dir.
|
||
|
||
### Gaps to close
|
||
|
||
- ~~Commits with no direct tests added (`c46d7a6`, `344e651`, `f6e0a5b`) need explicit regression tests.~~ **DONE**
|
||
|
||
### Planned additions — DONE
|
||
|
||
- ~~Add API compat test covering all legacy endpoint methods and payloads.~~ **DONE** — `test_legacy_v1_add_project_endpoint`, `test_legacy_v1_sync_config_endpoint`
|
||
- ~~Add CLI fast-path test for `--version` import behavior/performance guard.~~ **DONE** — `test_bm_version_does_not_import_heavy_modules`
|
||
- ~~Add empty metadata serialization regression test.~~ **DONE** — `test_schema_to_markdown_empty_metadata_no_metadata_key`
|
||
- Add migration safety test for SQLite generated columns (`VIRTUAL` expectation) — deferred, low risk.
|
||
|
||
## MCP Manual Verification Plan (LLM Tool Calls)
|
||
|
||
Run after automated tests pass.
|
||
|
||
### Setup
|
||
|
||
- Start MCP server: `basic-memory mcp --transport stdio`
|
||
- Use an MCP-capable client and issue tool calls directly.
|
||
|
||
### Manual scenarios
|
||
|
||
- Schema: call `schema_validate`, `schema_infer`, and `schema_diff` on known fixtures.
|
||
- Schema: verify error and success payloads match acceptance criteria.
|
||
- Semantic search: call `search_notes` with `search_type=text|vector|hybrid`.
|
||
- Semantic search: verify ranking relevance on semantic fixture queries.
|
||
- Routing: call tools with explicit project on mixed local/cloud setup.
|
||
- Routing: verify success/failure paths with and without API key.
|
||
- Permalink routing: read/write/search notes across projects with colliding titles.
|
||
- Permalink routing: verify memory URL routing correctness.
|
||
- UI/TUI: call `search_notes` and `read_note` with UI variants and `output_format=text|json`.
|
||
- UI/TUI: verify payload/resource format and metadata completeness.
|
||
|
||
## Implementation Backlog (Ordered)
|
||
|
||
1. ~~Fill schema MCP/client/router coverage gaps.~~ **DONE** — 18 tests in `test_tool_schema.py` + `test_client_schema.py`
|
||
2. ~~Fill semantic search MCP + Postgres repository gaps.~~ **DONE** — 20 tests in `test_postgres_search_repository_unit.py` + `test_tool_search.py`
|
||
3. ~~Add compatibility regression tests (legacy endpoints, migration, version fast path).~~ **DONE** — 5 tests across 3 files (see below)
|
||
4. ~~Add feature-level integration tests (permalinks, watch, CLI JSON, metadata filters).~~ **DONE** — 15 tests across 4 files (see items 4, 6, 7, 8 above)
|
||
5. ~~Expand UI SDK and template branch tests.~~ **DONE** — 31 tests in `test_ui_templates.py` + `test_ui_sdk.py` + `test_ui_resources.py`
|
||
6. ~~Run full gate and capture results in a short release readiness summary.~~ **DONE** — see results below
|
||
|
||
### Full Gate Results (`just check`)
|
||
|
||
| Phase | Result |
|
||
|-------|--------|
|
||
| lint | PASS |
|
||
| format | PASS |
|
||
| typecheck | PASS |
|
||
| Unit tests (SQLite) | 1788 passed, 15 skipped |
|
||
| Integration tests (SQLite) | 243 passed, 4 skipped, 10 deselected |
|
||
| Unit tests (Postgres) | 1760 passed, 28 skipped |
|
||
| Integration tests (Postgres) | 234 passed, 13 skipped, 10 deselected |
|
||
|
||
**0 failures. 10 deselected = semantic benchmark tests (run separately via `just test-semantic`).**
|
||
|
||
### Item 3 Details — Compatibility Regression Tests
|
||
|
||
| Test | File | What it covers |
|
||
|------|------|----------------|
|
||
| `test_legacy_v1_add_project_endpoint` | `tests/api/v2/test_project_router.py` | POST `/projects/projects` legacy route reachable (idempotent path) |
|
||
| `test_legacy_v1_sync_config_endpoint` | `tests/api/v2/test_project_router.py` | POST `/projects/config/sync` legacy route reachable |
|
||
| `test_bm_version_does_not_import_heavy_modules` | `tests/cli/test_cli_exit.py` | `bm --version` fast path does not load `basic_memory.mcp` |
|
||
| `test_schema_to_markdown_empty_metadata_no_metadata_key` | `tests/markdown/test_entity_parser_error_handling.py` | `schema_to_markdown()` with `entity_metadata={}` emits no `metadata:` key |
|
||
| `test_legacy_v1_list_projects_endpoint` | `tests/api/v2/test_project_router.py` | (pre-existing) GET `/projects/projects` legacy route |
|
||
|
||
**Suite totals after item 3: 1764 passed, 15 skipped, 0 failures.**
|
||
|
||
## Suggested Commands
|
||
|
||
- Full suite: `just check`
|
||
- Fast loop: `just fast-check`
|
||
- E2E consistency: `just doctor`
|
||
- SQLite focused: `just test-sqlite`
|
||
- Postgres focused: `just test-postgres`
|
||
- Schema integration: `pytest test-int/test_schema -q`
|
||
- Semantic + repo focus: `pytest tests/repository/test_postgres_search_repository.py tests/mcp/test_tool_search.py tests/services/test_semantic_search.py -q`
|
||
- MCP integration focus: `pytest test-int/mcp -q`
|
||
|
||
## Exit Criteria for This Plan
|
||
|
||
- All feature acceptance criteria above are validated.
|
||
- All identified high-priority coverage gaps are addressed or explicitly documented as intentional.
|
||
- Manual MCP verification scenarios complete with no P0/P1 findings.
|