Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 17 additions & 21 deletions .claude/commands/spec.md
Original file line number Diff line number Diff line change
@@ -1,41 +1,39 @@
---
allowed-tools: mcp__basic-memory__write_note, mcp__basic-memory__read_note, mcp__basic-memory__search_notes, mcp__basic-memory__edit_note, Task
argument-hint: [create|status|implement|review] [spec-name]
allowed-tools: mcp__basic-memory__write_note, mcp__basic-memory__read_note, mcp__basic-memory__search_notes, mcp__basic-memory__edit_note
argument-hint: [create|status|show|review] [spec-name]
description: Manage specifications in our development process
---

## Context

You are managing specifications using our specification-driven development process defined in @docs/specs/SPEC-001.md.
Specifications are managed in the Basic Memory "specs" project. All specs live in a centralized location accessible across all repositories via MCP tools.

See SPEC-1 and SPEC-2 in the "specs" project for the full specification-driven development process.

Available commands:
- `create [name]` - Create new specification
- `status` - Show all spec statuses
- `implement [spec-name]` - Hand spec to appropriate agent
- `show [spec-name]` - Read a specific spec
- `review [spec-name]` - Review implementation against spec

## Your task

Execute the spec command: `/spec $ARGUMENTS`

### If command is "create":
1. Get next SPEC number by searching existing specs
2. Create new spec using template from @docs/specs/Slash\ Commands\ Reference.md
3. Place in `/specs` folder with title "SPEC-XXX: [name]"
1. Get next SPEC number by searching existing specs in "specs" project
2. Create new spec using template from SPEC-2
3. Use mcp__basic-memory__write_note with project="specs"
4. Include standard sections: Why, What, How, How to Evaluate

### If command is "status":
1. Search all notes in `/specs` folder
2. Display table with spec number, title, and status
3. Show any dependencies or assigned agents

### If command is "implement":
1. Read the specified spec
2. Determine appropriate agent based on content:
- Frontend/UI β†’ vue-developer
- Architecture/system β†’ system-architect
- Backend/API β†’ python-developer
3. Launch Task tool with appropriate agent and spec context
1. Use mcp__basic-memory__search_notes with project="specs"
2. Display table with spec number, title, and progress
3. Show completion status from checkboxes in content

### If command is "show":
1. Use mcp__basic-memory__read_note with project="specs"
2. Display the full spec content

### If command is "review":
1. Read the specified spec and its "How to Evaluate" section
Expand All @@ -49,7 +47,5 @@ Execute the spec command: `/spec $ARGUMENTS`
- **Architecture compliance** - Component isolation, state management patterns
- **Documentation completeness** - Implementation matches specification
3. Provide honest, accurate assessment - do not overstate completeness
4. Document findings and update spec with review results
4. Document findings and update spec with review results using mcp__basic-memory__edit_note
5. If gaps found, clearly identify what still needs to be implemented/tested

Use the agent definitions from @docs/specs/Agent\ Definitions.md for implementation handoffs.
28 changes: 28 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Basic Memory Environment Variables Example
# Copy this file to .env and customize as needed
# Note: .env files are gitignored and should never be committed

# ============================================================================
# PostgreSQL Test Database Configuration
# ============================================================================
# These variables allow you to override the default test database credentials
# Default values match docker-compose-postgres.yml for local development
#
# Only needed if you want to use different credentials or a remote test database
# By default, tests use: postgresql://basic_memory_user:dev_password@localhost:5433/basic_memory_test

# Full PostgreSQL test database URL (used by tests and migrations)
# POSTGRES_TEST_URL=postgresql+asyncpg://basic_memory_user:dev_password@localhost:5433/basic_memory_test

# Individual components (used by justfile postgres-reset command)
# POSTGRES_USER=basic_memory_user
# POSTGRES_TEST_DB=basic_memory_test

# ============================================================================
# Production Database Configuration
# ============================================================================
# For production use, set these in your deployment environment
# DO NOT use the test credentials above in production!

# BASIC_MEMORY_DATABASE_BACKEND=postgres # or "sqlite"
# BASIC_MEMORY_DATABASE_URL=postgresql+asyncpg://user:password@host:port/database
77 changes: 56 additions & 21 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,80 +13,115 @@
branches: [ "main" ]

jobs:
test:
test-sqlite:
name: Test SQLite (${{ matrix.os }}, Python ${{ matrix.python-version }})
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest]
python-version: [ "3.12", "3.13" ]
runs-on: ${{ matrix.os }}

# Postgres service (only available on Linux runners)
services:
postgres:
image: postgres:17
env:
POSTGRES_DB: basic_memory_test
POSTGRES_USER: basic_memory_user
POSTGRES_PASSWORD: dev_password
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5433:5432

steps:
- uses: actions/checkout@v4
with:
submodules: true

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'

