Skip to content

Commit be04867

Browse files
authored
Merge branch 'main' into fix/integration-test-failures
Signed-off-by: Paul Hernandez <60959+phernandez@users.noreply.github.com>
2 parents 4f299eb + 622d37e commit be04867

71 files changed

Lines changed: 2153 additions & 1647 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/settings.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"enabledPlugins": {
3+
"basic-memory@basicmachines": true
4+
}
5+
}

.github/workflows/test.yml

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -78,21 +78,7 @@ jobs:
7878
python-version: [ "3.12", "3.13" ]
7979
runs-on: ubuntu-latest
8080

81-
# Postgres service (only available on Linux runners)
82-
services:
83-
postgres:
84-
image: postgres:17
85-
env:
86-
POSTGRES_DB: basic_memory_test
87-
POSTGRES_USER: basic_memory_user
88-
POSTGRES_PASSWORD: dev_password
89-
options: >-
90-
--health-cmd pg_isready
91-
--health-interval 10s
92-
--health-timeout 5s
93-
--health-retries 5
94-
ports:
95-
- 5433:5432
81+
# Note: No services section needed - testcontainers handles Postgres in Docker
9682

9783
steps:
9884
- uses: actions/checkout@v4
@@ -121,7 +107,7 @@ jobs:
121107
run: |
122108
uv pip install -e .[dev]
123109
124-
- name: Run tests (Postgres)
110+
- name: Run tests (Postgres via testcontainers)
125111
run: |
126112
uv pip install pytest pytest-cov
127113
just test-postgres

CHANGELOG.md

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,98 @@
11
# CHANGELOG
22

