Skip to content

Latest commit

 

History

History
206 lines (151 loc) · 7.58 KB

File metadata and controls

206 lines (151 loc) · 7.58 KB

Local Development Setup

This guide walks you through setting up a working local instance of the LLM Memory Donation Study platform.

Prerequisites

1. Install and start PostgreSQL

On macOS (Homebrew):

brew install postgresql@17
brew services start postgresql@17

PostgreSQL 17 is a keg-only formula, so you must add its binaries to your PATH. Add this line to your shell profile (~/.zshrc or ~/.bashrc) and restart your terminal:

echo 'export PATH="/opt/homebrew/opt/postgresql@17/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc

Verify PostgreSQL is running:

pg_isready

You should see accepting connections. If not, run brew services start postgresql@17.

2. Clone and install dependencies

git clone <repo-url>
cd MemoryHole
uv sync --all-extras --group dev

This installs:

  • Core: Django, psycopg, django-htmx, spaCy
  • Dev tools: pytest, pytest-django, ruff, mypy, django-stubs
  • E2E testing: playwright

Running uv sync without flags installs only core dependencies.

3. Download the spaCy NER model

The platform uses spaCy to flag third-party names in memory entries. Download the medium English model:

uv run python -m spacy download en_core_web_md

If disk space is limited, en_core_web_sm works as a fallback (loaded automatically if en_core_web_md is unavailable), but detection quality is lower.

4. Create the PostgreSQL database

createdb memory_donation

The database connection is configured in memory_donation/settings.py and defaults to memory_donation on localhost with no password (peer/trust auth).

If you need to customize the connection or other settings, set environment variables before running Django commands:

Variable Default Description
DJANGO_SECRET_KEY Dev fallback provided Session/CSRF signing key
DJANGO_DEBUG True Debug mode
DJANGO_ALLOWED_HOSTS localhost,127.0.0.1 Comma-separated hostnames

5. Run migrations

uv run python manage.py migrate

This creates all 9 core tables: Study, Participant, PreDonationSurvey, MemoryUpload, MemoryEntry, AccuracyAnnotation, EditAction, PostReviewSurvey, and DonationConsent.

6. Create an active Study record

The platform requires at least one active Study in the database. You can create one directly from the command line:

uv run python manage.py shell -c "
from donation.models import Study
Study.objects.create(
    title='LLM Memory Donation Study',
    description='Understanding what LLM memory systems store about their users.',
    consent_form_version='1.0',
    is_active=True,
)
print('Study created.')
"

Or create it via the admin interface at /admin/donation/study/add/ (requires a superuser -- see below).

7. Start the development server

uv run python manage.py runserver

Open http://localhost:8000 in your browser. You should see the landing page.

Optional: Create a superuser (for admin access)

uv run python manage.py createsuperuser

Follow the prompts to set a username and password. The admin interface is at /admin/ and shows all models with filters and search.

Participant flow

The platform walks participants through a linear 10-stage flow:

  1. Landing (/) -- Study description, "Begin" button
  2. Consent (/consent/) -- Informed consent with 4 required checkboxes
  3. Pre-Survey (/survey/pre/) -- Provider usage, expectations, comfort scales, demographics
  4. Export Instructions (/instructions/) -- Tabbed instructions for Claude, ChatGPT, Gemini, Grok
  5. Upload (/upload/) -- Paste or upload memory export text
  6. Parsing Review (/review/) -- Confirm parsed entries look correct
  7. Annotation (/annotate/) -- Rate each entry for accuracy, category, source, sensitivity, surprise
  8. Editing (/edit/) -- Keep, edit, or redact entries before donation
  9. Post-Survey (/survey/post/) -- Comfort and behavioral intention measures (mirrors pre-survey)
  10. Final Review + Thank You (/final/, /complete/) -- Summary, consent tier selection, completion

Each stage is gated -- participants cannot skip ahead. Progress is tracked via session tokens (no login required).

Running tests

Unit tests (135 tests)

uv run python -m pytest tests/ -v

Covers models, views, middleware (stage gating), parser pipeline (all 4 providers + NER + classifier + sampler), and form validation.

Note: Use python -m pytest rather than calling pytest directly. The direct pytest entry point may not resolve correctly depending on your virtual environment configuration.

End-to-end walkthrough (Playwright)

The E2E script walks through the entire participant flow in a headless browser, takes screenshots at every stage, and reports errors.

# Install Playwright browsers (first time only)
uv run playwright install chromium

# Run with the dev server already running in another terminal
uv run python tests/e2e_walkthrough.py

Screenshots are saved to screenshots/. The script:

  • Fills out all forms with test data
  • Uploads the sample Claude export from fixtures/claude_export_sample.txt
  • Annotates all parsed entries
  • Tests redact and edit actions
  • Completes the full flow through the thank-you page

Troubleshooting

Problem Solution
createdb: command not found PostgreSQL bin is not on your PATH. Run export PATH="/opt/homebrew/opt/postgresql@17/bin:$PATH" or add it to your shell profile.
connection refused on database commands PostgreSQL is not running. Run brew services start postgresql@17 and verify with pg_isready.
uv run pytest fails with "No such file or directory" Use uv run python -m pytest instead.
VIRTUAL_ENV does not match warning Safe to ignore. This appears when another Python environment is active; uv run uses the project .venv regardless.
spaCy model not found Run uv run python -m spacy download en_core_web_md.

Project structure

MemoryHole/
├── memory_donation/          # Django project settings
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── donation/                 # Main app
│   ├── models.py             # 9 data models
│   ├── views.py              # All stage views
│   ├── urls.py               # URL routing
│   ├── forms.py              # Form classes
│   ├── middleware.py          # StageGateMixin, session helpers
│   ├── admin.py              # Admin registration
│   ├── parsers/              # Memory export parsing pipeline
│   │   ├── detector.py       # Provider auto-detection
│   │   ├── claude.py         # Claude adapter
│   │   ├── chatgpt.py        # ChatGPT adapter
│   │   ├── gemini.py         # Gemini adapter
│   │   ├── grok.py           # Grok adapter
│   │   ├── generic.py        # Fallback line-by-line parser
│   │   ├── ner.py            # spaCy NER for third-party PII
│   │   ├── classifier.py     # Rule-based category classifier
│   │   ├── sampler.py        # Stratified sampling (>50 entries)
│   │   └── pipeline.py       # Orchestrates full pipeline
│   └── templates/donation/   # Django templates (HTMX + Alpine.js)
├── tests/                    # pytest unit tests + E2E script
├── fixtures/                 # Sample exports and attention checks
└── pyproject.toml            # Dependencies and tool config