- name: Install uv
run: |
pip install uv
- name: Install just (Linux/macOS)
if: runner.os != 'Windows'
run: |
curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to /usr/local/bin
- name: Install just (Windows)
if: runner.os == 'Windows'
run: |
# Install just using Chocolatey (pre-installed on GitHub Actions Windows runners)
choco install just --yes
shell: pwsh

- name: Create virtual env
run: |
uv venv
- name: Install dependencies
run: |
uv pip install -e .[dev]
- name: Run type checks
run: |
just typecheck
- name: Run linting
run: |
just lint
- name: Run tests (SQLite)
run: |
uv pip install pytest pytest-cov
just test
just test-sqlite
test-postgres:
Comment on lines 17 to 112

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium test

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}

Copilot Autofix

AI 3 days ago

The best way to fix this problem is to explicitly declare a permissions block at the root level of the workflow (line 2, immediately after name:), applying to all jobs by default. For most test workflows that do not require writing to the repo or interacting with PRs, the minimal permissions are contents: read. If some jobs require greater access, those jobs can declare their own permissions block as necessary. In this case, none of the shown jobs appear to require write access, so adding

permissions:
  contents: read

immediately after the name: Tests line is the simplest fix. No additional imports or package installations are needed.


Suggested changeset 1
.github/workflows/test.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -1,4 +1,6 @@
 name: Tests
+permissions:
+  contents: read
 
 on:
   push:
EOF
@@ -1,4 +1,6 @@
name: Tests
permissions:
contents: read

on:
push:
Copilot is powered by AI and may make mistakes. Always verify output.
name: Test Postgres (Python ${{ matrix.python-version }})
strategy:
fail-fast: false
matrix:
python-version: [ "3.12", "3.13" ]
runs-on: ubuntu-latest

# Postgres service (only available on Linux runners)
services:
postgres:
image: postgres:17
env:
POSTGRES_DB: basic_memory_test
POSTGRES_USER: basic_memory_user
POSTGRES_PASSWORD: dev_password
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5433:5432

steps:
- uses: actions/checkout@v4
with:
submodules: true

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'

- name: Install uv
run: |
pip install uv
- name: Install just
run: |
curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to /usr/local/bin
- name: Create virtual env
run: |
uv venv
- name: Install dependencies
run: |
uv pip install -e .[dev]
- name: Run tests (Postgres)
# Only run on Linux since Postgres service is only available there
if: runner.os == 'Linux'
run: |
just test-postgres
uv pip install pytest pytest-cov
just test-postgres

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium test

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}

Copilot Autofix

AI 3 days ago

To fix the problem, explicitly restrict GITHUB_TOKEN permissions by adding a permissions block at the top (root) level of the workflow. The minimal required permission is contents: read, which is enough for checking out code and running tests, and doesn't grant write privileges. This should be done above the jobs: key to apply to all jobs unless a specific job needs higher permissions. No further code or configuration changes are required.


Suggested changeset 1
.github/workflows/test.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -1,4 +1,6 @@
 name: Tests
+permissions:
+  contents: read
 
 on:
   push:
EOF
@@ -1,4 +1,6 @@
name: Tests
permissions:
contents: read