3+
## v0.16.3 (2025-12-20)
4+
5+
### Features
6+
7+
- **#439**: Add PostgreSQL database backend support
8+
([`fb5e9e1`](https://github.com/basicmachines-co/basic-memory/commit/fb5e9e1))
9+
- Full PostgreSQL/Neon database support as alternative to SQLite
10+
- Async connection pooling with asyncpg
11+
- Alembic migrations support for both backends
12+
- Configurable via `BASIC_MEMORY_DATABASE_BACKEND` environment variable
13+
14+
- **#441**: Implement API v2 with ID-based endpoints (Phase 1)
15+
([`28cc522`](https://github.com/basicmachines-co/basic-memory/commit/28cc522))
16+
- New ID-based API endpoints for improved performance
17+
- Foundation for future API enhancements
18+
- Backward compatible with existing endpoints
19+
20+
- Add project_id to Relation and Observation for efficient project-scoped queries
21+
([`a920a9f`](https://github.com/basicmachines-co/basic-memory/commit/a920a9f))
22+
- Enables faster queries in multi-project environments
23+
- Improved database schema for cloud deployments
24+
25+
- Add bulk insert with ON CONFLICT handling for relations
26+
([`0818bda`](https://github.com/basicmachines-co/basic-memory/commit/0818bda))
27+
- Faster relation creation during sync operations
28+
- Handles duplicate relations gracefully
29+
30+
### Performance
31+
32+
- Lightweight permalink resolution to avoid eager loading
33+
([`6f99d2e`](https://github.com/basicmachines-co/basic-memory/commit/6f99d2e))
34+
- Reduces database queries during entity lookups
35+
- Improved response times for read operations
36+
37+
### Bug Fixes
38+
39+
- **#464**: Pin FastMCP to 2.12.3 to fix MCP tools visibility
40+
([`f227ef6`](https://github.com/basicmachines-co/basic-memory/commit/f227ef6))
41+
- Fixes issue where MCP tools were not visible to Claude
42+
- Reverts to last known working FastMCP version
43+
44+
- **#458**: Reduce watch service CPU usage by increasing reload interval
45+
([`897b1ed`](https://github.com/basicmachines-co/basic-memory/commit/897b1ed))
46+
- Lowers CPU usage during file watching
47+
- More efficient resource utilization
48+
49+
- **#456**: Await background sync task cancellation in lifespan shutdown
50+
([`efbc758`](https://github.com/basicmachines-co/basic-memory/commit/efbc758))
51+
- Prevents hanging on shutdown
52+
- Clean async task cleanup
53+
54+
- **#434**: Respect --project flag in background sync
55+
([`70bb10b`](https://github.com/basicmachines-co/basic-memory/commit/70bb10b))
56+
- Background sync now correctly uses specified project
57+
- Fixes multi-project sync issues
58+
59+
- **#446**: Fix observation parsing and permalink limits
60+
([`73d940e`](https://github.com/basicmachines-co/basic-memory/commit/73d940e))
61+
- Handles edge cases in observation content
62+
- Prevents permalink truncation issues
63+
64+
- **#424**: Handle periods in kebab_filenames mode
65+
([`b004565`](https://github.com/basicmachines-co/basic-memory/commit/b004565))
66+
- Fixes filename handling for files with multiple periods
67+
- Improved kebab-case conversion
68+
69+
- Fix Postgres/Neon connection settings and search index dedupe
70+
([`b5d4fb5`](https://github.com/basicmachines-co/basic-memory/commit/b5d4fb5))
71+
- Optimized connection pooling for Postgres
72+
- Prevents duplicate search index entries
73+
74+
### Testing & CI
75+
76+
- Replace py-pglite with testcontainers for Postgres testing
77+
([`c462faf`](https://github.com/basicmachines-co/basic-memory/commit/c462faf))
78+
- More reliable Postgres testing infrastructure
79+
- Uses Docker-based test containers
80+
81+
- Add PostgreSQL testing to GitHub Actions workflow
82+
([`66b91b2`](https://github.com/basicmachines-co/basic-memory/commit/66b91b2))
83+
- CI now tests both SQLite and PostgreSQL backends
84+
- Ensures cross-database compatibility
85+
86+
- **#416**: Add integration test for read_note with underscored folders
87+
([`0c12a39`](https://github.com/basicmachines-co/basic-memory/commit/0c12a39))
88+
- Verifies folder name handling edge cases
89+
90+
### Internal
91+
92+
- Cloud compatibility fixes and performance improvements (#454)
93+
- Remove logfire instrumentation for cleaner production deployments
94+
- Truncate content_stems to fix Postgres 8KB index row limit
95+
396
## v0.16.2 (2025-11-16)
497

598
### Bug Fixes

CLAUDE.md

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,14 @@ See the [README.md](README.md) file for a project overview.
1515
### Build and Test Commands
1616

1717
- Install: `just install` or `pip install -e ".[dev]"`
18-
- Run all tests (with coverage): `just test` - Runs both unit and integration tests with unified coverage
19-
- Run unit tests only: `just test-unit` - Fast, no coverage
20-
- Run integration tests only: `just test-int` - Fast, no coverage
21-
- Generate HTML coverage: `just coverage` - Opens in browser
18+
- Run all tests (SQLite + Postgres): `just test`
19+
- Run all tests against SQLite: `just test-sqlite`
20+
- Run all tests against Postgres: `just test-postgres` (uses testcontainers)
21+
- Run unit tests (SQLite): `just test-unit-sqlite`
22+
- Run unit tests (Postgres): `just test-unit-postgres`
23+
- Run integration tests (SQLite): `just test-int-sqlite`
24+
- Run integration tests (Postgres): `just test-int-postgres`
25+
- Generate HTML coverage: `just coverage`
2226
- Single test: `pytest tests/path/to/test_file.py::test_function_name`
2327
- Run benchmarks: `pytest test-int/test_sync_performance_benchmark.py -v -m "benchmark and not slow"`
2428
- Lint: `just lint` or `ruff check . --fix`
@@ -30,6 +34,8 @@ See the [README.md](README.md) file for a project overview.
3034

3135
**Note:** Project requires Python 3.12+ (uses type parameter syntax and `type` aliases introduced in 3.12)
3236

37+
**Postgres Testing:** Uses [testcontainers](https://testcontainers-python.readthedocs.io/) which automatically spins up a Postgres instance in Docker. No manual database setup required - just have Docker running.
38+
3339
### Test Structure
3440

3541
- `tests/` - Unit tests for individual components (mocked, fast)
@@ -76,8 +82,10 @@ See the [README.md](README.md) file for a project overview.
7682
- SQLite is used for indexing and full text search, files are source of truth
7783
- Testing uses pytest with asyncio support (strict mode)
7884
- Unit tests (`tests/`) use mocks when necessary; integration tests (`test-int/`) use real implementations
79-
- Test database uses in-memory SQLite
80-
- Each test runs in a standalone environment with in-memory SQLite and tmp_file directory
85+
- By default, tests run against SQLite (fast, no Docker needed)
86+
- Set `BASIC_MEMORY_TEST_POSTGRES=1` to run against Postgres (uses testcontainers - Docker required)
87+
- Each test runs in a standalone environment with isolated database and tmp_path directory
88+
- CI runs SQLite and Postgres tests in parallel for faster feedback
8189
- Performance benchmarks are in `test-int/test_sync_performance_benchmark.py`
8290
- Use pytest markers: `@pytest.mark.benchmark` for benchmarks, `@pytest.mark.slow` for slow tests
8391

@@ -229,6 +237,11 @@ of using AI just for code generation, we've developed a true collaborative workf
229237
This approach has allowed us to tackle more complex challenges and build a more robust system than either humans or AI
230238
could achieve independently.
231239

240+
**Problem-Solving Guidance:**
241+
- If a solution isn't working after reasonable effort, suggest alternative approaches
242+
- Don't persist with a problematic library or pattern when better alternatives exist
243+
- Example: When py-pglite caused cascading test failures, switching to testcontainers-postgres was the right call
244+
232245
## GitHub Integration
233246

234247
Basic Memory has taken AI-Human collaboration to the next level by integrating Claude directly into the development workflow through GitHub:

README.md

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -433,42 +433,76 @@ See the [Documentation](https://memory.basicmachines.co/) for more info, includi
433433
- [Managing multiple Projects](https://docs.basicmemory.com/guides/cli-reference/#project)
434434
- [Importing data from OpenAI/Claude Projects](https://docs.basicmemory.com/guides/cli-reference/#import)
435435

436+
## Logging
437+
438+
Basic Memory uses [Loguru](https://github.com/Delgan/loguru) for logging. The logging behavior varies by entry point:
439+
440+
| Entry Point | Default Behavior | Use Case |
441+
|-------------|------------------|----------|
442+
| CLI commands | File only | Prevents log output from interfering with command output |
443+
| MCP server | File only | Stdout would corrupt the JSON-RPC protocol |
444+
| API server | File (local) or stdout (cloud) | Docker/cloud deployments use stdout |
445+
446+
**Log file location:** `~/.basic-memory/basic-memory.log` (10MB rotation, 10 days retention)
447+
448+
### Environment Variables
449+
450+
| Variable | Default | Description |
451+
|----------|---------|-------------|
452+
| `BASIC_MEMORY_LOG_LEVEL` | `INFO` | Log level: DEBUG, INFO, WARNING, ERROR |
453+
| `BASIC_MEMORY_CLOUD_MODE` | `false` | When `true`, API logs to stdout with structured context |
454+
| `BASIC_MEMORY_ENV` | `dev` | Set to `test` for test mode (stderr only) |
455+
456+
### Examples
457+
458+
```bash
459+
# Enable debug logging
460+
BASIC_MEMORY_LOG_LEVEL=DEBUG basic-memory sync
461+
462+
# View logs
463+
tail -f ~/.basic-memory/basic-memory.log
464+
465+
# Cloud/Docker mode (stdout logging with structured context)
466+
BASIC_MEMORY_CLOUD_MODE=true uvicorn basic_memory.api.app:app
467+
```
468+
436469
## Development
437470

438471
### Running Tests
439472

440-
Basic Memory supports dual database backends (SQLite and Postgres). Tests are parametrized to run against both backends automatically.
473+
Basic Memory supports dual database backends (SQLite and Postgres). By default, tests run against SQLite. Set `BASIC_MEMORY_TEST_POSTGRES=1` to run against Postgres (uses testcontainers - Docker required).
441474

442475
**Quick Start:**
443476
```bash
444-
# Run SQLite tests (default, no Docker needed)
477+
# Run all tests against SQLite (default, fast)
445478
just test-sqlite
446479

447-
# Run Postgres tests (requires Docker)
480+
# Run all tests against Postgres (uses testcontainers)
448481
just test-postgres
482+
483+
# Run both SQLite and Postgres tests
484+
just test
449485
```
450486

451487
**Available Test Commands:**
452488

453-
- `just test-sqlite` - Run tests against SQLite only (fastest, no Docker needed)
454-
- `just test-postgres` - Run tests against Postgres only (requires Docker)
489+
- `just test` - Run all tests against both SQLite and Postgres
490+
- `just test-sqlite` - Run all tests against SQLite (fast, no Docker needed)
491+
- `just test-postgres` - Run all tests against Postgres (uses testcontainers)
492+
- `just test-unit-sqlite` - Run unit tests against SQLite
493+
- `just test-unit-postgres` - Run unit tests against Postgres
494+
- `just test-int-sqlite` - Run integration tests against SQLite
495+
- `just test-int-postgres` - Run integration tests against Postgres
455496
- `just test-windows` - Run Windows-specific tests (auto-skips on other platforms)
456497
- `just test-benchmark` - Run performance benchmark tests
457-
- `just test-all` - Run all tests including Windows, Postgres, and benchmarks
458-
459-
**Postgres Testing Requirements:**
460498

461-
To run Postgres tests, you need to start the test database:
462-
```bash
463-
docker-compose -f docker-compose-postgres.yml up -d
464-
```
499+
**Postgres Testing:**
465500

466-
Tests will connect to `localhost:5433/basic_memory_test`.
501+
Postgres tests use [testcontainers](https://testcontainers-python.readthedocs.io/) which automatically spins up a Postgres instance in Docker. No manual database setup required - just have Docker running.
467502

468503
**Test Markers:**
469504

470505
Tests use pytest markers for selective execution:
471-
- `postgres` - Tests that run against Postgres backend
472506
- `windows` - Windows-specific database optimizations
473507
- `benchmark` - Performance tests (excluded from default runs)
474508

justfile

Lines changed: 45 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,44 +7,60 @@ install:
77
@echo ""
88
@echo "💡 Remember to activate the virtual environment by running: source .venv/bin/activate"
99

10-
# Run all tests with unified coverage report
11-
test: test-unit test-int
12-
13-
# Run unit tests only (fast, no coverage)
14-
test-unit:
15-
uv run pytest -p pytest_mock -v --no-cov tests
16-
17-
# Run integration tests only (fast, no coverage)
18-
test-int:
19-
uv run pytest -p pytest_mock -v --no-cov test-int
20-
2110
# ==============================================================================
2211
# DATABASE BACKEND TESTING
2312
# ==============================================================================
2413
# Basic Memory supports dual database backends (SQLite and Postgres).
25-
# Tests are parametrized to run against both backends automatically.
14+
# By default, tests run against SQLite (fast, no dependencies).
15+
# Set BASIC_MEMORY_TEST_POSTGRES=1 to run against Postgres (uses testcontainers).
2616
#
2717
# Quick Start:
28-
# just test-sqlite # Run SQLite tests (default, no Docker needed)
29-
# just test-postgres # Run Postgres tests (requires Docker)
18+
# just test # Run all tests against SQLite (default)
19+
# just test-sqlite # Run all tests against SQLite
20+
# just test-postgres # Run all tests against Postgres (testcontainers)
21+
# just test-unit-sqlite # Run unit tests against SQLite
22+
# just test-unit-postgres # Run unit tests against Postgres
23+
# just test-int-sqlite # Run integration tests against SQLite
24+
# just test-int-postgres # Run integration tests against Postgres
3025
#
31-
# For Postgres tests, first start the database:
32-
# docker-compose -f docker-compose-postgres.yml up -d
26+
# CI runs both in parallel for faster feedback.
3327
# ==============================================================================
3428

35-
# Run tests against SQLite only (default backend, skip Postgres/Benchmark tests)
36-
# This is the fastest option and doesn't require any Docker setup.
37-
# Use this for local development and quick feedback.
38-
# Includes Windows-specific tests which will auto-skip on non-Windows platforms.
39-
test-sqlite:
40-
uv run pytest -p pytest_mock -v --no-cov -m "not postgres and not benchmark" tests test-int
41-
42-
# Run tests against Postgres only (requires docker-compose-postgres.yml up)
43-
# First start Postgres: docker-compose -f docker-compose-postgres.yml up -d
44-
# Tests will connect to localhost:5433/basic_memory_test
45-
# To reset the database: just postgres-reset
46-
test-postgres:
47-
uv run pytest -p pytest_mock -v --no-cov -m "postgres and not benchmark" tests test-int
29+
# Run all tests against SQLite and Postgres
30+
test: test-sqlite test-postgres
31+
32+
# Run all tests against SQLite
33+
test-sqlite: test-unit-sqlite test-int-sqlite
34+
35+
# Run all tests against Postgres (uses testcontainers)
36+
test-postgres: test-unit-postgres test-int-postgres
37+
38+
# Run unit tests against SQLite
39+
test-unit-sqlite:
40+
uv run pytest -p pytest_mock -v --no-cov tests
41+
42+
# Run unit tests against Postgres
43+
test-unit-postgres:
44+
BASIC_MEMORY_TEST_POSTGRES=1 uv run pytest -p pytest_mock -v --no-cov tests
45+
46+
# Run integration tests against SQLite
47+
test-int-sqlite:
48+
uv run pytest -p pytest_mock -v --no-cov test-int
49+
50+
# Run integration tests against Postgres
51+
# Note: Uses timeout due to FastMCP Client + asyncpg cleanup hang (tests pass, process hangs on exit)
52+
# See: https://github.com/jlowin/fastmcp/issues/1311
53+
test-int-postgres:
54+
#!/usr/bin/env bash
55+
set -euo pipefail
56+
# Use gtimeout (macOS/Homebrew) or timeout (Linux)
57+
TIMEOUT_CMD=$(command -v gtimeout || command -v timeout || echo "")
58+
if [[ -n "$TIMEOUT_CMD" ]]; then
59+
$TIMEOUT_CMD --signal=KILL 600 bash -c 'BASIC_MEMORY_TEST_POSTGRES=1 uv run pytest -p pytest_mock -v --no-cov test-int' || test $? -eq 137
60+
else
61+
echo "⚠️ No timeout command found, running without timeout..."
62+
BASIC_MEMORY_TEST_POSTGRES=1 uv run pytest -p pytest_mock -v --no-cov test-int
63+
fi
4864

4965
# Reset Postgres test database (drops and recreates schema)
5066
# Useful when Alembic migration state gets out of sync during development

0 commit comments

Comments
 (0)