diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..a208d84 --- /dev/null +++ b/.env.example @@ -0,0 +1,86 @@ +# PromptPipe environment configuration +# Copy this file to .env and edit as needed: +# cp .env.example .env +# +# Precedence: CLI flags > environment variables (.env) > defaults +# See docs/configuration.md for the full reference. + +# --- Core --- + +# Base directory for SQLite files, debug logs, and lock file. +# Default: /var/lib/promptpipe +# PROMPTPIPE_STATE_DIR=/var/lib/promptpipe + +# HTTP server listen address. +# Default: :8080 +# API_ADDR=:8080 + +# --- Database --- + +# Application database DSN (SQLite or PostgreSQL). +# Default: file:{STATE_DIR}/state.db?_foreign_keys=on +# DATABASE_DSN=file:/var/lib/promptpipe/state.db?_foreign_keys=on +# DATABASE_DSN=postgres://user:pass@localhost:5432/promptpipe?sslmode=disable + +# Legacy fallback for DATABASE_DSN (used only when DATABASE_DSN is unset). +# DATABASE_URL= + +# WhatsApp/whatsmeow session database DSN. +# Default: file:{STATE_DIR}/whatsmeow.db?_foreign_keys=on +# WHATSAPP_DB_DSN=file:/var/lib/promptpipe/whatsmeow.db?_foreign_keys=on + +# --- GenAI (OpenAI) --- + +# Required for conversation flow and genai prompts. +# OPENAI_API_KEY= + +# OpenAI model name. +# Default: gpt-4o-mini +# GENAI_MODEL=gpt-4o-mini + +# OpenAI temperature (0.0–1.0). Lower = more consistent. +# Default: 0.1 +# GENAI_TEMPERATURE=0.1 + +# --- Scheduling --- + +# Default cron string for /schedule when no schedule object is provided. +# Five-field format: minute hour day month weekday +# DEFAULT_SCHEDULE= + +# Minutes before scheduled habit time to send preparation message. +# Default: 10 +# SCHEDULER_PREP_TIME_MINUTES=10 + +# --- Conversation flow --- + +# System prompt file paths. +# INTAKE_BOT_PROMPT_FILE=prompts/intake_bot_system.txt +# PROMPT_GENERATOR_PROMPT_FILE=prompts/prompt_generator_system.txt +# FEEDBACK_TRACKER_PROMPT_FILE=prompts/feedback_tracker_system.txt + +# Number of history messages sent to bot tools (-1=unlimited, 0=none). +# Default: -1 +# CHAT_HISTORY_LIMIT=-1 + +# Timeout for initial feedback response (e.g. "15m"). +# Default: 15m +# FEEDBACK_INITIAL_TIMEOUT=15m + +# Delay before follow-up feedback session (e.g. "3h"). +# Default: 3h +# FEEDBACK_FOLLOWUP_DELAY=3h + +# Auto-enter feedback mode after scheduled prompt inactivity. +# Default: true +# AUTO_FEEDBACK_AFTER_PROMPT_ENABLED=true + +# Auto-enroll unknown phone numbers on first message. +# Default: false +# AUTO_ENROLL_NEW_USERS=false + +# --- Debug --- + +# Enable debug messages and GenAI call logging. +# Default: false +# PROMPTPIPE_DEBUG=false diff --git a/.jules/atlas.md b/.jules/atlas.md new file mode 100644 index 0000000..3449938 --- /dev/null +++ b/.jules/atlas.md @@ -0,0 +1,5 @@ +## 2026-02-27 - Env var drift is the #1 documentation risk + +**Learning:** All 19 environment variables in `cmd/PromptPipe/main.go` were already correctly documented in `docs/configuration.md`, but there was no `.env.example` and no automated check to prevent future drift. Env vars are added via `os.Getenv`, `ParseBoolEnv`, `ParseIntEnv`, `ParseFloatEnv`, and `GetEnvWithDefault` — all easily grep-able. + +**Action:** Always run `make check-docs` (or `scripts/check-env-docs.sh`) after adding new env vars. The script extracts var names from main.go and verifies they appear in both `.env.example` and `docs/configuration.md`. diff --git a/Makefile b/Makefile index c8e6c04..38ee2cf 100644 --- a/Makefile +++ b/Makefile @@ -9,4 +9,7 @@ test-postgres: @echo "Run with: POSTGRES_DSN_TEST='postgres://user:pass@host:5432/dbname?sslmode=disable' make test-postgres" POSTGRES_DSN_TEST="$${POSTGRES_DSN_TEST}" go test ./internal/store/... -v -count=1 -.PHONY: build test test-postgres +check-docs: + @bash scripts/check-env-docs.sh + +.PHONY: build test test-postgres check-docs diff --git a/docs/configuration.md b/docs/configuration.md index 2c478bb..79c68f6 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -6,6 +6,8 @@ PromptPipe loads configuration from environment variables and command-line flags 2. `../.env` 3. `../../.env` +A ready-to-use template is available at [`.env.example`](../.env.example). Copy it to `.env` and uncomment the variables you need. + ## Precedence 1. **CLI flags** diff --git a/docs/development.md b/docs/development.md index cae1e87..9c5a105 100644 --- a/docs/development.md +++ b/docs/development.md @@ -4,6 +4,7 @@ - Go **1.24.3+** (see `go.mod`) - Make (optional) +- Docker & Docker Compose (optional, for running with PostgreSQL) ## Build @@ -16,14 +17,69 @@ go build -o build/promptpipe cmd/PromptPipe/main.go ## Test ```bash +make test +# or go test ./... +``` + +Additional checks: + +```bash go vet ./... +gofmt -d . +``` + +To run tests against PostgreSQL (requires a running Postgres instance): + +```bash +POSTGRES_DSN_TEST='postgres://user:pass@localhost:5432/dbname?sslmode=disable' make test-postgres +``` + +## Configure + +Copy the example environment file and edit it: + +```bash +cp .env.example .env ``` +At minimum, set `OPENAI_API_KEY` if you want GenAI / conversation features. +See [`.env.example`](../.env.example) for all available variables and their defaults, or +[Configuration](configuration.md) for the full reference. + +PromptPipe searches for `.env` files in `./.env`, `../.env`, and `../../.env` (first match wins). + ## Run locally +### Standalone (SQLite) + ```bash ./build/promptpipe ``` -The server loads `.env` files from the repository root or parent directories if present (see [Configuration](configuration.md)). +The API listens on `:8080` by default. Verify with: + +```bash +curl http://localhost:8080/health +``` + +### With Docker Compose (PostgreSQL) + +The repository includes a `docker-compose.yml` that starts PromptPipe alongside PostgreSQL 16: + +```bash +docker compose up -d +``` + +This exposes the API on the host port defined by `API_PORT` (default `8080`). +To tear down while keeping data: `docker compose down`. +To also remove volumes: `docker compose down -v`. + +## Verify documentation + +A drift-check script ensures `.env.example` and `docs/configuration.md` stay in sync with the +environment variables actually read in `cmd/PromptPipe/main.go`: + +```bash +make check-docs +``` diff --git a/scripts/check-env-docs.sh b/scripts/check-env-docs.sh new file mode 100755 index 0000000..0b975cc --- /dev/null +++ b/scripts/check-env-docs.sh @@ -0,0 +1,51 @@ +#!/usr/bin/env bash +# check-env-docs.sh — verify that every environment variable read in +# cmd/PromptPipe/main.go is documented in .env.example and docs/configuration.md. +# +# Usage: ./scripts/check-env-docs.sh (run from repo root) +# make check-docs (via Makefile target) +# +# Exit code 0 = all env vars are documented. Non-zero = drift detected. + +set -euo pipefail + +REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +MAIN_GO="$REPO_ROOT/cmd/PromptPipe/main.go" +ENV_EXAMPLE="$REPO_ROOT/.env.example" +CONFIG_DOC="$REPO_ROOT/docs/configuration.md" + +errors=0 + +# Extract environment variable names from main.go. +# Matches os.Getenv("VAR"), ParseBoolEnv("VAR", ...), ParseIntEnv("VAR", ...), +# ParseFloatEnv("VAR", ...), and GetEnvWithDefault("VAR", ...). +env_vars=$(grep -oP '(?:os\.Getenv|ParseBoolEnv|ParseIntEnv|ParseFloatEnv|GetEnvWithDefault)\(\s*"([A-Z_]+)"' "$MAIN_GO" \ + | grep -oP '"[A-Z_]+"' \ + | tr -d '"' \ + | sort -u) + +echo "Env vars found in $MAIN_GO:" +echo "$env_vars" +echo "" + +for var in $env_vars; do + # Check .env.example + if ! grep -q "$var" "$ENV_EXAMPLE" 2>/dev/null; then + echo "DRIFT: $var is used in main.go but missing from .env.example" + errors=$((errors + 1)) + fi + # Check docs/configuration.md + if ! grep -q "$var" "$CONFIG_DOC" 2>/dev/null; then + echo "DRIFT: $var is used in main.go but missing from docs/configuration.md" + errors=$((errors + 1)) + fi +done + +if [ "$errors" -gt 0 ]; then + echo "" + echo "❌ Found $errors documentation drift issue(s)." + echo " Update .env.example and/or docs/configuration.md to match main.go." + exit 1 +fi + +echo "✅ All environment variables are documented."