on:
push:
Copilot is powered by AI and may make mistakes. Always verify output.
51 changes: 51 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,57 @@ See the [Documentation](https://memory.basicmachines.co/) for more info, includi
- [Managing multiple Projects](https://docs.basicmemory.com/guides/cli-reference/#project)
- [Importing data from OpenAI/Claude Projects](https://docs.basicmemory.com/guides/cli-reference/#import)

## Development

### Running Tests

Basic Memory supports dual database backends (SQLite and Postgres). Tests are parametrized to run against both backends automatically.

**Quick Start:**
```bash
# Run SQLite tests (default, no Docker needed)
just test-sqlite

# Run Postgres tests (requires Docker)
just test-postgres
```

**Available Test Commands:**

- `just test-sqlite` - Run tests against SQLite only (fastest, no Docker needed)
- `just test-postgres` - Run tests against Postgres only (requires Docker)
- `just test-windows` - Run Windows-specific tests (auto-skips on other platforms)
- `just test-benchmark` - Run performance benchmark tests
- `just test-all` - Run all tests including Windows, Postgres, and benchmarks

**Postgres Testing Requirements:**

To run Postgres tests, you need to start the test database:
```bash
docker-compose -f docker-compose-postgres.yml up -d
```

Tests will connect to `localhost:5433/basic_memory_test`.

**Test Markers:**

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

**Other Development Commands:**
```bash
just install # Install with dev dependencies
just lint # Run linting checks
just typecheck # Run type checking
just format # Format code with ruff
just check # Run all quality checks
just migration "msg" # Create database migration
```

See the [justfile](justfile) for the complete list of development commands.

## License

AGPL-3.0
Expand Down
42 changes: 42 additions & 0 deletions docker-compose-postgres.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Docker Compose configuration for Basic Memory with PostgreSQL
# Use this for local development and testing with Postgres backend
#
# Usage:
# docker-compose -f docker-compose-postgres.yml up -d
# docker-compose -f docker-compose-postgres.yml down

services:
postgres:
image: postgres:17
container_name: basic-memory-postgres
environment:
# Local development/test credentials - NOT for production
# These values are referenced by tests and justfile commands
POSTGRES_DB: basic_memory
POSTGRES_USER: basic_memory_user
POSTGRES_PASSWORD: dev_password # Simple password for local testing only
ports:
- "5433:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U basic_memory_user -d basic_memory"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped

volumes:
# Named volume for Postgres data
postgres_data:
driver: local

# Named volume for persistent configuration
# Database will be stored in Postgres, not in this volume
basic-memory-config:
driver: local

# Network configuration (optional)
# networks:
# basic-memory-net:
# driver: bridge
72 changes: 67 additions & 5 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,78 @@ install:
@echo ""
@echo "πŸ’‘ Remember to activate the virtual environment by running: source .venv/bin/activate"

# Run all tests with unified coverage report
test: test-unit test-int

# Run unit tests only (fast, no coverage)
test-unit:
uv run pytest -p pytest_mock -v --no-cov -n auto tests
uv run pytest -p pytest_mock -v --no-cov tests

# Run integration tests only (fast, no coverage)
test-int:
uv run pytest -p pytest_mock -v --no-cov -n auto test-int

# Run all tests with unified coverage report
test: test-unit test-int
uv run pytest -p pytest_mock -v --no-cov test-int

# ==============================================================================
# DATABASE BACKEND TESTING
# ==============================================================================
# Basic Memory supports dual database backends (SQLite and Postgres).
# Tests are parametrized to run against both backends automatically.
#
# Quick Start:
# just test-sqlite # Run SQLite tests (default, no Docker needed)
# just test-postgres # Run Postgres tests (requires Docker)
#
# For Postgres tests, first start the database:
# docker-compose -f docker-compose-postgres.yml up -d
# ==============================================================================

# Run tests against SQLite only (default backend, skip Postgres/Benchmark tests)
# This is the fastest option and doesn't require any Docker setup.
# Use this for local development and quick feedback.
# Includes Windows-specific tests which will auto-skip on non-Windows platforms.
test-sqlite:
uv run pytest -p pytest_mock -v --no-cov -m "not postgres and not benchmark" tests test-int

# Run tests against Postgres only (requires docker-compose-postgres.yml up)
# First start Postgres: docker-compose -f docker-compose-postgres.yml up -d
# Tests will connect to localhost:5433/basic_memory_test
# To reset the database: just postgres-reset
test-postgres:
uv run pytest -p pytest_mock -v --no-cov -m "postgres and not benchmark" tests test-int

# Reset Postgres test database (drops and recreates schema)
# Useful when Alembic migration state gets out of sync during development
# Uses credentials from docker-compose-postgres.yml
postgres-reset:
docker exec basic-memory-postgres psql -U ${POSTGRES_USER:-basic_memory_user} -d ${POSTGRES_TEST_DB:-basic_memory_test} -c "DROP SCHEMA public CASCADE; CREATE SCHEMA public;"
@echo "βœ… Postgres test database reset"

# Run Alembic migrations manually against Postgres test database
# Useful for debugging migration issues
# Uses credentials from docker-compose-postgres.yml (can override with env vars)
postgres-migrate:
@cd src/basic_memory/alembic && \
BASIC_MEMORY_DATABASE_BACKEND=postgres \
BASIC_MEMORY_DATABASE_URL=${POSTGRES_TEST_URL:-postgresql://basic_memory_user:dev_password@localhost:5433/basic_memory_test} \
uv run alembic upgrade head
@echo "βœ… Migrations applied to Postgres test database"

# Run Windows-specific tests only (only works on Windows platform)
# These tests verify Windows-specific database optimizations (locking mode, NullPool)
# Will be skipped automatically on non-Windows platforms
test-windows:
uv run pytest -p pytest_mock -v --no-cov -m windows tests test-int

# Run benchmark tests only (performance testing)
# These are slow tests that measure sync performance with various file counts
# Excluded from default test runs to keep CI fast
test-benchmark:
uv run pytest -p pytest_mock -v --no-cov -m benchmark tests test-int

# Run all tests including Windows, Postgres, and Benchmarks (for CI/comprehensive testing)
# Use this before releasing to ensure everything works across all backends and platforms
test-all:
uv run pytest -p pytest_mock -v --no-cov tests test-int

# Generate HTML coverage report
coverage:
Expand Down
Loading
Loading