-
Notifications
You must be signed in to change notification settings - Fork 0
Development Guide
- Fork the repository -- Create your own fork on GitHub.
-
Create a feature branch -- Branch from
mainwith a descriptive name (e.g.,feature/add-new-watcher-typeorfix/energy-decay-bug). - Make changes -- Follow the code style conventions described below.
- Run linting and tests -- Ensure all checks pass before submitting.
-
Submit a pull request -- Open a PR against
mainwith a clear description of your changes.
pytest with asyncio_mode = "auto". All async test functions are automatically detected and run with an event loop.
# Fast tests (no API calls, ~4 seconds)
uv run pytest tests/ -x -m "not slow and not integration"
# Full suite
uv run pytest tests/ -x
# With coverage (target: 80%+)
uv run pytest tests/ --cov=colloquip --cov-report=term-missing
# Run a specific test file
uv run pytest tests/test_energy.py -x
# Run a specific test by name
uv run pytest tests/ -x -k "test_energy_decay"-
@pytest.mark.slow-- Tests that make real LLM API calls. Skipped in fast runs. -
@pytest.mark.integration-- Full deliberation loop tests. Skipped in fast runs.
707 tests across 37 files, organized as follows:
- Unit tests -- Energy calculator, trigger evaluator, observer agent, agent prompts, config loading, Pydantic models
- API tests -- All REST endpoints, SSE streaming, WebSocket connections, error handling and validation
- Database tests -- ORM models, repository pattern, migration integrity
- Behavioral tests -- Emergent properties, cross-domain connections, red-team activation patterns
- Integration tests -- Full deliberation loops with mock LLM from start to synthesis
- Platform tests -- Communities, agent recruitment, institutional memory, watchers, feedback and calibration
- Infrastructure tests -- Docker health checks, logging configuration, Prometheus metrics
Shared test factories are defined in tests/conftest.py:
-
create_post()-- Factory for building test posts with configurable stance, content, and metadata -
create_session()-- Factory for test deliberation sessions -
create_agent_config()-- Factory for agent configurations with persona, mandates, and keywords -
create_metrics()-- Factory for conversation metrics (novelty, disagreement, questions, staleness)
-
MockLLM-- Returns deterministic, structured responses for testing. Supports all the same interfaces as the real Anthropic provider. -
MockEmbedding-- Returns zero vectors for testing. Allows memory and similarity features to function without an API key.
# Check for lint issues
uv run ruff check .
# Check formatting
uv run ruff format --check .
# Auto-fix lint issues and format
uv run ruff check --fix . && uv run ruff format .Ruff configuration (from pyproject.toml):
- Line length: 100 characters
- Target version: Python 3.11+
- Enabled rules: E (pycodestyle errors), F (pyflakes), I (isort)
- Ignored: E402 -- module-level imports after
load_dotenv()calls are intentional
cd web && npm run lintLocated at scripts/pre-commit, the hook runs three checks before each commit:
-
ruff check-- Lint check -
ruff format --check-- Format check - Fast unit tests (
pytest -m "not slow and not integration")
./scripts/install-hooks.shThis symlinks the pre-commit script into .git/hooks/. All three checks must pass for the commit to proceed.
- Add the route handler in the appropriate
src/colloquip/api/*_routes.pyfile. - If this is a new router module, register it in
src/colloquip/api/__init__.py. - Add the corresponding API function in
web/src/lib/api.ts. - Write tests in
tests/.
- Define the SQLAlchemy model in
src/colloquip/db/tables.py. - Create an Alembic migration:
uv run alembic revision --autogenerate -m "description". - Add repository methods in
src/colloquip/db/repository.py. - Add a Pydantic model in
src/colloquip/models.pyif needed for API serialization.
- Define the persona configuration in
src/colloquip/agents/with a full prompt, phase mandates, and domain keywords. - Each agent requires:
agent_id,display_name,persona_prompt,phase_mandates,domain_keywords,knowledge_scope. - Register the agent in the agent pool / persona loader.
- Implement the
BaseWatcherinterface insrc/colloquip/watchers/. - Register the new type in
WatcherManager. - Add a DB model if persistent state is needed.
- Add API routes in
watcher_routes.py.
GitHub Actions workflows are defined in .github/workflows/:
Triggered on pushes to main and claude/* branches, and on pull requests targeting main.
-
lint-- Runsruff checkandruff format --check. -
test-unit-- Runs pytest across a Python 3.11 / 3.12 matrix with coverage reporting. -
test-integration-- Runs full deliberation loop tests. Depends on unit tests passing first.
Triggered on tags matching v* (e.g., v1.0.0).
- Runs the full test suite.
- Builds the Docker image (multi-stage).
- Pushes to GitHub Container Registry (GHCR).
Triggered on pull requests that touch db/ or alembic/ files.
- Validates that all migrations apply cleanly against a fresh database.
# Build and run with development overrides
docker compose -f docker-compose.yml -f docker-compose.dev.yml up
# With monitoring (Prometheus on :9090, Grafana on :3000)
docker compose -f docker-compose.yml -f docker-compose.monitoring.yml up -dThe development compose override provides:
-
Source volume mounts --
src/,tests/,config/,web/, andalembic/are mounted into the container so changes are reflected without rebuilding. -
Mock providers -- Uses
EMBEDDING_PROVIDER=mockandMEMORY_STORE=in_memoryfor fast iteration without external API keys. - Debug port -- Port 5678 is exposed for debugpy attachment.
- Exposed service ports -- PostgreSQL (5432) and Redis (6379) are accessible from the host for direct inspection.
| Service | Image | Ports | Purpose |
|---|---|---|---|
app |
Custom (multi-stage) | 8000 | FastAPI + static SPA |
postgres |
pgvector/pgvector:pg16 | 5432 (dev only) | Database with vector extension |
redis |
redis:7-alpine | 6379 (dev only) | Watcher job queue |
prometheus |
prom/prometheus (monitoring) | 9090 | Metrics collection |
grafana |
grafana/grafana (monitoring) | 3000 | Dashboards |
Copy .env.example to .env and configure as needed:
cp .env.example .envDocker Compose reads .env automatically. For mock mode (no API keys needed), the defaults work out of the box.
| Variable | Default | Description |
|---|---|---|
ANTHROPIC_API_KEY |
-- | Required for real LLM mode |
OPENAI_API_KEY |
-- | Required for OpenAI embeddings |
DB_PASSWORD |
colloquip |
PostgreSQL password |
EMBEDDING_PROVIDER |
mock |
mock or openai
|
MEMORY_STORE |
in_memory |
in_memory or pgvector
|
LOG_LEVEL |
INFO |
Standard Python log levels |
- Line length: 100 characters.
- Target version: Python 3.11+.
-
Async throughout: All DB operations, LLM calls, and API handlers are async. Use
awaitconsistently; do not mix sync and async database access. - Type hints: Use Pydantic models for structured data and type annotations on all function signatures.
-
Repository pattern: All database access goes through
SessionRepository. Never query tables directly in route handlers or services. - Interface pattern: Abstract base classes define contracts for LLM, Embedding, Tool, and Watcher implementations. Add new providers by implementing the appropriate ABC.
- Import order: Managed by ruff's isort rules (stdlib, third-party, local).
-
Strict mode: Enabled with strict null checks. Do not use
anyunless absolutely necessary. -
Path alias:
@/maps toweb/src/. Use this for all imports within the frontend codebase. -
Component pattern: Three layers -- Radix UI primitive, Tailwind + CVA styled wrapper (in
components/ui/), then domain-specific component. - State management: Zustand for client-side state (with persist middleware for theme, sidebar). TanStack React Query for all server state.
-
Styling: Tailwind CSS utility classes exclusively. CSS custom properties in
app.cssdrive the three-theme system (dark, light, pastel). -
Class merging: Use the
cn()utility (clsx + tailwind-merge) for conditional class composition. -
Route file:
web/src/routeTree.gen.tsis auto-generated by TanStack Router. Do not edit it manually.
- Group components by domain:
deliberation/,communities/,threads/,agents/,memories/. - Shared and reusable components belong in
components/shared/orcomponents/ui/. - All API call functions are centralized in
web/src/lib/api.ts. - Query keys are centralized in
web/src/lib/queryKeys.ts. - TypeScript type definitions live in
web/src/types/.
Getting Started
Concepts
Deep Dives
Reference